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

# Send to Many People

> Blasts vs Audiences: when to use each, how to create and send to both, and campaign volume caps.

Surge has two mechanisms for sending to multiple recipients: **Blasts** for one-time sends and **Audiences** for reusable contact lists. The choice between them depends on whether the same group of people will receive messages more than once.

## Blasts vs Audiences

**Use a Blast** when you have a list of recipients you're assembling specifically for this send. You pass the recipient list at send time and don't need to maintain it afterward — weekly flash sales, event announcements, one-time notifications.

**Use an Audience** when the same group of people receives messages regularly. You maintain the audience over time (adding and removing contacts), then blast the whole audience — weekly newsletters, customer cohorts, or geographic segments.

Both send the same underlying message; the difference is how you manage the recipient list.

***

## Blasts

### Send to a list of phone numbers

The simplest case: pass <Tooltip tip="International phone number format: starts with +, country code, then subscriber number, no spaces or punctuation. Example: +18015551234.">E.164</Tooltip> phone numbers directly in the `to` array.

<CodeGroup>
  ```python Python theme={null}
  from surge import Surge

  surge = Surge()

  blast = surge.blasts.create(
      account_id="{account_id}",
      from_="pn_01jrzhe8d9enptypyx360pcmxm",
      body="Flash sale: 30% off everything this weekend. Shop at acme.com/sale",
      to=["+18015551234", "+18025551234", "+18035551234"],
  )
  ```

  ```typescript TypeScript theme={null}
  import Surge from "@surgeapi/node";

  const surge = new Surge();

  const blast = await surge.blasts.create("{account_id}", {
    from: "pn_01jrzhe8d9enptypyx360pcmxm",
    body: "Flash sale: 30% off everything this weekend. Shop at acme.com/sale",
    to: ["+18015551234", "+18025551234", "+18035551234"],
  });
  ```

  ```ruby Ruby theme={null}
  require "surge_api"

  surge = SurgeAPI::Client.new

  blast = surge.blasts.create(
    "{account_id}",
    from_: "pn_01jrzhe8d9enptypyx360pcmxm",
    body: "Flash sale: 30% off everything this weekend. Shop at acme.com/sale",
    to: ["+18015551234", "+18025551234", "+18035551234"]
  )
  ```

  ```elixir Elixir theme={null}
  client = Surge.Client.new(System.get_env("SURGE_API_KEY"))

  {:ok, blast} =
    Surge.Blasts.create(client, "{account_id}", %{
      from: "pn_01jrzhe8d9enptypyx360pcmxm",
      body: "Flash sale: 30% off everything this weekend. Shop at acme.com/sale",
      to: ["+18015551234", "+18025551234", "+18035551234"]
    })
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.surge.app/accounts/{account_id}/blasts \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "from": "pn_01jrzhe8d9enptypyx360pcmxm",
      "body": "Flash sale: 30% off everything this weekend. Shop at acme.com/sale",
      "to": ["+18015551234", "+18025551234", "+18035551234"]
    }'
  ```
</CodeGroup>

### Send to contacts

Pass contact IDs (with `ctc_` prefix) instead of phone numbers. This links the blast to your contact records for tracking and opt-out management.

