API keys and scopes
Make a key, send it with each request, give it only the scopes it needs, and revoke it when a program no longer needs it or the key leaks.
Every request to the API carries a key, and the key decides two things: which account the request acts for, and what it may do there. Make one key for each program that uses BlueBot, give it the fewest scopes that program needs, and you can revoke any one of them without touching the others.
Make a key
In the dashboard, open Developers → API keys and press New key.
- Name it after what will use it (“Website booking form”, “Zapier”, “Nightly sync”), up to 60 characters. The name is how you’ll tell keys apart later.
- Tick its scopes. A new key starts with all of them; untick what the program won’t do.
- Copy the key. BlueBot shows it this once and keeps only a hash of it, so nobody at BlueBot can show it to you again. If you lose it, revoke it and make another.
Keep the key where your program reads its secrets: an environment variable, your host’s secret settings or a secret manager. Never put it in a web page, a mobile app or a public repository, where anyone could read it.
export BLUEBOT_API_KEY="bb_live_…"Send it with each request
Send the key as a bearer token in the Authorization header:
curl https://usebluebot.com/api/v1/me \
-H "Authorization: Bearer $BLUEBOT_API_KEY"The SDKs read BLUEBOT_API_KEY from the environment when you don’t pass a key, and bluebot login stores one for the CLI. GET /v1/me says which account and key a request acts as, which is the quickest check that a key works:
/v1/mecurl "https://usebluebot.com/api/v1/me" \
-H "Authorization: Bearer $BLUEBOT_API_KEY"{
"object": "me",
"account": {
"id": "acct_1Hq2LxW9cVbN3mKpRtYs0a",
"email": "dana@example.com",
"name": "Dana Whitfield",
"time_zone": "America/Chicago",
"created_at": "2026-11-01T15:00:00.000Z"
},
"key": {
"id": "key_1Hq2LxW9cVbN3mKpRtYs0a",
"name": "Website booking form",
"prefix": "bb_live_7Hq2Lx",
"mode": "live",
"scopes": [
"messages:send",
"messages:read"
],
"created_at": "2026-11-13T19:00:00.000Z"
},
"plan": {
"status": "active",
"active": true,
"trial_end": null,
"current_period_end": "2026-12-01T15:00:00.000Z"
},
"device": {
"status": "online"
}
}| You got | It means | Do next |
|---|---|---|
200 | The key works. key.scopes says what it may do. | Use it. |
401 unauthorized with “That isn’t a BlueBot key” | The key is cut short, has a typo, or isn’t a BlueBot key. | Copy it again, whole. |
401 unauthorized with “That key isn’t valid” | The key was revoked. | Make a new key. |
401 unauthorized with “Send your API key as Authorization: Bearer <key>” | The header is missing or isn’t Bearer followed by the key. | Fix the header. |
403 insufficient_scope | The key works but can’t read the account. | Add account:read to the key, or skip this check. |
What a key looks like
Every key is bb_live_ or bb_test_, then 32 random letters and digits, then a 6-character checksum of everything before it, 46 characters in all:
| Part | Example |
|---|---|
| Prefix | bb_live_ |
| 32 random characters | kV8yQ2nTmX4pLw7RzC9dHf3JsB6aGe1N |
| Checksum | u0YtPq |
The shape does two things:
- A typo costs nothing. BlueBot checks the shape and the checksum before it looks the key up, so a mistyped or made-up key is refused at once with
401 unauthorized. - A leaked key can be spotted. The fixed prefix and the checksum let secret scanners, such as GitHub’s, recognise a BlueBot key that was pushed to a repository by mistake.
The dashboard and GET /v1/me name a key by its first 14 characters (bb_live_7Hq2Lx), its prefix, which is enough to tell your keys apart and too little to use.
Live and test keys
Every key the dashboard at usebluebot.com makes is a live key, bb_live_, and sends real texts from your number. bb_test_ keys belong to BlueBot’s own development and preview servers: usebluebot.com refuses a test key, and those servers refuse a live one, so a key copied into the wrong place can’t act on the wrong account.
There is no test mode that pretends to send. To try something safely, send it to your own number: it arrives on your phone from your own number, and you can see every step.
Scopes
A scope lets a key use a group of operations. Give a key only the scopes its program needs, so a key that leaks can do as little as possible.
| Scope | Lets a key | Operations |
|---|---|---|
messages:send | Send, schedule, edit, cancel and resolve texts; upload files. | , , , , , , , , , , , , , , , , , , , , , , |
messages:read | Read texts, files, chats, lookups and the event feed. | , , , , , , , , , , , , , , , , , , , , , , , , , , |
contacts:write | Add people to the stop list and take them off it. | , , , , |
contacts:read | Read the stop list. | , , |
webhooks:manage | Make, change, test and delete webhooks; read deliveries and replay them. | , , , , , , , , |
account:read | Read the Mac’s status, the account and its sending rules. | , , |
GET /v1/status, which says whether BlueBot itself is up, needs no key at all.
A key without the scope an operation needs is refused with 403 insufficient_scope, and error.message names the scope. Each operation’s reference page names its scope too.
A few common choices:
| What the program does | Scopes |
|---|---|
| Sends texts and reads back what happened | messages:send, messages:read |
| A dashboard or report that only reads | messages:read, contacts:read, account:read |
| Sets up its own webhooks, like a CRM integration | messages:send, messages:read, webhooks:manage |
| Keeps a stop list in step with another system | contacts:read, contacts:write |
A key with every scope is a full key. A key with only messages:read, contacts:read and account:read is a read-only key, which can look at everything and change nothing.
You can’t change a key’s scopes after it’s made. Make a new key with the scopes you want, switch your program to it, then revoke the old one.
How many keys an account can have
An account can have 10 keys at once. Making an eleventh is refused with 409 limit_reached. Revoked keys don’t count, so revoke the ones you no longer use.
Revoke a key
On the Developers → API keys page, press Revoke next to the key. It stops working at once: the next request with it is 401 unauthorized. Revoking can’t be undone.
Revoking a key also deletes the webhooks a program made with that key through the API, so an integration you remove stops receiving events. Webhooks you made in the dashboard stay.
To replace a key without a gap, make the new key, put it in your program, check the program works with GET /v1/me, then revoke the old one. The Developers → API keys page shows when each key was last used, so you can see when the old one has gone quiet.
If a key leaks
Revoke it straight away, then make a new one. A leaked key with messages:send can text people from your number until it’s revoked. If you see texts in your dashboard you didn’t send, revoke every key that could have sent them, and write to .
Keys and sign-ins
AI assistants that connect to BlueBot’s MCP server, such as Claude Desktop or ChatGPT, can sign in with your BlueBot account instead of a key you paste. Each gets a token that works like a key with the scopes you approved and has its own limit of 120 requests a minute. You can disconnect one at any time under Connected apps. Zapier, Make, n8n and Pipedream use an API key.