Skip to main content

Keyword auto-reply worked examples

The Auto-Reply Rules guide covers the rule form: fields, match types, scope. This page goes the other direction — concrete scenarios with the exact request, the match outcome to expect, and where the evidence lands afterward. Work through them against your own workspace before you ship a keyword program to customers. Prerequisites: an API key (live keys are prefixed dv_live_sk_), and at least one number on SMS (or your chosen channel) that can receive inbound replies.

1. Exact, contains, and starts-with with expected results

Matching is never case-sensitive, and Exact and Starts-with trim leading and trailing whitespace before comparing. The table below assumes four active rules on the sms channel, created in the order listed: Create any of these over the API to follow along:
Response — 201

2. An inbound text, one fired rule, end to end

A customer texts in; the reply goes out asynchronously. Here is the sequence with the evidence to expect at each step:
  1. The inbound arrives. The customer sends hours to your SMS number from their handset.
  2. The platform matches it. The body trims and case-folds to HOURS, which satisfies the exact rule above. Since this rule is the first — and only — match, its action executes.
  3. The reply is sent. The response text goes out through the same billed outbound pipeline as any send. A plain body like the example is delivered verbatim; you can also reference the matched keyword or the sender’s number with tokens, e.g. "Thanks for asking about {{extra.keyword}} — we will text {{contact.phone}} during opening hours." The {{extra.from}} and {{extra.to}} tokens carry the sender and the receiving number when you need them raw.
  4. Confirm in the dashboard. The inbound appears in the Inbox conversation for that contact; the reply appears in the same thread, and as an outbound row across Messages → Tools → Delivery log. Because the log’s filters map one-to-one onto the messages API, the API equivalent of the lookup is:
Response — 200 (inbound and reply share the customer’s number on from/to in opposite directions):
The reply rows a rule produces are ordinary outbound messages — if the workspace has message suppression enabled, an identical body repeated inside the suppression window is collapsed like any duplicate send. Your own opt-out vocabulary (QUIT, UNSUBSCRIBE, brand-specific words) writes to the same consent records the built-in STOP handling maintains:
When a customer texts please unsubscribe me, the rule matches and two records change:
  1. The contact’s channel preferences flip to opted-out, and an entry is appended to the consent history on that contact: action opt_out, method keyword, keyword UNSUBSCRIBE, with the timestamp.
  2. An explicit consent record is written per channel — the same opt-out evidence you can review through the Opt-Out Lists API — so every later send to that contact is refused pre-send with RECIPIENT_OPTED_OUT until they opt back in.
Pair every opt-out keyword with the corresponding opt-in (action: "opt-in") so the customer has a way back. The built-in STOP/START vocabulary is handled before any rule runs — it is not a rule, cannot be shadowed by one, and a rule on STOP never fires.

4. Precedence in action: oldest matching rule wins

Rules are evaluated in creation order, and one inbound fires at most one rule. Suppose these four exist on sms, created in this exact API call order: Flip the creation order — broad rules first — and the specifics never fire: the contains rule swallows every YES-form, and a catch-all created ahead of the rest swallows everything. To re-sequence, delete the broad rule and re-create it so it becomes the newest:
…then POST it again. One nuance for pagination consumers: the rules list returns newest first (the same order the dashboard table uses), while matching walks oldest first — read the API page from the bottom up when reconstructing evaluation order.

5. The testing harness: prove a rule fired

There is no rule-hit counter. A fired rule is observable through its effects — the record custodians below are where you prove what happened:
  1. Send a real inbound from a handset to your number: the keyword, in the case you expect customers to use.
  2. Inbox. The conversation shows the inbound turn and, for a reply action, the outbound reply in the same thread.
  3. Delivery log. The reply shows as an outbound row; watch it traverse queuedsentdelivered. The row is an ordinary send — the status alone doesn’t name the rule; the sibling inbound in the same conversation is the attribution.
  4. Webhooks. If you subscribe to message status events, the reply’s delivery notification arrives where your sender id correlates — the envelope below is the shape to expect. See Webhook Events for the full status vocabulary.
  1. Consent surface (opt-in / opt-out actions). The customer’s contact profile shows the flipped preference with the keyword entry in consent history; the Opt-Outs view lists the record.
  2. Flow or agent actions. A trigger_flow match starts a run visible in the flow’s run history (the keyword rides into the run context); a forward_agent match hands the turn to the deployed agent, visible in the conversation timeline.
  3. Audit log. Rule management — create, update, delete — lands in Settings → Audit log with the actor and timestamp, alongside the rest of your organization’s actions. Use it with creation order to reconstruct why the wrong rule won when precedence surprises you.
When a rule that should match doesn’t fire, check in order: the rule is active; the keyword casing is irrelevant but accents are not (CAFECAFÉ); an Exact match is being defeated by invisible characters in the body (switch to Contains); or an earlier, broader rule is claiming the message first.

See also