> For the complete documentation index, see [llms.txt](https://flapjax.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://flapjax.gitbook.io/docs/your-data/people/consent-and-subscriptions.md).

# Consent & Subscriptions

Every person decides which of your [**consents**](/docs/settings/workspace/consents.md) they accept, per channel: Marketing, Product news, Account & legal. Consent is more than a label you keep for the record. Flapjax enforces it at send time.

A message aimed at someone who has not consented gets **skipped before it reaches your provider**, and Flapjax records the skip so you can see it happened.

A consent is a **purpose**, not a channel. That is what lets someone keep your order updates and drop your promotions.

## Email Consent and SMS Consent are summaries

**Email Consent** and **SMS Consent** still appear on the person, in exports, in segment filters and in the API. They are no longer separate settings. Each one **summarises that person's consents**, and Flapjax maintains it:

> **Email Consent is on when the person allows at least one email consent.** Refuse them all and it switches off by itself. Accept any one and it comes back on.

You manage one thing, the consents. One field then answers "can we reach this person on this channel at all?" for reporting and filtering.

**Push notifications** sit outside consents. **Push Notifications Consent** stays an ordinary flag you set directly.

## Consent gates delivery

An automation, a bulk action or a manual send tries to message a person. Flapjax checks the matching consent **before it builds or dispatches the message**.

* A person who consented gets the send.
* A person who has **not** consented gets **skipped**. Nothing reaches your email, SMS or push provider, and Flapjax logs the attempt with status **`Skipped`** and a reason of *"missing … consent"*.

An action that declares a consent needs the recipient to allow that consent on that channel. A consent the person never answered falls back to its **default**, so starting to use one needs no backfill of answers. The skip reason names the consent, for example *"Not sent, missing consent: Marketing"*.

An action with no consent assigned behaves as it always did. The channel summary gates it, meaning "allows at least one consent".

**Always on** consents such as password resets and legal notices pass all of this and reach people who have unsubscribed.

Flapjax records each skip against the person it applied to, with the reason. A run that "sent 1,000 and skipped 120" stays visible rather than silent. Single and bulk sends behave the same way. In a bulk send, people without consent leave the batch, each gets a logged skip, and everyone else still receives the message.

{% hint style="info" %}
**Where to look.** Skips are recorded as **action analytics**, visible on the person and on the automation run. They stay out of [Communications reporting](/docs/reporting/communications.md), which lists messages that actually went out. A skipped send never became a message. A message that did go out and then got rejected by your provider is a different case, and it shows in Communications as **Failed**.
{% endhint %}

The practical result: **you cannot message someone who has opted out**, whatever triggered the send. Consent is the last gate before dispatch.

## How consent gets set and changed

* **On the detail page.** The Details sidebar carries a **Consent purposes** section with a row per consent and channel. Unanswered rows show what the default gives that person, so a blank state never reads as a choice.
* **Via the preference page.** Recipients tick the consents they want, or use **Unsubscribe from everything**, which refuses every consent they can refuse. See [Unsubscribe Pages](/docs/settings/workspace/unsubscribe-pages.md).
* **Via one-click unsubscribe.** The control mail apps show at the top of a message does the same job.
* **From your email provider.** SendGrid reports an unsubscribe or a spam complaint, and Flapjax refuses every email consent for that person. Provider-side opt-outs and yours stay in step.
* **On import or through the API.** People CSVs and person updates carry a `consent_<key>_<channel>` column or a `consents` array, such as `consent_marketing_email`.
* **Writing `email_consent` directly** still works as a shortcut, described next.

## Writing Email Consent directly

`email_consent` and `sms_consent` stay writable through the API, the dedicated consent endpoints, imports and the Register Person form. They are summaries, so Flapjax translates a write into consents. The two values deliberately behave differently:

* **`false` refuses everything.** "Do not email me" leaves no room for doubt, so every consent on that channel gets refused.
* **`true` grants the starter consent alone.** It means "you may email me", not "I want every purpose". It ticks the consent marked as that channel's default, created for you as **Email updates** or **SMS updates**, and leaves every other consent on its own default.

That asymmetry is on purpose. A list import saying "these people agreed to email" must never manufacture consent for purposes nobody asked them about.

## Creating people: no value means opt-out

Creating a person never opts them in. A record you created is no evidence that anyone agreed to anything. People arrive through imports, API syncs and event ingestion, and none of those represent a decision by the person.

> **Create or import a person with no consent value and Flapjax treats them as&#x20;*****not consented*****.** A missing value is an opt-out, not a "decide later".

Importing a list of people who genuinely opted in elsewhere? Say so explicitly with `email_consent: true`, or with the `consent_<key>_<channel>` columns for per-purpose detail. Leave it out and every send skips those people until consent lands.

Two deliberate exceptions cover cases where waiting for an answer would be wrong:

* A consent can **default to opted in**, one consent at a time, where you have a lawful basis for it.
* An **Always on** consent needs no answer at all. That is how a person created a second ago still gets their password reset.

## WhatsApp is not a working consented channel

WhatsApp appears elsewhere in the product, and **it is not a functioning consented channel in Flapjax today**. Two things make it inert.

* **No WhatsApp consent control exists.** No checkbox on the form, no field on the person you can set, no place in the data model that stores a WhatsApp consent value. The send code references a WhatsApp consent flag, and nothing can ever set it, so it stays off.
* **The Send WhatsApp action has left the automation builder**, so no supported way remains to trigger a WhatsApp send.

Treat WhatsApp as vestigial and build no flows or consent processes around it. Use Email, SMS and Push, the three channels Flapjax enforces and delivers.

***

**Related:** [Consents](/docs/settings/workspace/consents.md) · [Managing People](/docs/your-data/people/managing-people.md) · [Person Detail Page](/docs/your-data/people/person-detail-page.md) · [Unsubscribe Pages](/docs/settings/workspace/unsubscribe-pages.md) · [Communications Reporting](/docs/reporting/communications.md)
