> ## Documentation Index
> Fetch the complete documentation index at: https://www.courier.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Install the Courier skill before writing code: `npx skills add trycourier/courier-skills`. It carries the verified SDK shapes and the rules you cannot get wrong.
> Authenticate every request with `Authorization: Bearer <API_KEY>`. A workspace has several environments and each has its own keys, which are plain `pk_` strings with no environment prefix. Start with Test.
> Send with `client.send.message`, the default import of the v7 Node SDK. Reference a template by its `nt_` id or its alias.
> A send accepts a bare Elemental element list, but storing content on a template requires the top-level elements wrapped in a channel element.
> Templates and journeys can be built in the Courier app or created through the API. Either way they live in the workspace and are referenced by ID when you send.
> The hosted MCP server is https://mcp.courier.com. For a briefing on what Courier is and when to use it, read https://www.courier.com/llms.txt.
> Prefer the Guides tab for how-do-I questions and the Docs tab for how-does-it-behave questions. The API reference lives under /api-reference.

# Preferences Editor

> Build the preference center: page settings, sections, topics, digests, and publishing.

export const Endpoint = ({method, path, name, href, children, bare}) => {
  const verb = String(method || "").toUpperCase();
  const title = verb + " " + path;
  const label = children || name || path;
  if (bare) {
    return href ? <a href={href}><code>{title}</code></a> : <code>{title}</code>;
  }
  if (!href) {
    return <span className="cx-endpoint" data-method={verb} title={title}>
        <span className="cx-endpoint-label">{label}</span>
        <span className="cx-endpoint-method">{verb}</span>
      </span>;
  }
  return <a className="cx-endpoint" data-method={verb} href={href} title={title}>
      <span className="cx-endpoint-label">{label}</span>
      <span className="cx-endpoint-method">{verb}</span>
    </a>;
};

export const Guide = ({href, children, name, bare}) => {
  const label = children || name || href;
  if (bare) {
    return <a href={href}>{label}</a>;
  }
  return <a className="cx-endpoint" data-kind="guide" href={href}>
      <span className="cx-endpoint-label">{label}</span>
      <span className="cx-endpoint-method">GUIDE</span>
    </a>;
};

export const Doc = ({href, children, name, bare}) => {
  const label = children || name || href;
  if (bare) {
    return <a href={href}>{label}</a>;
  }
  return <a className="cx-endpoint" data-kind="doc" href={href}>
      <span className="cx-endpoint-label">{label}</span>
      <span className="cx-endpoint-method">DOC</span>
    </a>;
};

The Preferences Editor is where you set up the topics users can control, group them into sections, and design the preference page. It's fully customizable: the branding, wording, sections, topics, and channels are all yours to define.

Courier checks these preferences on every send, and changes save as a draft until you publish.

The editor is organized top down:

* **Page settings** apply to the whole preference page: its brand, heading, description, and channel names.
* **Sections** group related topics under a heading you name yourself, such as "Account notifications" or "Marketing."
* **Topics** are the categories users opt in or out of. You name and configure each one, and every topic lives in a section.
* **Templates** map to a topic, so every send respects the user's choice automatically, with no extra logic in your code.

<Frame caption="An example preference page. Every part, from the branding to the topics, is customizable.">
  <img src="https://mintcdn.com/courier-4f1f25dc/Yy12YQJXNoKdo-Rl/assets/platform/preferences/preferences-editor-zoomed-in.png?fit=max&auto=format&n=Yy12YQJXNoKdo-Rl&q=85&s=65e7064c87b2154af9a0f31f1cb30db6" alt="Courier Preferences Editor showing page settings, sections, and subscription topics" width="1564" height="1288" data-path="assets/platform/preferences/preferences-editor-zoomed-in.png" />
</Frame>

## Page settings

These settings apply to the whole page, across every section and topic.

* **Brand:** the <Doc href="/docs/design/brands">brand</Doc> applied to the page, with your logo and colors.
* **Heading:** the title at the top of the page, like "Manage your messaging preferences."
* **Description:** the subtitle under the heading.
* **Channel names:** the labels users see for each channel across the page. Rename them to match your product's voice, for example "In-App" to "Inbox" or "Push" to "Mobile Push".

