Scopes and permissions
What a key is allowed to do, and how to find out.
A key carries two independent things: a scope map and a destructive flag.
The scope map
Each resource is granted read, write, or nothing:
{ "contacts": "write", "call_logs": "read", "calls": "write" }write implies read. A resource absent from the map is invisible to the key
— requests to it answer 403, and it does not appear in the discovery
response.
Every endpoint in the reference states the scope it needs, like
Requires scope contacts: write.
Reading calls and placing calls are different scopes
call_logs and calls look like they should be one resource. They are
deliberately two:
call_logs— history. What happened, recordings, transcripts, analysis.calls— placing new calls, which spends your credits.
A reporting integration that pulls yesterday's calls into a dashboard should
have call_logs: read and no calls scope at all. Otherwise it sits one
config mistake away from dialling your customers.
The destructive flag
A small number of operations cannot be undone, and are gated separately from the write scope:
| Operation | Why it is separate |
|---|---|
POST /campaigns/{id}/stop/ | Ends the campaign permanently and cancels every queued call. Pause instead if you may want it back. |
DELETE /documents/ | Removes the document and its embeddings from the vector index. |
A key without the flag gets 403 on these even with the right write scope. The
error says so explicitly rather than pretending the endpoint does not exist.
Checking what a key can do
curl https://dvoice.heykoala.ai/api/v1/ext/ \
-H "Authorization: Bearer hk_api_..."Each entry in resources tells you the resource, its path, what you were
granted, what the resource supports, and the operations you may actually
perform — already filtered by both the scope and the destructive flag. So if
stop is missing from a campaign's operations list, the key cannot stop
campaigns, and you do not need to work out why.
Revocation is immediate
Revoking a key, or having API access turned off for the organization, is checked when the request authenticates — not cached, not deferred. The next request fails. There is no window in which an old key still works.
Errors you will see
| Status | Meaning |
|---|---|
401 | The key is missing, malformed, expired, revoked, or its organization no longer has API access. |
403 | The key authenticated but lacks the scope, or the operation is destructive and the flag is off. |
404 | No such record — or it belongs to another organization. Reported identically on purpose, so the API cannot be used to probe for what exists elsewhere. |