Compliance

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:

FieldWhat it holds
statusopted_in, opted_out or pending — the state this event established.
sourceHow consent arrived. Not free text — one of a fixed set, so it cannot be softened later.
evidence_textWhat the person actually said or did. The literal YES, the literal STOP, or the note an operator captured.
evidence_refThe anchor that makes it checkable — the WhatsApp message ID, the page they clicked, the import batch it came from.
occurred_atWhen consent actually happened, as well as we know it.
recorded_atWhen 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:

contact_id,phone,name,consent_status,opt_in_at,opt_in_source,opt_in_evidence,opt_in_reference c_8f2a…,919xxxxxxxxx,Priya R,opted_in,2026-05-14T09:22:11Z,inbound_keyword,"YES",wamid.HBgM… c_41bd…,919xxxxxxxxx,Arun M,opted_in,2026-06-02T17:04:58Z,page_click,"Opted in from card",acme-jewels

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.