Skip to the page

API reference

API reference

The base URL, how to authenticate, what requests and answers look like, the headers BlueBot reads and sends, and every operation in the API.

The BlueBot API is JSON over HTTPS. You send texts, read every text in and out, look after your Mac and your sending rules, and manage webhooks. Each operation has its own page with its fields, an example in every language, its errors and a Try it panel that calls the API with a key you paste in.

The whole API is also one OpenAPI 3.1 file, /openapi.v1.json, which you can import into Postman or Insomnia or feed to a code generator. OpenAPI, Postman and Insomnia says how.

Base URL

https://usebluebot.com/api

The docs write each operation relative to https://usebluebot.com/api, so POST/v1/messages is POST https://usebluebot.com/api/v1/messages. Only HTTPS is answered.

Authentication

Every operation but GET/v1/status needs an API key, sent as a bearer token:

HTTP
Authorization: Bearer bb_live_7Hq2LxW9cVbN3mKpRtYs0aQ4eT6uY8iO1pA3sD

Make keys in the dashboard under Developers → API keys. A key starts bb_live_, ends with a checksum, and is shown once when you make it; BlueBot keeps only a hash. A key carries scopes, and each operation needs one of them, named on its page. A key from a development copy of BlueBot starts bb_test_, and the live API refuses it. API keys and scopes covers making, scoping and revoking keys.

Check a key with GET/v1/me, which says which account and key a request acts as:

GET/v1/meWho am I? →
curl "https://usebluebot.com/api/v1/me" \
  -H "Authorization: Bearer $BLUEBOT_API_KEY"
You gotIt meansDo next
200 with your account and key.scopesThe key works, and these are its scopes.Call anything those scopes allow.
401 unauthorizedNo key, a mistyped key, a revoked key, or a header that isn't Bearer <key>.Copy the key again or make a new one. unauthorized
403 insufficient_scopeThe key works but lacks account:read.Any operation its scopes allow still works. insufficient_scope

Requests

  • JSON in. Send Content-Type: application/json with a JSON body of up to 1 MB. A body sent as anything else is refused with unsupported_media_type.
  • Uploads are the one exception: POST/v1/files takes multipart/form-data with the file in a field named file, up to 25 MB.
  • Empty strings count as left out. A field sent as "" or only spaces is treated as if you hadn't sent it. Zapier and Make send "" for every field a step leaves unmapped, so this keeps an unmapped field from failing a send.
  • Phone numbers can be written the way people type them. +15555550123, 5555550123 and (555) 555-0123 all mean the same US number, and BlueBot answers with E.164 (+15555550123). An email address works anywhere a person goes, for iMessage only.
  • Times go in as ISO 8601 with a zone (2026-11-14T09:30:00-06:00 or 2026-11-14T15:30:00Z) and come back in UTC.
  • Ids are prefixed by kind: msg_ for a message, chat_ for a chat, file_ for a file, wh_ for a webhook, evt_ for an event. An id of the wrong kind in a path answers not_found.
  • POSTs take an Idempotency-Key header, so a retry never sends twice. Idempotency

Answers

  • JSON out, always. Every resource has an object field ("message", "chat", "device"), so a program can tell what it got.
  • Statuses: 200 for a read or a change, 201 when something new was made (a text, a file, a webhook, a stop), and 202 for a webhook delivery replayed in the background.
  • Lists are { "object": "list", "data": [...], "has_more": true, "next_cursor": "…" }, newest first. Send next_cursor back as cursor for the next page. Pagination
  • Refusals are one shape, { "error": { "code", "message", "hint", "doc_url", "request_id" } }, with a stable code. Errors
  • A held text is not a refusal. A send that can't go yet answers 201 with the message queued and a hold saying why. Holds

Headers

What BlueBot reads:

HeaderWhenWhat it does
AuthorizationEvery request but GET /v1/statusBearer <key>.
Content-TypeEvery request with a bodyapplication/json, or multipart/form-data for an upload.
Idempotency-KeyAny POST1 to 255 characters. The first answer is kept 24 hours and returned for a retry with the same key.