<CodeGroup>
  ```python Python theme={null}
  blast = surge.blasts.create(
      account_id="{account_id}",
      from_="pn_01jrzhe8d9enptypyx360pcmxm",
      body="Your subscription renews tomorrow. Manage it at acme.com/account",
      to=[
          "ctc_01jrzhe8d9enptypyx360pcmxa",
          "ctc_01jrzhe8d9enptypyx360pcmxb",
          "ctc_01jrzhe8d9enptypyx360pcmxc",
      ],
  )
  ```

  ```typescript TypeScript theme={null}
  const blast = await surge.blasts.create("{account_id}", {
    from: "pn_01jrzhe8d9enptypyx360pcmxm",
    body: "Your subscription renews tomorrow. Manage it at acme.com/account",
    to: [
      "ctc_01jrzhe8d9enptypyx360pcmxa",
      "ctc_01jrzhe8d9enptypyx360pcmxb",
      "ctc_01jrzhe8d9enptypyx360pcmxc",
    ],
  });
  ```

  ```ruby Ruby theme={null}
  blast = surge.blasts.create(
    "{account_id}",
    from_: "pn_01jrzhe8d9enptypyx360pcmxm",
    body: "Your subscription renews tomorrow. Manage it at acme.com/account",
    to: [
      "ctc_01jrzhe8d9enptypyx360pcmxa",
      "ctc_01jrzhe8d9enptypyx360pcmxb",
      "ctc_01jrzhe8d9enptypyx360pcmxc"
    ]
  )
  ```

  ```elixir Elixir theme={null}
  {:ok, blast} =
    Surge.Blasts.create(client, "{account_id}", %{
      from: "pn_01jrzhe8d9enptypyx360pcmxm",
      body: "Your subscription renews tomorrow. Manage it at acme.com/account",
      to: [
        "ctc_01jrzhe8d9enptypyx360pcmxa",
        "ctc_01jrzhe8d9enptypyx360pcmxb",
        "ctc_01jrzhe8d9enptypyx360pcmxc"
      ]
    })
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.surge.app/accounts/{account_id}/blasts \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "from": "pn_01jrzhe8d9enptypyx360pcmxm",
      "body": "Your subscription renews tomorrow. Manage it at acme.com/account",
      "to": [
        "ctc_01jrzhe8d9enptypyx360pcmxa",
        "ctc_01jrzhe8d9enptypyx360pcmxb",
        "ctc_01jrzhe8d9enptypyx360pcmxc"
      ]
    }'
  ```
</CodeGroup>

### Schedule a blast

Add `send_at` to queue the blast for a future time:

<CodeGroup>
  ```python Python theme={null}
  blast = surge.blasts.create(
      account_id="{account_id}",
      name="April sale launch",
      from_="pn_01jrzhe8d9enptypyx360pcmxm",
      body="Acme Corp: Our biggest sale of the year starts now. Shop: acme.com/spring",
      to=["+18015551234", "+18025551234", "+18035551234"],
      send_at="2026-06-01T09:00:00Z",
  )
  ```

  ```typescript TypeScript theme={null}
  const blast = await surge.blasts.create("{account_id}", {
    name: "April sale launch",
    from: "pn_01jrzhe8d9enptypyx360pcmxm",
    body: "Acme Corp: Our biggest sale of the year starts now. Shop: acme.com/spring",
    to: ["+18015551234", "+18025551234", "+18035551234"],
    send_at: "2026-06-01T09:00:00Z",
  });
  ```

  ```ruby Ruby theme={null}
  blast = surge.blasts.create(
    "{account_id}",
    name: "April sale launch",
    from_: "pn_01jrzhe8d9enptypyx360pcmxm",
    body: "Acme Corp: Our biggest sale of the year starts now. Shop: acme.com/spring",
    to: ["+18015551234", "+18025551234", "+18035551234"],
    send_at: "2026-06-01T09:00:00Z"
  )
  ```

  ```elixir Elixir theme={null}
  {:ok, blast} =
    Surge.Blasts.create(client, "{account_id}", %{
      name: "April sale launch",
      from: "pn_01jrzhe8d9enptypyx360pcmxm",
      body: "Acme Corp: Our biggest sale of the year starts now. Shop: acme.com/spring",
      to: ["+18015551234", "+18025551234", "+18035551234"],
      send_at: "2026-06-01T09:00:00Z"
    })
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.surge.app/accounts/{account_id}/blasts \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "April sale launch",
      "from": "pn_01jrzhe8d9enptypyx360pcmxm",
      "body": "Acme Corp: Our biggest sale of the year starts now. Shop: acme.com/spring",
      "to": ["+18015551234", "+18025551234", "+18035551234"],
      "send_at": "2026-06-01T09:00:00Z"
    }'
  ```
</CodeGroup>

***

## Audiences

### Create an audience

An audience is a named contact list. Create it first, then populate it.

<CodeGroup>
  ```python Python theme={null}
  audience = surge.audiences.create(
      account_id="{account_id}",
      name="Premium subscribers",
  )
  ```

  ```typescript TypeScript theme={null}
  const audience = await surge.audiences.create("{account_id}", {
    name: "Premium subscribers",
  });
  ```

  ```ruby Ruby theme={null}
  audience = surge.audiences.create(
    "{account_id}",
    name: "Premium subscribers"
  )
  ```

  ```elixir Elixir theme={null}
  # Surge.Audiences isn't typed in the Elixir SDK yet — use the raw client.
  {:ok, audience} =
    Surge.Client.request(client, :post, "/accounts/{account_id}/audiences",
      json: %{name: "Premium subscribers"}
    )
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.surge.app/accounts/{account_id}/audiences \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Premium subscribers"
    }'
  ```
