Skip to the page

API reference

Send a broadcast

Sends one text to up to 500 people: contacts with any of tags, the contacts in contact_ids, or a list in recipients (people who aren’t contacts yet are added).

POST/v1/broadcasts

Sends one text to up to 500 people: contacts with any of tags, the contacts in contact_ids, or a list in recipients (people who aren’t contacts yet are added). Each person’s {{variables}} are filled in from their contact and their row.

Texts go through your sending rules like any other: your pace, quiet hours, the daily limit for new people and BlueBot’s daily limit. BlueBot feeds them into the queue a few at a time, so a long broadcast never sits in the queue long enough to expire. People on your stop list are skipped. estimate says when the last text should go.

Only send to people who asked to hear from you.

Needs a key with the messages:send scope. Keys and scopes

Send an Idempotency-Key so a retry never acts twice. Idempotency

Headers

  • Idempotency-Keystring

    Any string of up to 255 characters, new for each request. A retry with the same key gets the first answer back for 24 hours, with Idempotent-Replayed: true.

    Up to 255 characters.

Request body

  • namestringrequired

    Up to 120 characters.

  • textstring

    The words. {{first_name}}, {{first_name|there}} and any variable your list brings are filled in for each person.

    Up to 2,000 characters.

  • template_idstring

    A saved template to use instead of text.

    Starts with tpl_.

  • tagsarray of strings

    Send to your contacts with any of these tags.

    Up to 20 items.

  • contact_idsarray of strings

    Send to these contacts.

    Up to 500 items.

  • recipientsarray of object

    Send to these people, adding any who aren’t contacts yet, each with their own variables.

    Up to 500 items.

    Show its 4 fields
    • tostringrequired

      A phone number (US numbers may leave off +1; (555) 555-0123 works) or an email address an Apple ID uses.

      3 to 320 characters.

    • first_namestring

      Up to 100 characters.

    • last_namestring

      Up to 100 characters.

    • variablesmap of string

      Values for this person’s {{variables}}.

  • servicestring

    One of auto, imessage, sms.Default "auto".

  • send_attimestamp

    Start later. Leave it out to start now.

Example

POST/v1/broadcastsSend a broadcast →
curl -X POST "https://usebluebot.com/api/v1/broadcasts" \
  -H "Authorization: Bearer $BLUEBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0f6d8c2e-5b1a-4c7e-9d3f-2a8b6e1c4d70" \
  -d '{
    "name": "Open house Saturday",
    "text": "Hi {{first_name|there}}, open house at 412 Oak St this Saturday 1–4. Reply STOP to opt out.",
    "tags": [
      "buyer"
    ],
    "send_at": "2026-11-14T15:00:00.000Z"
  }'

Response

201: The broadcast, started or scheduled.

  • idstringrequired

    A bc_ id.

    Starts with bc_.

  • object"broadcast"required
  • namestringrequired
  • textstring or nullrequired

    The words, with {{variables}}, as you wrote them. Each person’s filled-in text is on their message. Null once they’re deleted, 30 days after the broadcast finished.

  • text_deletedbooleanrequired

    True once the words, and the values each person’s list row brought, were deleted 30 days after the broadcast finished.

  • template_idstring or nullrequired

    The template the words came from, when one did.

  • audienceanyrequired

    Who the broadcast goes to.

  • servicestringrequired

    One of auto, imessage, sms.

  • statestringrequired

    draft, scheduled (waiting for send_at), sending, completed or canceled.

    One of draft, scheduled, sending, completed, canceled.

  • send_attimestamp or nullrequired

    When it starts, for a scheduled broadcast.

  • started_attimestamp or nullrequired

    When the first text was queued.

  • completed_attimestamp or nullrequired

    When every text had settled.

  • canceled_attimestamp or nullrequired

    When the rest was canceled.

  • recipient_countintegerrequired

    How many people it goes to, up to 500.

  • countsmap of integerrequired

    How many recipients are in each state: pending, queued, sent, delivered, read, failed, skipped and so on.

  • estimateBroadcastEstimate or nullrequired

    For a scheduled or sending broadcast, when the rest should go. Worked out on GET /v1/broadcasts/{id} and when it is made; null in lists.

    Show its 6 fields
    • first_attimestamp or nullrequired

      When the first text should go.

    • last_attimestamp or nullrequired

      When the last text should go, given your pace, quiet hours and daily limits.

    • daysintegerrequired

      How many days the sending spans in your time zone.

    • waits_forarray of stringsrequired

      Holds the texts will meet on the way: quiet_hours, daily_new_people_limit, platform_daily_limit.

    • blocked_bystring or nullrequired

      A hold with no end that stops the broadcast from going, such as plan_lapsed.

    • mac_onlinebooleanrequired

      Whether your Mac is online now. The estimate assumes it stays on.

  • created_viastringrequired

    One of dashboard, api, assistant, mcp, zapier, cli.

  • created_attimestamprequired

    When it was made.

Response201
{
  "id": "bc_1Hq2LxW9cVbN3mKpRtYs0a",
  "object": "broadcast",
  "name": "Open house Saturday",
  "text": "Hi {{first_name|there}}, open house at 412 Oak St this Saturday 1–4. Reply STOP to opt out.",
  "text_deleted": false,
  "template_id": null,
  "audience": {
    "kind": "tags",
    "tags": [
      "buyer"
    ]
  },
  "service": "auto",
  "state": "scheduled",
  "send_at": "2026-11-14T15:00:00.000Z",
  "started_at": null,
  "completed_at": null,
  "canceled_at": null,
  "recipient_count": 42,
  "counts": {
    "pending": 41,
    "skipped": 1
  },
  "estimate": {
    "first_at": "2026-11-14T15:00:00.000Z",
    "last_at": "2026-11-14T15:14:20.000Z",
    "days": 1,
    "waits_for": [],
    "blocked_by": null,
    "mac_online": true
  },
  "created_via": "api",
  "created_at": "2026-11-13T19:41:00.000Z"
}

Errors

Every refusal has the same envelope and a page of its own. These are the ones this operation can give.

CodeStatusWhat it means
unauthorized401The request carried no key, or a key BlueBot doesn’t know: mistyped, revoked, or a test key sent to the live API.
insufficient_scope403The key doesn’t carry the scope the endpoint needs. Each endpoint’s reference names its scope.
rate_limited429Too many requests. A key may make 120 requests a minute. The RateLimit header says how many are left, and Retry-After how long to wait.
internal500Something went wrong on BlueBot’s side. It was reported. Send the request again; with an Idempotency-Key that is always safe.
invalid_request400Something in the request doesn’t fit: a missing or malformed field, a bad id, or a combination the endpoint refuses. details names each field.
not_found404There is no such thing on this account. Ids are prefixed by kind, so a message id starts with msg_.
limit_reached409The account has as many of something as it may have.
plan_lapsed402The account’s plan isn’t active, so BlueBot isn’t taking new texts. Texts already queued wait and go once the plan is active again.
idempotency_conflict409The Idempotency-Key was used in the last 24 hours with a different request. A key stands for one request.

Try it

Call this operation from the page with your own key. The key stays in this tab and is forgotten when you leave.