> This page is part of the [Customer.io documentation](https://docs-customerio.netlify.app). For the complete index, see [llms.txt](https://docs-customerio.netlify.app/llms.txt).
> Last updated: June 8, 2026

# Respond to inbound keywords

When people send you SMS messages, you can use campaigns to handle the incoming messages and trigger responses.

## How it works[](#how-it-works)

We treat inbound messages like events in Customer.io: they can trigger [campaignsCampaigns are automated workflows you set up to send people messages and perform other actions when they meet your criteria.](/journeys/send/campaigns/overview/) and add people to [segmentsA segment is a group of people in your workspace. Use segments to trigger campaigns, track membership over time, or fine-tune your audience. There are two types of segments: data-driven and manual. Data-driven segments automatically update when people start or stop matching criteria. Manual segments are static.](/journeys/segmentation/segments/).

We handle inbound messages by looking for keywords. Think of it a bit like the menu you hear when you call somewhere that has an automated phone system: the phone system prompts the user to press an option on the keypad to advance to the next message.

Except in this case, rather than pressing the right button to advance in a menu, the user responds with a keyword from a list of supported keywords, and you send them down a path based on the keyword they used.

## Set up an inbound message campaign[](#set-up-an-inbound-message-campaign)

1.  When you set up a campaign, click the **Trigger**.
2.  Select the **Event** trigger option.
3.  Change *they perform the event* to **they send an inbound SMS**.

 Don’t use this process for reserved keywords

Words like `STOP`, `START`, `UNSTOP`, `HELP`, or `INFO` are processed by carriers and Customer.io’s built-in SMS compliance flows and won’t trigger your campaigns the way you expect. Rather than looking for [reserved keywords](#keywords) like `STOP` or `START`, you should base your campaign logic on the downstream effects of these keywords instead—like watching for changes to opt-in or opt-out status.

[![Inbound SMS campaign trigger](https://docs.customer.io/images/inbound-sms-trigger-1.png)](#9d3bd218008be604c0c636d63acb4906-lightbox)

The *Inbound message event* that triggers your campaign doesn’t differentiate between replies to different phone numbers. If you want to handle inbound replies to your different sender numbers independently, you should add conditions to your trigger based on the `to` value. (Inbound messages come `from` your audience and `to` your SMS “sender” number.)

[![Inbound SMS campaign trigger with a filter for a sender number](https://docs.customer.io/images/inbound-sms-trigger.png)](#505cc7ba9faddfc8379c18819056bacd-lightbox)

### Using inbound message data[](#using-inbound-message-data)

Like other event-triggered campaigns, inbound message variables start with `event`. For example, referencing the `keyword` variable would be `{{event.keyword}}`.

Most of these values come directly from the inbound message, but there are rules to the `keyword` variable.

```json
{
    "body": "join",
    "from": "+15551234567",
    "keyword": "JOIN",
    "messaging_service_sid": "MG1c4d997a947f60dfaddf382a32dffc11",
    "sid": "SMec32f5db600322613b0c592d4d7417f1",
    "to": "+15559876543"
}
```

Variable

Description

`body`

The body of the inbound message

`from`

The phone number of the person who sent the inbound message

`keyword`

The keyword that the person used, if we can parse it from the body of the inbound message

`messaging_service_sid`

The Twilio messaging service SID that the inbound message came from

`sid`

Twilio’s unique ID for the inbound message

`to`

The phone number that the inbound message was sent to, also the “sender” of the message the person replied to

### Keywords[](#keywords)

When we parse an inbound message, we normalize recognized terms into keyword values that you can use in campaign conditions. This works if the inbound message contains a single keyword.

If an inbound message contains multiple words, the `keyword` variable will be empty. If this happens, you can respond with a message that tells the user to try again with one of the supported keywords.

We have a set of reserved keywords that carriers and Customer.io handle automatically. You can also set up campaigns to handle [custom keywords](#custom-keywords), so you can respond to people when they use terms specific to your business.

#### Reserved keywords[](#reserved-keywords)

Carriers (like Twilio) and Customer.io handle these keywords automatically as a matter of compliance.

Keyword

Supported terms

Description

STOP

STOP, CANCEL, UNSUBSCRIBE, OPTOUT, END, QUIT, REVOKE, STOPALL

Opt-out keywords that unsubscribe the user from SMS messages

START

START, UNSTOP

Opt-in keywords that resubscribe the user to SMS messages

HELP

HELP, INFO

Keywords that trigger help or information responses

Because we process these keywords automatically outside of campaign workflows, you shouldn’t use them as campaign triggers or branch conditions because they might not trigger your campaign (or other conditions) as expected.

If you want to listen for reserved keywords, you should base your campaign logic on the downstream effects of these keywords instead—like changes to opt-in or opt-out status rather than the `START` or `STOP` keywords themselves.

See [Opt-out keyword handling](/journeys/channels/sms/keyword-opt-out/) to understand how Customer.io handles SMS opt-outs.

#### Custom keywords[](#custom-keywords)

Beyond the [default keywords above](#keywords), you can also tell people to respond with custom keywords like `JOIN`, `PROMO`, `SURVEY`, or `DETAILS`. For example, if you want to run a survey, you could ask people to respond 1-5 to indicate satisfaction. If you want people to join a list, you could ask them to reply `JOIN`.

## Example campaign and best practices[](#example-campaign-and-best-practices)

In a custom keyword campaign, use a multi-split branch to route people based on non-reserved keywords. For example, you might branch on `JOIN`, `PROMO`, `SURVEY`, or `DETAILS`, then add an “all others” branch for replies you don’t recognize.

Don’t branch on reserved keywords like `STOP`, `START`, `UNSTOP`, `HELP`, or `INFO`. For opt-out targeting, use [SMS opt-out segments](/journeys/channels/sms/keyword-opt-out/#segment-users-by-sms-opt-out-status) instead of campaign branches.

### Filter by sender number or outbound message[](#filter-by-sender-number-or-outbound-message)

If you want to handle keywords differently based on the sender number or a specific message, you can add that as a *Filter* to your campaign trigger.

[![Inbound SMS campaign trigger with a filter for a sender number](https://docs.customer.io/images/inbound-sms-trigger.png)](#505cc7ba9faddfc8379c18819056bacd-lightbox)

### Set up branches to handle different keywords[](#set-up-branches-to-handle-different-keywords)

Set up branches for the custom keywords your message asks people to send. Add an “all others” branch to respond when the reply doesn’t match a supported keyword.

[![Inbound SMS campaign branches](https://docs.customer.io/images/inbound-sms-branches.png)](#3c2654fae716a778335f69501371fe71-lightbox)

Remember not to branch on reserved keywords like `STOP`, `START`, `UNSTOP`, `HELP`, or `INFO`. See [Reserved keywords](#reserved-keywords) for more information. For opt-out targeting, use [SMS opt-out segments](/journeys/channels/sms/keyword-opt-out/#segment-users-by-sms-opt-out-status) instead of listening for reserved keywords.

### You cannot wait for subsequent messages in your campaign[](#no-wait-until)

In your campaign, you can’t wait for another inbound message or a follow-up event. You have to handle cascading inbound messages with subsequent campaigns.

You can still use the *Wait Until* action to wait for other conditions, but you cannot currently wait for a separate inbound message to continue through a campaign.

## When to limit send rates[](#when-to-limit-send-rates)

If you want to send an SMS broadcast or newsletter, and you want to respond to inbound messages on the same “sender” number in Customer.io, you should throttle your broadcast so that your inbound-based responses aren’t delayed by messages queued from your broadcast.

Imagine you send a broadcast to 100,000 people. SMS messages from a single phone number send at a maximum rate of 225 messages per second. This would take around 444 seconds to send, or around 7 minutes. If someone receives your message and responds immediately, and any subsequent message you try to send is added to the end of the queue. This means that any subsequent messages you send to your audience are be delayed by the time it takes to finish sending your broadcast.

Throttling broadcasts and newsletters ensures that your sender phone number can continue to send messages as it normally would, without being blocked by messages queued from your broadcast.

 You can’t limit campaign send rates this way

When you start campaigns triggered by segments or attribute changes, you can let people who already meet your conditions enter the campaign immediately. If you choose this option, you can’t limit the send rate from, or the number of people who enter, your campaign. This could cause a queue of SMS messages that delays other campaigns or broadcasts that rely on the same sender numbers.