Two-Way Messaging Keywords, Channel Support, and Endpoints

This page documents the fixed facts of two-way messaging: the default keyword set and matching rules, per-channel feature support, SMS provider limitations, and the conversation history endpoints. For how the inbound pipeline works and why it behaves this way, see Two-Way Conversations. For webhook handler code, see Receiving Inbound Messages.


Default Keywords

Sent seeds ten default keywords for every account, implementing CTIA/TCPA keyword handling:

KeywordAction
STOPOpts the contact out
CANCELOpts the contact out
UNSUBSCRIBEOpts the contact out
QUITOpts the contact out
ENDOpts the contact out
STARTOpts the contact back in
UNSTOPOpts the contact back in
SUBSCRIBEOpts the contact back in
HELPSends the configured help auto-reply
INFOSends the configured help auto-reply

Opt-out flips the opt_out flag on the contact record; the flag is contact-level and channel-agnostic, so a keyword received on any channel suppresses the contact on all channels.

Matching Rules

  • The entire trimmed message body must equal a keyword. "STOP" matches; "Please stop messaging me" does not.
  • Case is ignored: stop, Stop, and STOP all match.
  • Partial phrases, sentences, and free-form opt-out requests never match.
  • Matching runs against your full keyword list (defaults plus custom keywords) on every inbound message on a two-way capable channel.

Custom Keywords

Custom keywords are managed in the dashboard under Compliance → Opt Keywords. Each keyword carries one of three actions: Opt Out, Opt In, or Help. Custom keywords follow the same exact-match rules as the defaults, and must be a single exact token, not a sentence. Default keywords are seeded automatically for every account and remain active alongside any custom keywords you add.

RCS STOP Chip

Sent appends a STOP suggestion chip to every outbound RCS message.

  • Taps on the built-in STOP chip carry opt-out postback data. The consent engine processes the postback directly and sets the contact's opt_out flag; keyword matching is not involved.
  • Chip taps are delivered to your webhook as message.received events with the chip's reply text in payload.text. There is no separate event type for chip taps.
  • Typed RCS replies go through standard keyword matching.

Channel Support

FeatureSMSRCSWhatsApp
Inbound stored as RECEIVEDYes*YesYes
Reply from same sender routingYes*YesYes
Keyword detection (STOP/START/HELP)Yes*YesYes
Auto-replyYes*YesYes (free-form text within the 24-hour window)
Opt-out engineYes*YesYes

* SMS requires an MO-capable provider and a number type with an inbound path; see SMS Provider Support.

WhatsApp auto-replies are delivered as free-form session text inside the 24-hour conversation window, and the configured STOP/START/HELP template must be approved for the reply to send.

SMS Provider Support

ConfigurationTwo-way support
Long codes and short codes on a route with an inbound (MO) pathSupported
Alphanumeric sender IDsNot supported. Send-only; contacts cannot reply, and any attempt is dropped at the carrier level
SMPP connections without an inbound pathNot supported. Delivery receipts only; no inbound path

On an alphanumeric sender ID or an SMPP provider, inbound keywords (STOP, START, HELP) never reach Sent and are not processed.


Conversation History Endpoints

Two account-scoped endpoints return message history. Both return the standard v3 envelope with a data.messages array and a data.pagination object; see Data Models for the envelope and pagination shapes.

List Conversation Messages

GET /v3/conversations?page=1&page_size=20

Returns a paginated list of your messages across all conversations, ordered by created date, most recent first.

ParameterInTypeRequiredDescription
pagequeryintegerYesPage number. Must be greater than 0.
page_sizequeryintegerYesResults per page. Must be between 1 and 100.
x-profile-idheaderstring (UUID)NoScopes the request to a child profile. Organization API keys only.

List Messages for a Conversation

GET /v3/conversations/{id}?page=1&page_size=20

Returns a paginated list of the messages in a single conversation, ordered by created date, most recent first. Accepts the same page, page_size, and x-profile-id parameters.

ParameterInTypeRequiredDescription
idpathstring (UUID)YesThe conversation id. See Conversation IDs.
pagequeryintegerYesPage number. Must be greater than 0.
page_sizequeryintegerYesResults per page. Must be between 1 and 100.
x-profile-idheaderstring (UUID)NoScopes the request to a child profile. Organization API keys only.
{
  "success": true,
  "data": {
    "messages": [
      {
        "id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
        "customer_id": "41681f0a-15b4-45ab-afca-d9af35b4d3a1",
        "contact_id": "14b278db-6db8-448f-a5db-8d6ce46a3451",
        "phone": "+1234567890",
        "phone_international": "+1 234-567-890",
        "region_code": "US",
        "template_id": null,
        "template_name": null,
        "template_category": null,
        "channel": "sms",
        "message_body": null,
        "status": "DELIVERED",
        "direction": "OUTBOUND",
        "created_at": "2026-07-24T15:20:20.4343024+00:00",
        "price": 0.0075,
        "active_contact_price": 0.0,
        "events": null
      }
    ],
    "pagination": {
      "page": 1,
      "page_size": 20,
      "total_count": 1,
      "total_pages": 1,
      "has_more": false,
      "cursors": null
    }
  },
  "error": null,
  "meta": {
    "request_id": "req_7X9zKp2jDw",
    "timestamp": "2026-07-24T15:25:20.4359817+00:00",
    "version": "v3"
  }
}

Message Fields

FieldTypeDescription
idstring (UUID)Message id
customer_idstring (UUID)Your account's customer id
contact_idstring (UUID)The contact the message was exchanged with
phonestringContact number in E.164 format
phone_internationalstringContact number in international display format
region_codestringTwo-letter region code of the contact number
template_idstring (UUID) | nullTemplate used for the message, when one was used
template_namestring | nullName of the template used
template_categorystring | nullCategory of the template used
channelstringsms, whatsapp, or rcs
message_bodyobject | nullMessage body content
statusstringMessage status, for example DELIVERED or RECEIVED
directionstringOUTBOUND or INBOUND
created_atstringISO 8601 creation timestamp
pricenumber | nullProvider cost for the message
active_contact_pricenumber | nullActive-contact price component
eventsarray | nullAlways null on the conversation endpoints; per-message status history is served by message activities

Errors

CodeMeaningCondition
400Invalid request parameterspage is less than 1, or page_size is outside 1–100
401UnauthorizedMissing or invalid API key

Conversation IDs

A conversation id is a deterministic RFC 4122 v5 UUID computed from your account's customer id and the contact id. It identifies one continuous thread between your account and a contact across every channel; it does not depend on the sender number or channel.

InputValue
Namespace9f4e6a2c-0b1d-4c3e-8a5f-2d7e6c1b0a99
Name{customer_id}:{contact_id}, lowercase canonical UUIDs, customer id first
AlgorithmSHA-1 name-based UUID (version 5), equivalent to PostgreSQL's uuid_generate_v5(namespace, name)

The same pair always yields the same id, so you can compute a conversation id from the customer_id and contact_id fields of any message without an extra lookup. The API does not return conversation ids as a separate field.

On this page