Lynomia Chat keeps one record per person of **what they agreed to receive from you**. Every campaign and every
automated template asks that record before the message goes out, and a message it refuses is never handed to
WhatsApp at all.

This is the part of the product where a mistake is expensive. Messaging people who asked you to stop is how a
WhatsApp number loses its quality rating, and then its ability to send.

## Two classes, opposite defaults

A message is one of two things, and the register answers for them separately.

| | What it is | The default |
|---|---|---|
| **Transactional** | an update about an order this person placed — paid, shipped, delivered, cancelled, refunded | **allowed** unless they refused |
| **Promotional** | anything they did not ask for — a campaign, a marketing template | **refused** unless they agreed |

**No record at all is not consent.** For a transactional message it means nobody objected, so the message goes.
For a promotional message it means nobody agreed, so it does not. That asymmetry is the whole point of keeping
two classes: treating them the same would either silence parcel notifications nobody objected to, or market at
people who never agreed.

**The class comes from Meta, not from you.** A WhatsApp template Meta approved as **UTILITY** is transactional.
Everything else is promotional — a MARKETING template, an AUTHENTICATION template, a template this inbox's synced
list does not hold. Nothing you type decides it, which is deliberate: a marketing template attached to an
order-shipped trigger is still marketing. SMS has no provider classification at all, so an SMS campaign is
always promotional.

## Three states

| State | What it means | Who decides it | How it ends |
|---|---|---|---|
| **Granted** | they agreed to this class | the shopper, or an administrator recording what the shopper told them | a later withdrawal |
| **Withdrawn** | they asked not to be messaged | the shopper | **only the shopper, by agreeing again** |
| **Suppressed** | the number cannot receive | the system | an administrator clearing it, once the cause is fixed |

**Withdrawn and suppressed both block, and they are not interchangeable.** A withdrawal is the person's
decision. A suppression is a delivery fault. They are kept apart so that fixing a delivery fault can never
overturn somebody's opt-out: clearing a suppression leaves every withdrawal exactly where it was.

There is **one record per person per class**. Recording a new decision replaces the previous one; the sequence of
decisions lives in the account's audit trail, not on the record.

## STOP and START

A shopper can opt out without an agent. The keywords are matched **on the inbound message, the moment it
arrives**, on every channel and in every account. This does not depend on your plan, on Commerce, or on anybody
reading the conversation — an opt-out that only works when somebody is at their desk is not an opt-out.

| | Keywords |
|---|---|
| **Opt out** | `stop` `unsubscribe` `cancel` `الغاء` `إلغاء` `ايقاف` `إيقاف` `توقف` |
| **Opt back in** | `start` `subscribe` `ابدأ` `يبدأ` `اشتراك` `موافق` |

Three rules decide whether a message counts as a keyword.

- **The match is the whole message, not a word inside one.** "Please stop sending me the wrong size" is a
  complaint for an agent to answer. It is not an opt-out, and reading it as one silences a customer who was
  asking for help.
- **Case and surrounding punctuation are ignored.** `STOP`, `stop` and `stop.` all match. Nothing else about the
  word is changed before it is compared.
- **Anything longer than 20 characters is not a keyword**, whatever it contains.

**STOP means stop, for both classes.** Somebody typing STOP is asking not to be messaged, and answering "that
only applied to some of our messages" serves you rather than them. A shopper who wants only their parcel updates
back can type START, which grants both again.

What is kept as evidence is the message's id and the keyword matched. **The message text is never kept** — a
consent record is the last place a customer's own words should be copied to.

## Recording a decision yourself

You may record what a shopper told you at a counter, on a call or on a paper form. Three things are true of it.

**It is administrators only, and it needs a plan that includes Commerce.** Whether a person receives automated
messages from you is not an agent's call to change, and a list of who opted out of marketing is not an agent's
to read.

**An evidence note is required, not optional.** A grant typed in by a merchant is a claim about a conversation
that happened somewhere else; without a note saying where, it is indistinguishable from somebody adding a person
to a marketing list. The note is 1 to 500 characters, is stored with the decision, and is kept alongside your
name and the date.

**There is no consent screen in the dashboard.** The register is reached through the account API with your own
access token — see [your profile and security](your-profile-and-security). Do not go looking for a settings
page; there is not one. Four calls exist, all under `/api/v1/accounts/{account_id}/commerce/`:

| Call | What it does |
|---|---|
| `GET consents` | the account's 100 most recent decisions, newest first; `purpose` and `state` filter it |
| `GET consents/{contact_id}` | one person's two classes, and whether a send would be allowed right now |
| `PUT consents/{contact_id}` | record one class: `purpose`, `state` (`granted` or `withdrawn`) and `note` |
| `DELETE consents/{contact_id}` | clear a **suppression** |

One class per `PUT`, and the decision is marked as yours automatically. **A withdrawal cannot be cleared.**
`granted` and `withdrawn` are the only states you may record, and a `granted` decision after a withdrawal is
written as a new, evidenced decision rather than as an undo — which is what keeps the record honest. `DELETE`
clears suppressions and nothing else.