</CodeGroup>

```json theme={null}
{
  "id": "aud_01jrzhe8d9enptypyx360pcmxz",
  "name": "Premium subscribers"
}
```

### Add contacts to the audience

<CodeGroup>
  ```python Python theme={null}
  surge.audiences.add_contact(
      audience_id="aud_01jrzhe8d9enptypyx360pcmxz",
      id="ctc_01jrzhe8d9enptypyx360pcmxa",
  )
  ```

  ```typescript TypeScript theme={null}
  await surge.audiences.addContact("aud_01jrzhe8d9enptypyx360pcmxz", {
    id: "ctc_01jrzhe8d9enptypyx360pcmxa",
  });
  ```

  ```ruby Ruby theme={null}
  surge.audiences.add_contact(
    "aud_01jrzhe8d9enptypyx360pcmxz",
    id: "ctc_01jrzhe8d9enptypyx360pcmxa"
  )
  ```

  ```elixir Elixir theme={null}
  {:ok, _} =
    Surge.Client.request(client, :post,
      "/audiences/aud_01jrzhe8d9enptypyx360pcmxz/contacts",
      json: %{id: "ctc_01jrzhe8d9enptypyx360pcmxa"}
    )
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.surge.app/audiences/aud_01jrzhe8d9enptypyx360pcmxz/contacts \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "id": "ctc_01jrzhe8d9enptypyx360pcmxa"
    }'
  ```
</CodeGroup>

Repeat for each contact, or build this into the workflow that creates or updates contacts.

### Blast the audience

Pass the audience ID in the `to` array.

<Note>
  Surge expands the audience at send time and applies opt-out status automatically — opted-out contacts are skipped, so you never need to filter the list yourself.
</Note>

<CodeGroup>
  ```python Python theme={null}
  blast = surge.blasts.create(
      account_id="{account_id}",
      from_="pn_01jrzhe8d9enptypyx360pcmxm",
      body="Your monthly update from Acme Corp: acme.com/newsletter/april",
      to=["aud_01jrzhe8d9enptypyx360pcmxz"],
  )
  ```

  ```typescript TypeScript theme={null}
  const blast = await surge.blasts.create("{account_id}", {
    from: "pn_01jrzhe8d9enptypyx360pcmxm",
    body: "Your monthly update from Acme Corp: acme.com/newsletter/april",
    to: ["aud_01jrzhe8d9enptypyx360pcmxz"],
  });
  ```

  ```ruby Ruby theme={null}
  blast = surge.blasts.create(
    "{account_id}",
    from_: "pn_01jrzhe8d9enptypyx360pcmxm",
    body: "Your monthly update from Acme Corp: acme.com/newsletter/april",
    to: ["aud_01jrzhe8d9enptypyx360pcmxz"]
  )
  ```

  ```elixir Elixir theme={null}
  {:ok, blast} =
    Surge.Blasts.create(client, "{account_id}", %{
      from: "pn_01jrzhe8d9enptypyx360pcmxm",
      body: "Your monthly update from Acme Corp: acme.com/newsletter/april",
      to: ["aud_01jrzhe8d9enptypyx360pcmxz"]
    })
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.surge.app/accounts/{account_id}/blasts \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "from": "pn_01jrzhe8d9enptypyx360pcmxm",
      "body": "Your monthly update from Acme Corp: acme.com/newsletter/april",
      "to": ["aud_01jrzhe8d9enptypyx360pcmxz"]
    }'
  ```
</CodeGroup>

You can mix audience IDs, contact IDs, and raw phone numbers in the same `to` array.

***

## Volume caps

Campaign volume limits apply to all sends, including blasts:

| Campaign volume | T-Mobile limit                                              |
| --------------- | ----------------------------------------------------------- |
| `low`           | 2,000 SMS segments per day                                  |
| `high`          | Up to 200,000 segments per day (subject to TCR trust score) |

Surge queues messages within your daily cap and delivers them in order. If you regularly approach the `low` cap, request a volume increase through support after your campaign is approved.

***

## Tracking a blast

Blast-level delivery metrics (deliverability rate, opt-out rate) are available in the dashboard under the Blasts section. Per-message delivery status comes through the `message.sent`, `message.delivered`, and `message.failed` webhook events — see [Track Message Delivery](./track-delivery) for the full mechanism.