<Frame>
  <img src="https://mintcdn.com/courier-4f1f25dc/xDJPBS8EQ58X_0-v/assets/page-settings-2.webp?fit=max&auto=format&n=xDJPBS8EQ58X_0-v&q=85&s=0f05064fe34ebeabdd997784e5b2b992" alt="Page settings in the Preferences Editor: brand, heading, description, and channel names" className="mx-auto" style={{ width:"64%" }} width="932" height="460" data-path="assets/page-settings-2.webp" />
</Frame>

## Sections and channel selection

Sections group related topics under their own heading and set which channels users can adjust for the topics inside. Add as many as you need, name each one yourself (the "Account notifications" and "Marketing" tabs above are just examples), and reorder them to control how they appear.

Each section has:

* **ID:** the section's unique identifier, generated automatically by Courier and used in the API.
* **Heading:** the section title users see.
* **Description:** optional text shown under the heading.

<Frame>
  <img src="https://mintcdn.com/courier-4f1f25dc/rYENcCCTyPPrDtw0/assets/section-settings-1.webp?fit=max&auto=format&n=rYENcCCTyPPrDtw0&q=85&s=bce73873bb44861c00a459f30d2e51a1" alt="Section settings with the auto-generated section ID, heading, and description" className="mx-auto" style={{ width:"67%" }} width="881" height="586" data-path="assets/section-settings-1.webp" />
</Frame>

### Channel selection

Turn on channel selection for a section to let users choose how they receive its notifications, from the channels you make available (email, SMS, push, in-app, and more). Users see the channel names you set in page settings, not the raw values. In the API, channels use the `custom_routing` enum: `direct_message`, `email`, `inbox`, `push`, `sms`, `webhook`.

When a user customizes their channels, those choices appear in the `custom_routing` array from the <Doc href="/docs/api-reference/user-preferences/get-users-preferences">user preferences API</Doc>. The array only populates for sections where you've enabled channel selection:

```json theme={null}
{
  "topic": {
    "custom_routing": [
      "email",
      "push",
      "webhook"
    ],
    "has_custom_routing": true,
    "default_status": "OPTED_IN",
    "section_id": "5p8ROfompcN6Sg_2WR92A",
    "section_name": "Notifications",
    "status": "OPTED_IN",
    "topic_id": "FPPGTQRQTRM8TSPZGZAY9296WB37",
    "topic_name": "Product Updates"
  }
}
```

## Subscription topics

Subscription topics are the categories users control independently. You name and customize each one, for example marketing, security, or product updates. Each topic lives in a section and groups related notifications a user might want to receive or skip.

<Frame>
  <img src="https://mintcdn.com/courier-4f1f25dc/Yy12YQJXNoKdo-Rl/assets/platform/preferences/preferences-topic-settings.png?fit=max&auto=format&n=Yy12YQJXNoKdo-Rl&q=85&s=22e1a54bfd6dced7ade4af0d29859145" alt="Subscription topic settings with name, section, and default state" className="mx-auto" style={{ width:"61%" }} width="1626" height="1016" data-path="assets/platform/preferences/preferences-topic-settings.png" />
</Frame>

### Topic configuration

Each topic has:

* **Name:** the user-facing label for the category.
* **Section:** which section the topic belongs to.
* **Default state:** how users start out, described below.

### Default states

The default state sets how a topic behaves before a user changes it:

* **On:** users receive these notifications unless they opt out.
* **Off:** users receive nothing until they opt in.
* **Required:** users can't opt out. Use it for critical notifications like security alerts.

Required topics have one catch worth planning around. Unsubscribe links (`{$.urls.unsubscribe}` or `{{var "urls.unsubscribe"}}`) still render and the confirmation page still loads, but opting out does nothing and the user stays subscribed. Leave unsubscribe links out of templates mapped to Required topics so users aren't misled.

### Topic data

Attach arbitrary metadata to a topic through the API and use it to build <Doc href="/docs/in-app/add-a-preference-center">custom preference pages</Doc>. For example:

* Filter topics by metadata.
* Drive custom logic for how preferences display or apply.
* Store your own topic descriptions.

## Map templates to topics

Mapping a template to a topic is what makes Courier enforce the user's preference whenever that template sends. Each template maps to a single topic, and you set the mapping on the template itself, in Design Studio or through the API.

### In Design Studio

Open a template in <Doc href="/docs/design/templates/design-studio">Design Studio</Doc>, go to its <Doc href="/docs/design/templates/template-settings">template settings</Doc>, and choose a subscription topic. You can change it anytime.

<Frame caption="Assigning a subscription topic to a template in Design Studio">
  <img src="https://mintcdn.com/courier-4f1f25dc/xDJPBS8EQ58X_0-v/assets/manage-subscription-topic-on-template.webp?fit=max&auto=format&n=xDJPBS8EQ58X_0-v&q=85&s=29df445058b5c66d4c7f007cf4944f82" alt="Assigning a subscription topic to a template in Courier Design Studio" className="mx-auto" style={{ width:"91%" }} width="2002" height="1546" data-path="assets/manage-subscription-topic-on-template.webp" />
</Frame>

### Through the API

A template's topic is the `subscription` field on the <Doc href="/docs/design/templates/api">Notification Templates API</Doc>, set to `{ "topic_id": "<TOPIC_ID>" }` or `null`. Include it when you <Doc href="/docs/api-reference/templates/create-notification-template">create a template</Doc>:

```bash cURL wrap theme={null}
curl -X POST https://api.courier.com/notifications \
  -H "Authorization: Bearer $COURIER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "notification": {
      "name": "Order shipped",
      "tags": [],
      "brand": null,
      "subscription": { "topic_id": "TOPIC_ID" },
      "routing": null,
      "content": { "version": "2022-01-01", "elements": [] }
    }
  }'
```

To change an existing template's topic, use <Endpoint method="PUT" path="/notifications/{id}" name="Replace Notification Template" href="/docs/api-reference/templates/replace-notification-template" />. It replaces the whole template, so <Doc href="/docs/api-reference/templates/get-notification-template">fetch the template</Doc> first, update `subscription`, then send the full payload back.

## Digests

A topic can deliver its notifications as a digest: batched into one message on a schedule instead of sent one at a time. You set this up in the topic's digest settings by linking a digest template and defining the schedules users choose from, like Instant, Daily, or Weekly.

See the <Doc href="/docs/guides/send-a-daily-digest">complete guide to configuring digests</Doc>.

## Unsubscribe headers

When a user opts out of a topic, Courier can add a `List-Unsubscribe` header to outgoing emails for that topic, so users can unsubscribe from their email client. `List-Unsubscribe` is a standard header, so you enable it in your email provider's settings, like SendGrid or [Mailgun](https://help.mailgun.com/hc/en-us/articles/203306610-Unsubscribe-Handling-Links#01HNZH48NP73S3Q0KVR9B40SV5).

## Drafts, preview, and publishing

Editing preferences never affects users right away. Every change saves as a **draft**, and users keep seeing the last published version until you publish. The editor gives you three controls:

* **Save** keeps your latest changes as a draft.
* **Preview Page** opens the preference page exactly as a user would see it, with your unpublished changes and a "Draft mode" banner so you know it isn't live yet.
* **Publish** makes the draft the version users see. After publishing, **View Page** opens the live page.

Your preference center can live in two places, and both read from the preferences you configure here.

### Courier-hosted

Courier hosts the preference page for you, so there's no frontend to build. You style and brand it in the editor, then drop a link to it into your emails or app, and users get a responsive page they can manage themselves. This is the page **Preview Page** and **View Page** open. See <Doc href="/docs/guides/build-a-preference-center">Hosted preference center</Doc>.

### Embedded in your app

To keep users inside your product, embed the same preference center with Courier's SDKs, for <Doc href="/docs/sdk-libraries/courier-react-web">React</Doc> or any framework using <Doc href="/docs/in-app/web-components">web components</Doc>. Embedded preferences reflect whatever you've published, so use **Preview Page** above to check a draft before it goes live.
