Authentication
Every API request authenticates with a CallMissed API key.
API Key
Every request authenticates with an API key. Create one in the console under Developer → API keys — keys are prefixed with cm_ and are passed as a Bearer token:
Authorization: Bearer cm_your_api_key_hereA key has no expiry unless you set one when you create it (1-365 days). An expired key gets 401 (api_key_expired on the inference endpoints), and an api_key.expired webhook fires. Any key can be revoked at any time.
Anthropic SDK (x-api-key header)
When using the Anthropic-compatible endpoint (/v1/messages), you can also authenticate with the x-api-key header:
x-api-key: cm_your_api_key_hereBoth header styles work on the Anthropic endpoint — use whichever your SDK sends by default.
Managed Voice Agent WebSocket (Token header or subprotocol)
The Managed Voice Agent sockets — /v1/agent/converse
and /v2/voice/agent — take the key as a Token, not a Bearer:
Authorization: Token cm_your_api_key_hereBrowsers cannot set headers on a WebSocket, so the key may instead travel as a
subprotocol. This is the only option for browser clients:
new WebSocket(url, ["token", "cm_your_api_key_here"])The key needs all three of stt, tts and llm permissions — the socket runs
the full speech pipeline, so a key missing any one of them is refused at the
handshake rather than part-way through a call.
Permissions vs. scopes
API keys carry two independent access controls.
Service permissions
Permissions decide which AI services a key may call. They are enforced on the inference endpoints — a key without the matching permission gets 403 permission_denied. Set any combination of llm, stt, tts, search, image, email, or * for all (the default for new keys).
| Permission | Gates |
|---|---|
llm | /v1/chat/completions, /v1/responses, /v1/messages (+ /anthropic/v1/messages), /v1/embeddings, /v1/batches and /v1/files |
stt | /v1/audio/transcriptions, /v1/audio/translations |
tts | /v1/audio/speech |
search | /v1/search |
image | /v1/images/generations, /v1/images/history |
email | The Email API |
Voice agents run the whole speech pipeline, so the Voice Session API and the Managed Voice Agent sockets need all three of stt, tts and llm.
Resource scopes
Scopes gate the resource endpoints under /api/v1/ — agents, conversations, CRM, support, knowledge, webhooks and the rest. Unlike permissions, scopes default to empty = no resource access — you opt in explicitly.
| Scope | Gates |
|---|---|
bots:read / bots:write | Agents: view vs. create/update/delete |
conversations:read / conversations:write | Conversations and the handoff queue: view vs. update |
knowledge:read / knowledge:write | Knowledge: search and view vs. add/remove sources |
webhooks:write | Webhook subscriptions and the delivery log, reads included. There is no webhooks:read |
whatsapp:read / whatsapp:write / whatsapp:send | WhatsApp: read accounts, numbers and templates vs. manage them vs. send messages |
campaigns:read / campaigns:write | Outbound calling campaigns and the do-not-call list |
telephony:read / telephony:write | Phone numbers, compliance and calls: view vs. provision/update |
integrations:read / integrations:write | Connected integrations and sheet automations: view vs. connect/update/remove |
* | All resource scopes |
Gateway scopes
| Scope | Gates |
|---|---|
usage:read | Usage summaries, logs and CSV export |
prompts:read / prompts:write | Stored prompts, versions, labels and presets. Rendering counts as a read |
cache:read / cache:write | Cache statistics vs. purging |
provider_keys:read / provider_keys:write | Your own provider credentials |
end_user_budgets:read / end_user_budgets:write | Per-end-user monthly budgets |
CRM scopes
| Scope | Gates |
|---|---|
contacts:read / contacts:write | Contacts |
companies:read / companies:write | Companies |
crm_notes:read / crm_notes:write | Notes |
crm_tasks:read / crm_tasks:write | Tasks |
crm_deals:read / crm_deals:write | Deals and pipelines — one pair covers both |
crm_timeline:read | The activity timeline. Read-only, no write half |
crm_custom_fields:read / crm_custom_fields:write | Custom field definitions and values |
crm_views:read / crm_views:write | Saved views |
crm_search:read / crm_search:write | Search and duplicates vs. merging |
crm_bulk:write | Bulk update and delete. Write-only, no read half |
crm_csv:read / crm_csv:write | CSV export vs. import |
crm_scores:read / crm_scores:write | Lead scoring rules and recompute |
Support desk scopes
| Scope | Gates |
|---|---|
support_tickets:read / support_tickets:write | Tickets |
sla:read / sla:write | SLA policies, ticket clocks and breaches |
support_ops:read / support_ops:write | Macros, tags and routing rules |
csat:read / csat:write | Surveys and results. The customer's response page needs no credential at all |
Commerce and voice-agent scopes
| Scope | Gates |
|---|---|
wa_commerce:read / wa_commerce:write | WhatsApp orders |
wa_flows:read / wa_flows:write | WhatsApp Flows |
evals:read / evals:write | Eval suites, cases and runs |
experiments:read / experiments:write | A/B experiments. Assignment needs write |
squads:read / squads:write | Agent squads. Handoff simulation needs only read |
Watch for the scopes whose read and write halves do not line up with the HTTP verb. POST /api/v1/gateway/prompts/{id}/render, POST /api/v1/support/ops/routing-rules/evaluate and POST /api/v1/voice/squads/{id}/simulate-handoff are all POST requests that write nothing, so they need only the read scope.
A key created for plain inference (the common case) needs only service permissions — leave scopes empty.