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

# Journey send node

> Send a message on one channel with a journey template, conditions, overrides, and a send window.

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

Send nodes deliver a message on one channel (email, SMS, push, etc.). Each links to a <Doc href="/docs/journeys/build">journey template</Doc> that defines the content.

A journey can hold multiple send nodes, each with its own channel, conditions, recipient overrides, and delivery timing.

## Adding a send node

Drag a **Send** node from the palette onto the canvas, or drop it onto an edge between two nodes. Then choose the channel.

### Supported channels

| Channel             | Description                                                                                                                           |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| **Email**           | Messages delivered to the recipient's email address                                                                                   |
| **SMS**             | Text messages via configured SMS provider                                                                                             |
| **Push**            | Mobile or web push notifications                                                                                                      |
| **In-app / Inbox**  | Messages delivered to Courier's <Doc href="/docs/in-app/overview">Inbox</Doc> component                                                    |
| **Slack**           | Direct messages or channel posts in a connected <Doc href="/docs/integrations/direct-message/slack">Slack</Doc> workspace                  |
| **Microsoft Teams** | Direct messages or channel posts in a connected <Doc href="/docs/integrations/direct-message/microsoft-teams">Microsoft Teams</Doc> tenant |

<Frame caption="Send node configuration panel with an email channel selected and a linked message template">
  <img src="https://mintcdn.com/courier-4f1f25dc/rYENcCCTyPPrDtw0/assets/send-node-config.webp?fit=max&auto=format&n=rYENcCCTyPPrDtw0&q=85&s=cc992b3b650d6bde0ac2637f5f48f957" width="3446" height="1922" data-path="assets/send-node-config.webp" />
</Frame>

## A/B test with an experiment

A send node can run an **experiment** to A/B test versions of a message. The node holds 2 to 10 **variants**, each linked to its own <Doc href="/docs/journeys/build">journey template</Doc>. Courier splits traffic across them by weight.

Each recipient is assigned one variant deterministically and stays in it across sends. You compare delivery and engagement per variant, then promote one. A send node uses either a single template or an experiment, not both.

For traffic allocation, bucketing keys, stickiness, results, and promotion, see <Doc href="/docs/journeys/experiments">Experiments</Doc>.

## Recipient override

By default, a send node delivers to the user who entered the journey, identified by the `user_id` or `profile` from the <Doc href="/docs/journeys/invoke">invocation</Doc>.

To send to a different recipient, click **Add** next to "Recipient Override" in the node's configuration panel. In the single field that opens, either:

* **Select a field reference** from the dropdown. It lists fields from the trigger schema, profile, and upstream fetch node responses. At runtime, that field's value becomes the recipient address.
* **Type a hardcoded value** (e.g., `ops@yourcompany.com` or `+15551234567`). Type your value and click away to commit it.

The field Courier writes to depends on the channel:

| Channel         | Recipient field                                                                             |
| --------------- | ------------------------------------------------------------------------------------------- |
| Email           | `email`                                                                                     |
| SMS             | `phone_number`                                                                              |
| Push / Inbox    | `email` (user lookup)                                                                       |
| Slack           | **Channel**: channel ID. **Direct message**: user ID or email                               |
| Microsoft Teams | **Channel**: channel ID, or channel name with team ID. **Direct message**: user ID or email |

Click **Remove** to revert to the default recipient.

Slack and Microsoft Teams have no journey user to fall back on, so you always set their fields on the node. Neither offers a recipient override.

<Frame caption="Recipient override with the dropdown showing available schema and profile fields">
  <img src="https://mintcdn.com/courier-4f1f25dc/rYENcCCTyPPrDtw0/assets/recipient-override-dropdown.webp?fit=max&auto=format&n=rYENcCCTyPPrDtw0&q=85&s=e70928dc71454383e266e68b022cade0" width="3450" height="1920" data-path="assets/recipient-override-dropdown.webp" />
</Frame>

