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, , which you can import into Postman or Insomnia or feed to a code generator. 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 /v1/status needs an API key, sent as a bearer token:
Authorization: Bearer bb_live_7Hq2LxW9cVbN3mKpRtYs0aQ4eT6uY8iO1pA3sDMake 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. covers making, scoping and revoking keys.
Check a key with /v1/me, which says which account and key a request acts as:
/v1/mecurl "https://usebluebot.com/api/v1/me" \
-H "Authorization: Bearer $BLUEBOT_API_KEY"| You got | It means | Do next |
|---|---|---|
200 with your account and key.scopes | The key works, and these are its scopes. | Call anything those scopes allow. |
401 unauthorized | No key, a mistyped key, a revoked key, or a header that isn't Bearer <key>. | Copy the key again or make a new one. |
403 insufficient_scope | The key works but lacks account:read. | Any operation its scopes allow still works. |
Requests
- JSON in. Send
Content-Type: application/jsonwith a JSON body of up to 1 MB. A body sent as anything else is refused with . - Uploads are the one exception: POST
/v1/filestakesmultipart/form-datawith the file in a field namedfile, 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,5555550123and(555) 555-0123all 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:00or2026-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 . - POSTs take an
Idempotency-Keyheader, so a retry never sends twice.
Answers
- JSON out, always. Every resource has an
objectfield ("message","chat","device"), so a program can tell what it got. - Statuses:
200for a read or a change,201when something new was made (a text, a file, a webhook, a stop), and202for a webhook delivery replayed in the background. - Lists are
{ "object": "list", "data": [...], "has_more": true, "next_cursor": "…" }, newest first. Sendnext_cursorback ascursorfor the next page. - Refusals are one shape,
{ "error": { "code", "message", "hint", "doc_url", "request_id" } }, with a stablecode. - A held text is not a refusal. A send that can't go yet answers
201with the messagequeuedand aholdsaying why.
Headers
What BlueBot reads:
| Header | When | What it does |
|---|---|---|
Authorization | Every request but GET /v1/status | Bearer <key>. |
Content-Type | Every request with a body | application/json, or multipart/form-data for an upload. |
Idempotency-Key | Any POST | 1 to 255 characters. The first answer is kept 24 hours and returned for a retry with the same key. |
What BlueBot sends back:
| Header | On | What it says |
|---|---|---|
Request-Id | Every answer | This request's id, such as req_1Hq2LxW9cVbN3mKpRtYs0a. |
RateLimit-Limit | Every answer to a key | Requests the key may make a minute: 120. |
RateLimit-Remaining | Every answer to a key | Requests left this minute. |
RateLimit-Reset | Every answer to a key | Seconds until the minute starts again. |
RateLimit-Policy | Every answer to a key | The limit and its window, 120;w=60. |
Retry-After | A 429, and a 409 for a key still in use | Seconds to wait before trying again. |
Idempotent-Replayed | A replayed answer | true when this is the kept answer to an earlier request with the same Idempotency-Key. |
Cache-Control | Every answer | no-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.
{
"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.
Before you build on it
- : a text that can't go yet is accepted and waits. Don't retry it.
- : send an
Idempotency-Keyon every POST. - : 120 requests a minute per key; poll less and listen to webhooks more.
- : every cap and what happens at it.
- : every code and whether to retry it.
Every operation
Messages
Send texts, read them, schedule them and cancel them.
| Operation | What it does | Scope |
|---|---|---|
messages:read | ||
messages:send | ||
messages:read | ||
messages:send | ||
messages:send | ||
messages:send |
Files
Pictures, video, voice memos and other files to send, and the ones that arrive.
| Operation | What it does | Scope |
|---|---|---|
messages:send | ||
messages:read |
Chats
Group chats and one-to-one chats the Mac has seen.
| Operation | What it does | Scope |
|---|---|---|
messages:read | ||
messages:read |
Lookup
Whether a number is on iMessage, from your own history.
| Operation | What it does | Scope |
|---|---|---|
messages:read |
Device
Your Mac and BlueBot’s own status.
| Operation | What it does | Scope |
|---|---|---|
account:read | ||
| None |
Settings
The sending rules.
| Operation | What it does | Scope |
|---|---|---|
account:read | ||
messages:send |
Stops
People who asked not to be texted.
| Operation | What it does | Scope |
|---|---|---|
contacts:read | ||
contacts:write | ||
contacts:write |
Events
The last 30 days of events.
| Operation | What it does | Scope |
|---|---|---|
messages:read | ||
messages:read |
Webhooks
Addresses BlueBot posts events to.
| Operation | What it does | Scope |
|---|---|---|
webhooks:manage | ||
webhooks:manage | ||
webhooks:manage | ||
webhooks:manage | ||
webhooks:manage | ||
webhooks:manage | ||
webhooks:manage | ||
webhooks:manage | ||
webhooks:manage |
Account
Who a key belongs to.
| Operation | What it does | Scope |
|---|---|---|
account:read |
Conversations
Your texts grouped by person or group chat, as the inbox shows them.
| Operation | What it does | Scope |
|---|---|---|
messages:read | ||
messages:read | ||
messages:send | ||
messages:read |
Analytics
Texting numbers and the conversations waiting on you.
| Operation | What it does | Scope |
|---|---|---|
messages:read |
Contacts
The people you text, their tags and custom fields.
| Operation | What it does | Scope |
|---|---|---|
contacts:read | ||
contacts:write | ||
contacts:read | ||
contacts:write | ||
contacts:write |
Templates
Saved texts with variables.
| Operation | What it does | Scope |
|---|---|---|
messages:read | ||
messages:send | ||
messages:read | ||
messages:send | ||
messages:send |
Broadcasts
One text to a list of people who asked to hear from you, paced by your Mac.
| Operation | What it does | Scope |
|---|---|---|
messages:read | ||
messages:send | ||
messages:read | ||
messages:read | ||
messages:read | ||
messages:send |
Sequences
Texts with waits between them that stop when the person replies.
| Operation | What it does | Scope |
|---|---|---|
messages:read | ||
messages:send | ||
messages:read | ||
messages:send | ||
messages:read | ||
messages:send | ||
messages:read | ||
messages:send |
Text Hooks
Addresses that turn any app’s webhook post into a text.
| Operation | What it does | Scope |
|---|---|---|
messages:read | ||
messages:send | ||
messages:read | ||
messages:send | ||
messages:send |
Automations
Keyword auto-replies and the away message.
| Operation | What it does | Scope |
|---|---|---|
messages:read | ||
messages:send | ||
messages:read | ||
messages:send | ||
messages:send | ||
messages:read | ||
messages:send |