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

# Send a broadcast

> Create, schedule, and send a broadcast from the console or the API.

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

A Broadcast sends one message to a whole List or Audience, now or on a schedule.

## Send from the console

<Steps>
  <Step title="Create the Broadcast">
    In the console, open **Broadcasts** under **Orchestration** and select **Add broadcast**. Name it and pick a channel. Each Broadcast sends on one channel.

    <Frame>
      <img src="https://mintcdn.com/courier-4f1f25dc/LdpdyPjJHKHJqFY9/assets/broadcast-add-new-broadcast.webp?fit=max&auto=format&n=LdpdyPjJHKHJqFY9&q=85&s=1f127c70480698f1f941834ffe55d65a" alt="The Add a new broadcast modal: a Name field and channel options for Email, SMS, and In-App" className="mx-auto" width="1752" height="1256" data-path="assets/broadcast-add-new-broadcast.webp" />
    </Frame>
  </Step>

  <Step title="Design the content">
    Drag blocks onto the canvas, the same editor as a Template. Variables resolve from each recipient's Profile.

    <Frame>
      <img src="https://mintcdn.com/courier-4f1f25dc/LdpdyPjJHKHJqFY9/assets/broadcast-create-design-editor.webp?fit=max&auto=format&n=LdpdyPjJHKHJqFY9&q=85&s=418e672fdb6bcc1625e7828c97280c7f" alt="The broadcast design editor: the blocks panel on the left, the email canvas in the center, and Email styles on the right" width="1200" height="831" data-path="assets/broadcast-create-design-editor.webp" />
    </Frame>
  </Step>

  <Step title="Choose recipients">
    Open **Recipients** and pick a <Doc href="/docs/recipients/lists-and-audiences/lists">List</Doc> you curate by hand, or an <Doc href="/docs/recipients/lists-and-audiences/audiences">Audience</Doc> Courier keeps current from rules.

    <Frame>
      <img src="https://mintcdn.com/courier-4f1f25dc/LdpdyPjJHKHJqFY9/assets/broadcast-recipients-dropdown.webp?fit=max&auto=format&n=LdpdyPjJHKHJqFY9&q=85&s=c249ec837329c452a82313f34d5cb1fb" alt="The broadcast Recipients dropdown open, listing lists and audiences alongside the send-time fields" className="mx-auto" width="1186" height="732" data-path="assets/broadcast-recipients-dropdown.webp" />
    </Frame>
  </Step>

  <Step title="Send or schedule">
    Send now, or schedule a date, time, and timezone. A scheduled Broadcast locks its content. To change the message, cancel, edit, and schedule again.

    <Frame>
      <img src="https://mintcdn.com/courier-4f1f25dc/LdpdyPjJHKHJqFY9/assets/broadcast-schedule-details.webp?fit=max&auto=format&n=LdpdyPjJHKHJqFY9&q=85&s=f19098c8935951e6578f1989ca7f6cc7" alt="The broadcast send panel with Scheduled selected, showing date, time, and timezone" width="1044" height="700" data-path="assets/broadcast-schedule-details.webp" />
    </Frame>
  </Step>

  <Step title="Check performance">
    After it sends, the <Doc href="/docs/monitor/broadcast-performance">**Performance** tab</Doc> reports delivery, open, click, and error rates, plus a per-recipient log.

    <Frame>
      <img src="https://mintcdn.com/courier-4f1f25dc/LdpdyPjJHKHJqFY9/assets/broadcast-performance.webp?fit=max&auto=format&n=LdpdyPjJHKHJqFY9&q=85&s=de242699501487e48013e642be593f69" alt="The Performance tab for a sent broadcast" width="1200" height="646" data-path="assets/broadcast-performance.webp" />
    </Frame>
  </Step>
</Steps>

## Send with the API

