> ## 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.

# In-app notifications

> The Courier Inbox, toasts, and preferences UI on every client SDK, plus mobile push.

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>;
};

Courier gives your app three pieces of UI, all rendered by the client SDKs:

* **Inbox**, an embeddable in-app notification center.
* **Toasts**, lightweight popups synced to the same feed.
* **Preferences**, where users pick which topics they receive, and how.

All three sync in real time across a user's devices and share one authentication and theming model.

The same SDKs handle **mobile push**. One `signIn` call registers the device token APNs and FCM deliver to, so push rides the session you set up here.

<Frame caption="The Courier Inbox: unread indicators, relative timestamps, and per-message action buttons.">
  <img src="https://mintcdn.com/courier-4f1f25dc/9rcgucLA9fBnJt_U/assets/inbox-card.webp?fit=max&auto=format&n=9rcgucLA9fBnJt_U&q=85&s=9834fcc8c1fb404a4da412d96163c473" alt="The Courier Inbox with an unread count badge in its header, listing notifications with unread dots, relative timestamps, and View all, Download, and Approve actions" className="mx-auto" width="3152" height="1776" data-path="assets/inbox-card.webp" />
</Frame>

<Info>
  In-app renders inside your open app. Push is delivered by the operating system, so it arrives when your app is closed. They are separate channels, and one message can send to both. <Guide href="/docs/guides/set-up-mobile-push">Set up push notifications</Guide> covers the push side.
</Info>

## Choose your SDK

Install the SDK for your platform. Web Components work with any framework, or none.

| Platform                                                                | Package                             | Install                           |
| :---------------------------------------------------------------------- | :---------------------------------- | :-------------------------------- |
| <Doc href="/docs/sdk-libraries/courier-react-web">React</Doc> (18+)          | `@trycourier/courier-react` (v9)    | npm / yarn                        |
| <Doc href="/docs/sdk-libraries/courier-react-web">React 17</Doc>             | `@trycourier/courier-react-17` (v9) | npm / yarn                        |
| <Doc href="/docs/in-app/web-components">Web Components</Doc> (any framework) | `@trycourier/courier-ui-inbox` (v2) | npm / yarn                        |
| <Doc href="/docs/sdk-libraries/courier-vue-web">Vue</Doc>                    | `@trycourier/courier-vue` (v1)      | npm / yarn                        |
| <Doc href="/docs/sdk-libraries/courier-angular-web">Angular</Doc>            | `@trycourier/courier-angular` (v1)  | npm / yarn                        |
| <Doc href="/docs/sdk-libraries/ios">iOS</Doc>                                | `courier-ios`                       | Swift Package Manager / CocoaPods |
| <Doc href="/docs/sdk-libraries/android">Android</Doc>                        | `courier-android`                   | Gradle                            |
| <Doc href="/docs/sdk-libraries/flutter">Flutter</Doc>                        | `courier_flutter`                   | pub                               |
| <Doc href="/docs/sdk-libraries/react-native">React Native</Doc>              | `@trycourier/courier-react-native`  | npm / yarn                        |

<Note>
  `@trycourier/react-inbox`, `react-provider`, and the `components` bundle are deprecated. See the <Doc href="/docs/sdk-libraries/courier-react-v8-migration-guide">courier-react v8 migration guide</Doc> to move to `@trycourier/courier-react` or `@trycourier/courier-ui-inbox`.
</Note>

Every SDK follows the same three steps: send a token to the client, call `signIn`, then render the inbox.

