> ## 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` from the Node SDK (`@trycourier/courier` v7 and later, where the client is the default import). 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.
> To translate a template, write one locale at a time with `PUT /notifications/{id}/locales/{localeId}`, which merges into the existing translations. `PUT /notifications/{id}/content` and `PUT /notifications/{id}/elements/{elementId}` overwrite translations along with the content, so send each element's `id` and `locales` back, and first remove every `checksum` and any `locales` key that starts with an underscore.
> 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.

# Environments and API keys

> Production, Test, and custom environments with separate API keys, templates, and logs, and how to migrate templates between them.

export const AppLink = ({href, children, name, bare}) => {
  const label = children || name || "Open in Courier";
  if (bare) {
    return <a href={href} target="_blank" rel="noreferrer">{label}</a>;
  }
  return <a className="cx-endpoint" data-kind="app" href={href} target="_blank" rel="noreferrer">
      <span className="cx-endpoint-label">{label}</span>
      <span className="cx-endpoint-method" aria-hidden="true">↗</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>;
};

An environment is a separate copy of your Courier setup inside one workspace, the same way you run separate development, staging, and production deployments. The API key on each request decides which environment it reads from and writes to.

| Separate in each environment | Shared across the workspace |
| :- | :- |
| Templates, brands, and tags | Team members, and the <Doc href="/docs/workspaces/team-access">roles</Doc> that set their access in each environment |
| Journeys and subscription topics | <Doc href="/docs/monitor/tracking">Open and click tracking</Doc> settings |
| Provider integrations and their credentials | <Doc href="/docs/workspaces/billing">Billing</Doc>, which counts sends from every environment |
| API keys | |
| Logs and metrics | |

A change in one environment doesn't reach another until you <Doc href="/docs/workspaces/environments#migrate-assets-between-environments">migrate</Doc> it.

## API keys

Every API key belongs to one environment, and the key you call Courier with decides where the request lands. Courier has no separate test mode: a Test key is what puts you in the Test environment. The prefix tells you what the key can do:

| Key | Prefix | What it does |
| :- | :- | :- |
| Published | `pk_…` | Sends with the latest published version of each template, through that environment's integrations |
| Draft | `dk_…` | Renders unpublished template changes against real payloads, so you catch a rendering bug before publishing |

Create a separate key for each service so you can rotate or revoke one without breaking the others. Use API keys only in server-side code, and use Test keys during development. A browser or mobile app signs in with a JWT that your backend mints, as <Doc href="/docs/in-app/authenticate-users">Authenticate users</Doc> shows.

Create and rotate keys in <AppLink href="https://app.courier.com/settings/api-keys">Settings → API Keys</AppLink>.

## Production, Test, and custom environments

Every workspace starts with **Production** and **Test**. You can create as many custom environments as you need, such as Staging or QA. To create one, open the environment dropdown at the top of the console and select **Create new environment**. You can rename any environment except Production.

Switch environments from the same dropdown. Switching changes only your view, never live notifications.

### Email in the Test environment

A new workspace's Test environment comes with a testing email provider already configured, so you can send before connecting anything of your own.

That provider **only delivers to the address you signed up with**. You can develop against real sends with no chance of reaching a customer, which also makes a Test key the right one to hand an <Guide href="/docs/guides/send-from-an-ai-agent">AI agent</Guide>.

To reach other addresses from Test, connect your own email provider to that environment, such as a sandbox SendGrid key. Integrations are per environment, so this doesn't change Production.

## Migrate assets between environments

To copy a template to another environment, open the ellipsis menu on the template in the templates page and choose **Migrate assets**. Courier copies the template with its dependencies: brands, tags, subscription topics, test events, and event maps. On later migrations, you choose whether to overwrite each copied dependency or keep the one already there. To copy to another workspace, pick it as the destination.

**Provider integrations stay in their own environment and aren't copied.** Before you send from a migrated template, configure its providers in the destination environment. The destination can use different credentials from the source.

## Logs and metrics by environment

Logs and metrics belong to the environment of the key that made the send. A Test-key send appears only in the Test environment's logs, and a Production-key send only in Production's.

## FAQ

<AccordionGroup>
  <Accordion title="Should I use separate workspaces or environments for staging?">
    Environments are the right fit for staging. Create a custom Staging environment in the same workspace. Separate workspaces are for separate billing, not for staging.
  </Accordion>

  <Accordion title="Why does a migrated template render but not deliver?">
    Provider integrations are per environment and aren't migrated. Configure the provider in the destination environment so the template has a channel to send through.
  </Accordion>
</AccordionGroup>
