HeyKoala Voice APIAPI

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:

OperationWhy 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

StatusMeaning
401The key is missing, malformed, expired, revoked, or its organization no longer has API access.
403The key authenticated but lacks the scope, or the operation is destructive and the flag is off.
404No such record — or it belongs to another organization. Reported identically on purpose, so the API cannot be used to probe for what exists elsewhere.

On this page