When Meta asks you to prove opt-in
Sooner or later a WhatsApp Business account gets reviewed — usually after a quality-rating drop or a run of blocks. Meta asks the same thing every time: show us that these people agreed to be messaged. The businesses that lose their number are rarely the ones who did something egregious. They are the ones who could not answer.
What the request actually looks like
You will be asked to evidence consent for specific numbers, or for a sample of the audience a campaign went to. What satisfies it is boring and specific: who agreed, when they agreed, how they agreed, and what they actually did that constituted agreement. A claim that "they're all customers" is not evidence. Neither is a spreadsheet you assembled after the request arrived — a record created after the fact is the thing an auditor is specifically looking for.
What we record, and when
Klaros writes consent to an append-only ledger. Events are added, never edited, so the history reads as a sequence of things that happened rather than a current state somebody could have adjusted. Each event carries:
| Field | What it holds |
|---|---|
| status | opted_in, opted_out or pending — the state this event established. |
| source | How consent arrived. Not free text — one of a fixed set, so it cannot be softened later. |
| evidence_text | What the person actually said or did. The literal YES, the literal STOP, or the note an operator captured. |
| evidence_ref | The anchor that makes it checkable — the WhatsApp message ID, the page they clicked, the import batch it came from. |
| occurred_at | When consent actually happened, as well as we know it. |
| recorded_at | When we wrote it down. Kept separate from occurred_at on purpose — see below. |
Recognised sources, fixed at the schema level:
inbound_keywordpage_clickpersonal_waoperatorimportsystem
Why two timestamps matter more than they look.
Keeping "when it happened" apart from "when we recorded it" is what lets you demonstrate you are not
backdating. A single editable opted_in_at column proves nothing — anyone can write a date
into it. Two timestamps, one of them the immutable write time, let an auditor see the shape of your
record-keeping rather than take your word for it.
Producing the file
Two exports, both scoped to your workspace. Per contact, the full package: current status, the event that established it, and the complete history for disputes. In bulk, every contact in a given status as CSV, ready to attach:
Available in the dashboard under Compliance, and over the API at
/api/compliance/consent-export — see the API reference.
Opt-outs export the same way, which is the other half of the answer: you can show not only that people
agreed, but that when someone withdrew, you stopped.
What this does not do
It does not guarantee you pass a review, and nobody honest will tell you otherwise — the outcome depends on what you actually sent and to whom. It cannot manufacture consent you never captured: if a contact was imported from a list with no opt-in event, the export will say exactly that, because the alternative is fabricating evidence for an audit, which is a considerably worse day than a restricted number.
What it does is turn the request from an emergency into a task. You attach a file, in minutes, that was written as consent happened rather than assembled once someone asked.
Klaros runs on your own WhatsApp Business Account, so this ledger — and everything else — stays in infrastructure you control. Start a free trial or read how we handle your data.
