Skip to the page

API reference

Check a broadcast before sending it

Answers what POST /v1/broadcasts would do with the same body, without sending anything: how many people it reaches, who is skipped, the first five texts filled in, and when the last one should go.

POST/v1/broadcasts/preview

Answers what POST /v1/broadcasts would do with the same body, without sending anything: how many people it reaches, who is skipped, the first five texts filled in, and when the last one should go.

Needs a key with the messages:read 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

  • textstring

    The words.

    Up to 2,000 characters.

  • template_idstring

    A saved template to use instead of text.

    Starts with tpl_.

  • tagsarray of strings

    Up to 20 items.

  • contact_idsarray of strings

    Up to 500 items.

  • recipientsarray of object

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

  • send_attimestamp

Example

POST/v1/broadcasts/previewCheck a broadcast before sending it →
curl -X POST "https://usebluebot.com/api/v1/broadcasts/preview" \
  -H "Authorization: Bearer $BLUEBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0f6d8c2e-5b1a-4c7e-9d3f-2a8b6e1c4d70" \
  -d '{
    "text": "Hi {{first_name|there}}, open house at 412 Oak St this Saturday 1–4.",
    "tags": [
      "buyer"
    ]
  }'

Response

200: What it would do.

  • object"broadcast_preview"required
  • recipient_countintegerrequired

    Everyone it would go to, counting people on your stop list.

  • stopped_countintegerrequired

    People on your stop list, who won’t get it.

  • new_people_countintegerrequired

    People you have never texted, who count toward your daily limit for new people.

  • duplicate_countintegerrequired

    Rows dropped because the same person was already in the list.

  • samplesarray of objectrequired

    The first five people’s texts.

    Show its 4 fields
    • handlestringrequired

      A phone number in E.164 (+15555550123) or an email address an Apple ID uses (iMessage only).

    • namestring or nullrequired
    • textstringrequired

      Their text, filled in.

    • missingarray of stringsrequired

      Variables they had no value for, which were left empty.

  • estimateBroadcastEstimate or nullrequired

    When the broadcast’s texts should go, worked out with your sending rules.

    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.

Response200
{
  "object": "broadcast_preview",
  "recipient_count": 42,
  "stopped_count": 1,
  "new_people_count": 3,
  "duplicate_count": 0,
  "samples": [
    {
      "handle": "+15555550123",
      "name": "Maria Alvarez",
      "text": "Hi Maria, open house at 412 Oak St this Saturday 1–4.",
      "missing": []
    }
  ],
  "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
  }
}

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.

Try it

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