Opting out of WhatsApp
STOP on its own ends WhatsApp messages and START restores them, recognised exactly as strictly as on SMS. Connect writes the change in two places: consent withdrawn on that person's WhatsApp route, and a memory block that every send path already consults. Inbound messages keep arriving — consent governs what Connect sends, not what it hears.
What counts as opting out#
A message that is only a stop word: stop, stopall, unsubscribe, cancel, end, quit, optout, opt out or revoke. Punctuation and case are ignored, nothing else is. The counterparts that bring somebody back are start, unstop, subscribe, optin, opt in and resume. This is the same test SMS uses, deliberately reused rather than reinvented for this channel.
The strictness is the point. "Please stop the second delivery" contains the word and is a message to answer, not an unsubscribe; treating a sentence containing *stop* as an opt-out would end the relationship of every customer who ever wrote one. The cost is the other direction: a person who writes *please remove me from this list* has not opted out by this test, and their request needs a human, or a suppression recorded by hand, to become one.
Where a STOP is written#
One stop word produces three records, on purpose. The conversation itself is marked opted out with the moment it happened, so the thread carries its own state. The person's WhatsApp route in the relationship record has its consent set to withdrawn, sourced as whatsapp:opt-out, which is what makes the change visible where consent is normally reviewed. And a memory block is written against that number, tagged for this channel — the record dispatch consults before every automatic send, which is what makes the stop hold in conversations that do not exist yet.
A START reverses it symmetrically: the conversation reopens, the route's consent is granted again with source whatsapp:opt-in, and the opt-out memory rows for that number are deactivated rather than deleted, so the history of the decision survives.
None of this depends on how the number is connected. A STOP arriving at an Official API number and a STOP arriving at a QR-linked one take the same path and write the same three records — the consent test runs on inbound customer messages, and a QR-linked number receives those exactly as any other does. What the handset sends back is the business's own words and is never tested for a stop word.
| Mechanism | Scope | Cleared by |
|---|---|---|
opted_out on the conversation | This thread — no template and nothing automatic | A START from the same person |
| Consent on the WhatsApp route | This person, this channel, in the relationship record | A person, or their own START |
| Memory block tagged for WhatsApp | This person, this channel, across every future conversation | A START, or removing the tag from the memory row |
| Suppression / do-not-contact | This person, the channels it names or all of them | A person — never the Connect Assistant, which has no such right |
The memory block is the one that explains a piece of design people ask about. Blocking is deliberately not a column on a table. It is a memory row against the contact carrying block:whatsapp in its tags, and directives() reads only the tag list — never the body. That is exactly what makes a block hold across channels and across conversations that do not exist yet, instead of being a flag on a thread that a new thread would not inherit.
What happens immediately after#
The request is recognised or recorded.
Result The suppression exists against the Person, with its origin — who or what created it, and when.
Any pending outbound work for that person is re-evaluated.
Result A held draft cannot be approved past a suppression; approving it fails with the suppression and its origin shown.
The decision is written to the audit trail.
Result A refusal is a decision, and
audit.pyrecords refusals as well as actions. Months later the question "why did nobody chase this account" has an answer.
After a STOP, send_message refuses any template and anything automatic outright. The one path left open is a person in Connect typing a reply inside the window to something the customer sent afterwards — that is still a reply to them, not an approach. dispatch, which is every automatic path, refuses with opted_out before a model is even asked.
What a stop does not do#
- It does not delete the person, the conversation or the history. Erasure is a different request with different consequences.
- It does not stop inbound messages. If they write again, the message arrives and is recorded — and if they are asking for something, a person should see it.
- It does not silently expire. A suppression stays until somebody with the right to clear it does so, and the Assistant cannot clear a do-not-contact entry at all.
- It does not travel outside the workspace. Each workspace holds its own suppressions, like everything else.
If the request should reach every channel rather than this one, A do-not-contact reaching every channel is the flow that does it, and it is the safer choice when somebody asks to be left alone rather than to stop one particular kind of message.
Questions#
Can a customer opt back in?
Yes — by writing START (or unstop, subscribe, optin, opt in, resume) on its own. That reopens the conversation, grants consent on the route again and deactivates the block. A suppression or do-not-contact recorded by a person is separate and is not cleared by the customer writing.
Does an opt-out on WhatsApp stop emails as well?
No. The consent change is written on the person's WhatsApp route and the memory block is tagged for this channel, both deliberately. Only a do-not-contact recorded against the person reaches every channel.
What if somebody opts out mid-conversation about an order?
The stop is honoured for new outbound work, and the open commitment becomes something a person should look at. That is what Needs You is for — an unfinished obligation to a person Connect may no longer message is exactly the kind of thing a human has to decide about.