What BlueBot sends back:

HeaderOnWhat it says
Request-IdEvery answerThis request's id, such as req_1Hq2LxW9cVbN3mKpRtYs0a.
RateLimit-LimitEvery answer to a keyRequests the key may make a minute: 120.
RateLimit-RemainingEvery answer to a keyRequests left this minute.
RateLimit-ResetEvery answer to a keySeconds until the minute starts again.
RateLimit-PolicyEvery answer to a keyThe limit and its window, 120;w=60.
Retry-AfterA 429, and a 409 for a key still in useSeconds to wait before trying again.
Idempotent-ReplayedA replayed answertrue when this is the kept answer to an earlier request with the same Idempotency-Key.
Cache-ControlEvery answerno-store.

BlueBot's own apps (Zapier, Make, n8n, Pipedream, the CLI) also send a BlueBot-Client header so a text they send records them as its source. Your own code doesn't need it, and texts it sends are source: "api".

Request ids

Every answer has a Request-Id header, and every refusal repeats it as error.request_id. Log it beside your own record of the call. When you write to support about a request, the id lets a person at BlueBot find it at once; BlueBot logs the route, the status and the time of each request, never its body.

Response404A refusal, with its request id
{
  "error": {
    "code": "not_found",
    "message": "There’s no message with that id.",
    "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
    "doc_url": "https://usebluebot.com/docs/errors/not_found",
    "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
  }
}

Versions

The version is in the path: this is /v1, and there is no version header to send. BlueBot adds to /v1 without breaking it: new operations, new optional fields, new fields in answers, new event types and new values in lists such as hold.reason. Write your code to ignore fields it doesn't know and to treat an unknown value as "something else". A change that would break working code becomes /v2, with /v1 kept running beside it.

Webhook payloads carry api_version (now 2026-11-13), and each webhook keeps the version it was made with, so a new payload shape never surprises a handler you already wrote. Versioning

Before you build on it

  • Holds: a text that can't go yet is accepted and waits. Don't retry it.
  • Idempotency: send an Idempotency-Key on every POST.
  • Rate limits: 120 requests a minute per key; poll less and listen to webhooks more.
  • Limits: every cap and what happens at it.
  • Errors: every code and whether to retry it.

Every operation

Messages

Send texts, read them, schedule them and cancel them.

Files

Pictures, video, voice memos and other files to send, and the ones that arrive.

OperationWhat it doesScope
POST /v1/filesUpload a filemessages:send
GET /v1/files/{id}Get a filemessages:read

Chats

Group chats and one-to-one chats the Mac has seen.

OperationWhat it doesScope
GET /v1/chatsList chatsmessages:read
GET /v1/chats/{id}Get a chatmessages:read

Lookup

Whether a number is on iMessage, from your own history.

OperationWhat it doesScope
GET /v1/lookupIs this number on iMessage?messages:read

Device

Your Mac and BlueBot’s own status.

OperationWhat it doesScope
GET /v1/deviceGet the Macaccount:read
GET /v1/statusBlueBot’s statusNone

Settings

The sending rules.

Stops

People who asked not to be texted.

Events

The last 30 days of events.

OperationWhat it doesScope
GET /v1/eventsList eventsmessages:read
GET /v1/events/{id}Get an eventmessages:read

Webhooks

Addresses BlueBot posts events to.

Account

Who a key belongs to.

OperationWhat it doesScope
GET /v1/meWho am I?account:read

Conversations

Your texts grouped by person or group chat, as the inbox shows them.

Analytics

Texting numbers and the conversations waiting on you.

OperationWhat it doesScope
GET /v1/analyticsGet the numbersmessages:read

Contacts

The people you text, their tags and custom fields.

Templates

Saved texts with variables.

Broadcasts

One text to a list of people who asked to hear from you, paced by your Mac.

Sequences

Texts with waits between them that stop when the person replies.

Text Hooks

Addresses that turn any app’s webhook post into a text.

Automations

Keyword auto-replies and the away message.