<Steps>
  <Step title="Create the Broadcast">
    <Endpoint method="POST" path="/broadcasts" name="Create Broadcast" href="/docs/api-reference/broadcasts/create-broadcast" /> takes a name and one channel, and returns the Broadcast ID. `channel` is one of `email`, `sms`, `push`, `inbox`, `slack`, or `msteams`.

    <CodeGroup>
      ```javascript Node.js highlight={3} theme={null}
      const broadcast = await client.broadcasts.create({
        name: 'March product update',
        channel: 'email',
      });
      ```

      ```python Python highlight={3} theme={null}
      broadcast = client.broadcasts.create(
          name="March product update",
          channel="email",
      )
      ```

      ```bash cURL highlight={5} theme={null}
      curl --request POST \
        --url https://api.courier.com/broadcasts \
        --header "Authorization: Bearer $COURIER_API_KEY" \
        --header "Content-Type: application/json" \
        --data '{ "name": "March product update", "channel": "email" }'
      ```

      ```ruby Ruby theme={null}
      broadcast = courier.broadcasts.create(name: "March product update", channel: "email")
      ```

      ```go Go highlight={4} theme={null}
      broadcast, err := client.Broadcasts.New(context.TODO(), courier.BroadcastNewParams{
      	CreateBroadcastRequest: courier.CreateBroadcastRequestParam{
      		Name:    "March product update",
      		Channel: "email",
      	},
      })
      ```

      ```java Java highlight={3} theme={null}
      CreateBroadcastRequest params = CreateBroadcastRequest.builder()
          .name("March product update")
          .channel(CreateBroadcastRequest.Channel.EMAIL)
          .build();
      Broadcast broadcast = client.broadcasts().create(params);
      ```

      ```php PHP highlight={3} theme={null}
      $broadcast = $client->broadcasts->create(
        name: 'March product update',
        channel: 'email',
      );
      ```

      ```csharp C# highlight={4} theme={null}
      BroadcastCreateParams parameters = new()
      {
          Name = "March product update",
          Channel = "email",
      };

      var broadcast = await client.Broadcasts.Create(parameters);
      ```

      ```bash CLI highlight={4} theme={null}
      courier broadcasts create \
        --api-key "$COURIER_API_KEY" \
        --name "March product update" \
        --channel email
      ```
    </CodeGroup>
  </Step>

  <Step title="Write the content">
    <Endpoint method="PUT" path="/broadcasts/{broadcastId}/content" name="Update Broadcast content" href="/docs/api-reference/broadcasts/update-broadcast-content" /> takes the same Elemental document a Template uses.

    <CodeGroup>
      ```javascript Node.js theme={null}
      await client.broadcasts.putContent('YOUR_BROADCAST_ID', {
        content: {
          version: '2022-01-01',
          elements: [{ type: 'text', content: 'Here is what shipped in March.' }],
        },
      });
      ```

      ```python Python theme={null}
      client.broadcasts.put_content(
          broadcast_id="YOUR_BROADCAST_ID",
          content={
              "version": "2022-01-01",
              "elements": [{"type": "text", "content": "Here is what shipped in March."}],
          },
      )
      ```

      ```bash cURL theme={null}
      curl --request PUT \
        --url https://api.courier.com/broadcasts/YOUR_BROADCAST_ID/content \
        --header "Authorization: Bearer $COURIER_API_KEY" \
        --header "Content-Type: application/json" \
        --data '{
          "content": {
            "version": "2022-01-01",
            "elements": [{ "type": "text", "content": "Here is what shipped in March." }]
          }
        }'
      ```

      ```ruby Ruby theme={null}
      courier.broadcasts.put_content(
        "YOUR_BROADCAST_ID",
        content: {elements: [{type: "text", content: "Here is what shipped in March."}], version: "2022-01-01"}
      )
      ```

      ```go Go theme={null}
      // Elemental nodes carry no typed content field, so set it as an extra field.
      textNode := shared.ElementalTextNodeWithTypeParam{Type: "text"}
      textNode.SetExtraFields(map[string]any{"content": "Here is what shipped in March."})

      _, err := client.Broadcasts.PutContent(
      	context.TODO(),
      	"YOUR_BROADCAST_ID",
      	courier.BroadcastPutContentParams{
      		NotificationContentPutRequest: courier.NotificationContentPutRequestParam{
      			Content: courier.NotificationContentPutRequestContentParam{
      				Elements: []shared.ElementalNodeUnionParam{{
      					OfElementalTextNodeWithType: &textNode,
      				}},
      				Version: courier.String("2022-01-01"),
      			},
      		},
      	},
      )
      ```

      ```java Java theme={null}
      BroadcastPutContentParams params = BroadcastPutContentParams.builder()
          .broadcastId("YOUR_BROADCAST_ID")
          .notificationContentPutRequest(NotificationContentPutRequest.builder()
              .content(NotificationContentPutRequest.Content.builder()
                  .addElement(ElementalTextNodeWithType.builder()
                      .type(ElementalTextNodeWithType.Type.TEXT)
                      .putAdditionalProperty("content", JsonValue.from("Here is what shipped in March."))
                      .build())
                  .version("2022-01-01")
                  .build())
              .build())
          .build();
      client.broadcasts().putContent(params);
      ```

      ```php PHP theme={null}
      $client->broadcasts->putContent(
        'YOUR_BROADCAST_ID',
        content: ['elements' => [['type' => 'text', 'content' => 'Here is what shipped in March.']], 'version' => '2022-01-01'],
      );
      ```

      ```csharp C# theme={null}
      BroadcastPutContentParams parameters = new()
      {
          BroadcastID = "YOUR_BROADCAST_ID",
          Content = new()
          {
              // Elemental nodes expose no typed content property, so build the node from raw JSON.
              Elements =
              [
                  ElementalTextNodeWithType.FromRawUnchecked(
                      JsonSerializer.Deserialize<Dictionary<string, JsonElement>>("""
                      { "type": "text", "content": "Here is what shipped in March." }
                      """)),
              ],
              Version = "2022-01-01",
          },
      };

      await client.Broadcasts.PutContent(parameters);
      ```

      ```bash CLI theme={null}
      courier broadcasts put-content \
        --api-key "$COURIER_API_KEY" \
        --broadcast-id YOUR_BROADCAST_ID \
        --content '{"version":"2022-01-01","elements":[{"type":"text","content":"Here is what shipped in March."}]}'
      ```
    </CodeGroup>
  </Step>

  <Step title="Send it">
    <Endpoint method="POST" path="/broadcasts/{broadcastId}/send" name="Send Broadcast" href="/docs/api-reference/broadcasts/send-broadcast" /> targets a List or an Audience and sends immediately.

    <CodeGroup>
      ```javascript Node.js theme={null}
      await client.broadcasts.send('YOUR_BROADCAST_ID', {
        recipient_type: 'list',
        recipient_id: 'acme-corp.beta-testers',
      });
      ```

      ```python Python theme={null}
      client.broadcasts.send(
          broadcast_id="YOUR_BROADCAST_ID",
          recipient_type="list",
          recipient_id="acme-corp.beta-testers",
      )
      ```

      ```bash cURL theme={null}
      curl --request POST \
        --url https://api.courier.com/broadcasts/YOUR_BROADCAST_ID/send \
        --header "Authorization: Bearer $COURIER_API_KEY" \
        --header "Content-Type: application/json" \
        --data '{ "recipient_type": "list", "recipient_id": "acme-corp.beta-testers" }'
      ```

      ```ruby Ruby theme={null}
      courier.broadcasts.send_(
        "YOUR_BROADCAST_ID",
        recipient_type: "list",
        recipient_id: "acme-corp.beta-testers"
      )
      ```

      ```go Go theme={null}
      _, err := client.Broadcasts.Send(
      	context.TODO(),
      	"YOUR_BROADCAST_ID",
      	courier.BroadcastSendParams{
      		SendBroadcastRequest: courier.SendBroadcastRequestParam{
      			RecipientType: "list",
      			RecipientID:   "acme-corp.beta-testers",
      		},
      	},
      )
      ```

      ```java Java theme={null}
      BroadcastSendParams params = BroadcastSendParams.builder()
          .broadcastId("YOUR_BROADCAST_ID")
          .sendBroadcastRequest(SendBroadcastRequest.builder()
              .recipientType(SendBroadcastRequest.RecipientType.LIST)
              .recipientId("acme-corp.beta-testers")
              .build())
          .build();
      client.broadcasts().send(params);
      ```

      ```php PHP theme={null}
      $client->broadcasts->send(
        'YOUR_BROADCAST_ID',
        recipientType: 'list',
        recipientID: 'acme-corp.beta-testers',
      );
      ```

      ```csharp C# theme={null}
      BroadcastSendParams parameters = new()
      {
          BroadcastID = "YOUR_BROADCAST_ID",
          RecipientType = "list",
          RecipientID = "acme-corp.beta-testers",
      };

      await client.Broadcasts.Send(parameters);
      ```

      ```bash CLI theme={null}
      courier broadcasts send \
        --api-key "$COURIER_API_KEY" \
        --broadcast-id YOUR_BROADCAST_ID \
        --recipient-type list \
        --recipient-id acme-corp.beta-testers
      ```
    </CodeGroup>
  </Step>

  <Step title="Or schedule it">
    <Endpoint method="POST" path="/broadcasts/{broadcastId}/schedule" name="Schedule Broadcast" href="/docs/api-reference/broadcasts/schedule-broadcast" /> takes a wall-clock `scheduled_to` with no offset, so the zone comes from `timezone`.

    <CodeGroup>
      ```javascript Node.js highlight={4} theme={null}
      await client.broadcasts.schedule('YOUR_BROADCAST_ID', {
        recipient_type: 'audience',
        recipient_id: 'active-business-users',
        scheduled_to: '2026-07-21T20:00:00',
        timezone: 'America/New_York',
      });
      ```

      ```python Python highlight={5} theme={null}
      client.broadcasts.schedule(
          broadcast_id="YOUR_BROADCAST_ID",
          recipient_type="audience",
          recipient_id="active-business-users",
          scheduled_to="2026-07-21T20:00:00",
          timezone="America/New_York",
      )
      ```

      ```bash cURL highlight={8} theme={null}
      curl --request POST \
        --url https://api.courier.com/broadcasts/YOUR_BROADCAST_ID/schedule \
        --header "Authorization: Bearer $COURIER_API_KEY" \
        --header "Content-Type: application/json" \
        --data '{
          "recipient_type": "audience",
          "recipient_id": "active-business-users",
          "scheduled_to": "2026-07-21T20:00:00",
          "timezone": "America/New_York"
        }'
      ```

      ```ruby Ruby highlight={5} theme={null}
      courier.broadcasts.schedule(
        "YOUR_BROADCAST_ID",
        recipient_type: "audience",
        recipient_id: "active-business-users",
        scheduled_to: "2026-07-21T20:00:00",
        timezone: "America/New_York"
      )
      ```

      ```go Go highlight={8} theme={null}
      _, err := client.Broadcasts.Schedule(
      	context.TODO(),
      	"YOUR_BROADCAST_ID",
      	courier.BroadcastScheduleParams{
      		ScheduleBroadcastRequest: courier.ScheduleBroadcastRequestParam{
      			RecipientType: "audience",
      			RecipientID:   "active-business-users",
      			ScheduledTo:   "2026-07-21T20:00:00",
      			Timezone:      courier.String("America/New_York"),
      		},
      	},
      )
      ```

      ```java Java highlight={6} theme={null}
      BroadcastScheduleParams params = BroadcastScheduleParams.builder()
          .broadcastId("YOUR_BROADCAST_ID")
          .scheduleBroadcastRequest(ScheduleBroadcastRequest.builder()
              .recipientType(ScheduleBroadcastRequest.RecipientType.AUDIENCE)
              .recipientId("active-business-users")
              .scheduledTo("2026-07-21T20:00:00")
              .timezone("America/New_York")
              .build())
          .build();
      client.broadcasts().schedule(params);
      ```

      ```php PHP highlight={5} theme={null}
      $client->broadcasts->schedule(
        'YOUR_BROADCAST_ID',
        recipientType: 'audience',
        recipientID: 'active-business-users',
        scheduledTo: '2026-07-21T20:00:00',
        timezone: 'America/New_York',
      );
      ```

      ```csharp C# highlight={6} theme={null}
      BroadcastScheduleParams parameters = new()
      {
          BroadcastID = "YOUR_BROADCAST_ID",
          RecipientType = "audience",
          RecipientID = "active-business-users",
          ScheduledTo = "2026-07-21T20:00:00",
          Timezone = "America/New_York",
      };

      await client.Broadcasts.Schedule(parameters);
      ```

      ```bash CLI highlight={6} theme={null}
      courier broadcasts schedule \
        --api-key "$COURIER_API_KEY" \
        --broadcast-id YOUR_BROADCAST_ID \
        --recipient-type audience \
        --recipient-id active-business-users \
        --scheduled-to "2026-07-21T20:00:00" \
        --timezone America/New_York
      ```
    </CodeGroup>

    <Endpoint method="POST" path="/broadcasts/{broadcastId}/cancel" name="Cancel Broadcast schedule" href="/docs/api-reference/broadcasts/cancel-broadcast-schedule" /> cancels a scheduled send, and <Endpoint method="POST" path="/broadcasts/{broadcastId}/duplicate" name="Duplicate Broadcast" href="/docs/api-reference/broadcasts/duplicate-broadcast" /> copies one for a repeat.
  </Step>
</Steps>