Add a schema field like `manager_email` to your API trigger, then select it as the recipient override on a send node. Your application then controls who receives that notification without changing the journey.

## Slack recipients

A Slack send node needs a destination and an **Access Token** for the workspace it posts into.

Set the destination with **Send to**:

* **Channel** posts to a Slack channel. Enter the channel ID, like `C012AB3CD`. Courier does not list your channels, so bring the ID from Slack.
* **Direct message** goes to one person, addressed by **User ID** (like `U01AB2CD3EF`) or **Email**.

Then set **Access Token** to the bot token (`xoxb-...`) for that workspace. Point it at `profile.slack.access_token` or a tenant property so each send picks up the right one.

These map onto the fields the Send API uses:

| Send to        | `to.slack` field         |
| -------------- | ------------------------ |
| Channel        | `channel`                |
| Direct message | `user_id` **or** `email` |
| Every send     | `access_token`           |

For message content, Block Kit layouts, threading, and provider overrides, see the <Doc href="/docs/integrations/direct-message/slack">Slack integration</Doc>.

## Microsoft Teams recipients

A Teams send node needs a destination, a **Service URL**, and sometimes a **Microsoft tenant ID**.

Set the destination with **Send to**:

* **Channel** posts to a Teams channel. Under **Identify channel by**, choose **Channel ID**, or **Channel Name** plus the **Team ID** that channel belongs to.
* **Direct message** goes to one person. Under **Identify user by**, choose **User ID** or **Email**.

The **Service URL** is regional, like `https://smba.trafficmanager.net/amer`. **Microsoft tenant ID** is needed when you address a direct message by user ID or email, or a channel by channel name.

These map onto the fields the Send API uses:

| Send to        | `to.ms_teams` field                                                                |
| -------------- | ---------------------------------------------------------------------------------- |
| Channel        | `channel_id`, **or** `channel_name` with `team_id`                                 |
| Direct message | `user_id` **or** `email`                                                           |
| Every send     | `service_url`, plus `tenant_id` when addressing by user ID, email, or channel name |

For adaptive cards, thread replies, and provider overrides, see the <Doc href="/docs/integrations/direct-message/microsoft-teams">Microsoft Teams integration</Doc>.

## Conditions

A send node can carry conditions, evaluated at runtime. If they are not met, the node is skipped and the journey continues to the next step.

Conditions use the same operators and field references as <Doc href="/docs/journeys/nodes/branch">branch nodes</Doc>. Common patterns:

* Skip a push notification if `profile.push_tokens` is empty
* Only send an email if `data.notification_preference` equals `"email"`
* Send only when a fetch node response indicates the user hasn't completed an action

## Send window

A send window controls when a message is delivered. If the run reaches a send node outside the window, delivery is held until the window opens.

Use it to respect business hours, avoid late-night messages, or batch sends into a time range.

<Frame caption="Send window configuration with per-day time ranges and timezone selection">
  <img src="https://mintcdn.com/courier-4f1f25dc/rYENcCCTyPPrDtw0/assets/send-window-config.webp?fit=max&auto=format&n=rYENcCCTyPPrDtw0&q=85&s=014997c2dd7ff2bdf3b8faabaeb0985e" width="1614" height="1060" data-path="assets/send-window-config.webp" />
</Frame>

Enable a send window in the send node's settings:

* **Day-by-day schedule**: Each day of the week has its own row with an opening and closing time (e.g., Mon through Fri, 9:00 AM to 5:00 PM). A day with no time range is blocked entirely.
* **Timezone**: Choose **User's** timezone (resolved from the recipient's profile) or **UTC**. If the recipient has no timezone set, messages are sent in UTC.

## Provider resolution

Courier picks the provider from your workspace's configured integrations. A send node never specifies one.

For example, if your workspace has SendGrid configured for email, an email send node routes through SendGrid with no configuration on the node.

With multiple providers on the same channel, Courier follows your <Doc href="/docs/send/routing#channel-priority">routing rules</Doc>.