A filter value the server does not recognise is **refused rather than ignored**. Asking to see who has opted out
and being shown everybody instead would read the opt-ins as opt-outs, which is the one mistake this register
cannot afford.

## What a withdrawal blocks

| | Blocked |
|---|---|
| A WhatsApp campaign, an SMS campaign | **yes** |
| A WhatsApp template an agent sends from the composer, or in a new conversation | **yes** |
| A template sent by an [automation rule](automation-rules) or a [Flow Builder](flow-builder) step | **yes** |
| A reply you type in a conversation while the 24-hour window is open | no |
| A private note | no |
| The shopper's own incoming messages | no |

**A reply inside an open conversation is not marketing.** The person wrote to you; answering them is the service
they asked for. Consent gates the messages *you* start — templates and campaigns — and does not gate the
conversation *they* started.

A refused message does not quietly disappear. It appears in the conversation marked **Failed to send**, with the
reason underneath: *this person asked not to be messaged. They can opt back in by replying START.* A refused
campaign recipient is recorded on the campaign instead — see
[why a campaign skipped someone](why-a-campaign-skipped-someone).

## A worked example

A customer asks at your counter to be told when their order ships, and says they do not want offers.

1. Record **transactional — granted**, with the note *asked at Salmiya counter, 4 March, wants shipping updates*.
2. Record **promotional — withdrawn**, with the note *asked at Salmiya counter, 4 March, no offers*.

Your order-shipped template now reaches them. Your campaigns do not, and no label or audience you build can put
them back into one, because the refusal is applied after the audience is resolved.

Two weeks later they reply **STOP** to the shipping update. Both classes are now withdrawn, including the
transactional one you recorded a grant for, and you cannot undo it. If they ask for the updates back, they type
START.

## Limits

- **A promotional message needs a grant that exists, and only a Commerce plan can record one.** Without
  Commerce there is no authorised way to record that somebody agreed, so a MARKETING template in a campaign, an
  automation rule or a flow reaches nobody. Order updates through an approved UTILITY template are unaffected.
  Opt-outs are honoured either way: a STOP reply writes a withdrawal in every account, on every plan.
- **The composer is the one exception to that.** In an account without Commerce, a marketing template an agent
  sends by hand is stopped only by a decision somebody actually made — a withdrawal or a suppression — rather
  than by the absence of a grant.
- **A decision you record applies to the one class you named.** A STOP keyword writes both, so a real opt-out
  stops everything; a merchant recording "no marketing" leaves order updates running, on purpose.
- **Consent decides nothing about the 24-hour window, template approval or your messaging limit.** Those are
  separate refusals with their own reasons — see [the WhatsApp 24-hour window](the-whatsapp-24-hour-window).
- **A connected store can hold its own opt-in, separately from this.** A shopper who ticked a marketing box at a
  store's own checkout is recorded against that store, and a campaign belonging to that store accepts either
  record. A refusal in either record stops the send, and neither record can overturn the other.
- **The Audit Logs page has no wording for a consent change.** The decision is written to the account's audit
  trail with its author, time and note, but [audit logs](audit-logs) does not describe it and its event type is
  not one of the types that page can filter on.
- **Blocking a contact is not a consent decision.** It stops what comes in, and it does also stop every campaign
  and template going out, under its own reason. It records nothing about what the person agreed to, and
  unblocking restores nothing they withdrew.

## Related

- [Why a campaign skipped someone](why-a-campaign-skipped-someone)
- [WhatsApp campaigns](whatsapp-campaigns)
- [The WhatsApp 24-hour window](the-whatsapp-24-hour-window)
- [WhatsApp templates](whatsapp-templates)
- [What connecting a store gives you](commerce-overview)
- [Contacts](contacts)

## If it does not work

**My campaign reached far fewer people than the recipient count promised.** The count is already filtered by
consent, but it is taken when you build the campaign and the recipients are resolved again at send time. Open
**View analytics** on the campaign: *No marketing consent on record* and *Customer opted out* are reasons, not
errors.

**An agent's marketing template keeps failing with "has not opted in to marketing".** Meta classifies that
template as something other than UTILITY, so it is promotional, and this person has no promotional grant. A
UTILITY template still sends to them.

**A shopper says they replied STOP but was messaged anyway.** Check what they actually sent. A keyword inside a
longer sentence is not an opt-out. Record the withdrawal yourself, with their words as the note.

**I cleared the suppression and they still receive nothing.** Clearing a suppression never clears a withdrawal.
Read the person's record: if the state is withdrawn, only they can change it, by replying START.

**Nothing I send to this person arrives, and there is no consent record at all.** Check whether the contact is
blocked, and check the 24-hour window. Both refuse messages for their own reasons and neither writes anything
here.

**I cannot find the consent register in the dashboard.** There is no screen for it. It is the API above, and it
needs a plan that includes Commerce and an administrator's access token.