<CodeGroup>
  ```jsx React highlight={9} theme={null}
  import { useEffect } from "react";
  import { useCourier, CourierInbox } from "@trycourier/courier-react";  // or "@trycourier/courier-react-17"

  export default function App() {
    const courier = useCourier();

    useEffect(() => {
      // Authenticate the user
      courier.shared.signIn({ userId, jwt });
    }, []);

    // Render the Inbox component
    return <CourierInbox />;
  }
  ```

  ```html Web Components highlight={7} theme={null}
  <courier-inbox id="inbox"></courier-inbox>

  <script type="module">
    import { Courier } from "@trycourier/courier-ui-inbox";

    // Authenticate the user
    Courier.shared.signIn({ userId, jwt });
  </script>
  ```

  ```vue Vue highlight={9} theme={null}
  <script setup lang="ts">
  import { onMounted } from "vue";
  import { CourierInbox, useCourier } from "@trycourier/courier-vue";

  const courier = useCourier();

  onMounted(() => {
    // Authenticate the user
    courier.shared.signIn({ userId, jwt });
  });
  </script>

  <template>
    <CourierInbox />
  </template>
  ```

  ```ts Angular highlight={4} theme={null}
  import { CourierService } from "@trycourier/courier-angular";

  // Authenticate the user
  this.courier.signIn({ userId, jwt });

  // Render: <courier-inbox></courier-inbox>
  ```

  ```swift iOS highlight={4} theme={null}
  import Courier_iOS

  // Authenticate the user
  await Courier.shared.signIn(userId: userId, accessToken: jwt)

  // UIKit
  view.addSubview(CourierInbox())

  // SwiftUI
  CourierInboxView()
  ```

  ```kotlin Android highlight={1,3} theme={null}
  // Authenticate the user (signIn is a suspend function)
  lifecycleScope.launch {
    Courier.shared.signIn(userId = userId, accessToken = jwt)
  }

  // Render the Inbox @Composable
  CourierInbox()
  ```

  ```dart Flutter highlight={4} theme={null}
  import 'package:courier_flutter/ui/inbox/courier_inbox.dart';

  // Authenticate the user
  await Courier.shared.signIn(accessToken: jwt, userId: userId);

  // Render the inbox widget
  CourierInbox();
  ```

  ```jsx React Native highlight={4} theme={null}
  import Courier, { CourierInboxView } from "@trycourier/courier-react-native";

  // Authenticate the user
  await Courier.shared.signIn({ accessToken: jwt, userId });

  // Render the inbox component
  <CourierInboxView />;
  ```
</CodeGroup>

## How it fits together

### A customizable UI

Courier Inbox ships a notification center out of the box. Theme it with `CourierInboxTheme`, supply your own views while the SDK still manages messages, or build a custom UI on the low-level APIs.

### Real-time and synced across devices

Messages arrive in real time on web and mobile. Every state change (read, opened, archived) syncs instantly across a user's signed-in devices.

### Notification-center essentials, built in

Out of the box you get:

* Unread counts and badges.
* Read and archive actions.
* Message-level buttons.
* Pagination and infinite scroll.

## FAQ

<AccordionGroup>
  <Accordion title="What is the difference between in-app and push notifications?">
    In-app notifications render inside your running app through the Courier SDK (the Inbox and Toasts). The operating system delivers push through APNs or FCM, so it appears even when your app is closed. They are separate channels, and one message can send to both. Connect your <Doc href="/docs/integrations/push/apple-push-notification">APNs</Doc> or <Doc href="/docs/integrations/push/firebase-fcm">FCM</Doc> credentials under Integrations.
  </Accordion>

  <Accordion title="What is the difference between Inbox and Toasts?">
    Inbox is the persistent notification center listing a user's messages. Toasts are transient popups that appear when a new message arrives, synced to the same feed. Both use the same authentication (`signIn`) and theming. See <Doc href="/docs/in-app/add-toasts">Add toasts</Doc>.
  </Accordion>

  <Accordion title="Which frameworks and platforms are supported?">
    React, React 17, Vue, Angular, Web Components (any framework or none), iOS, Android, Flutter, and React Native. See the [table above](#choose-your-sdk) for the package name per platform.
  </Accordion>

  <Accordion title="How do I authenticate users?">
    Your backend generates a JWT with your Courier API key and passes it to the client, which calls `signIn({ userId, jwt })`. See <Doc href="/docs/in-app/authenticate-users">Inbox authentication</Doc> for the full flow and scope strings.
  </Accordion>

  <Accordion title="Can I send to the inbox and other channels at the same time?">
    Add `inbox` alongside other channels in your message's routing. Courier delivers to each channel by your routing rules. Cross-channel syncing can mark the Inbox message read when the user opens the email. See <Doc href="/docs/in-app/send-to-the-inbox">Send to the inbox</Doc>.
  </Accordion>
</AccordionGroup>
