Authentication
Send Authorization: Bearer on every /v1 request.
Two credentials
| Credential | Form | Used for |
|---|---|---|
| Access token | Supabase session token | The dashboard, acting as a member |
| API key | zt_live_… or zt_test_… | A server you run |
Both prefixes are sent to https://api.zoe-tel.com. A zt_test_ key never reaches a carrier or a payment provider. Keys are stored as a SHA-256 hash. The plaintext is not kept.
Organisation
The organisation comes from the credential.
- One active membership: the organisation is implicit.
- More than one: send
X-Zoetel-Org: <uuid>. The UUID must be one of the caller's memberships, or the response is403org_not_member.
Key scopes
A key is limited to the numbers and voice surfaces.
| Scope | Numbers | Voice | Methods |
|---|---|---|---|
read | yes | yes | GET, HEAD, OPTIONS |
numbers | yes | no | GET, HEAD, OPTIONS |
numbers_write | yes | no | any method on that surface |
voice | no | yes | GET, HEAD, OPTIONS |
voice_write | no | yes | any method on that surface |
full | yes | yes | any method on both surfaces |
voice_write currently reaches no route. Voice routes are reads. A missing scope returns 403 scope_insufficient.
A key can write one numbers route: PUT /v1/numbers/{id}/routing, and only in the modes sip_uri, connection, and unrouted. forward and webhook stay on a member session. Ordering, releasing, reservations, SIP apply, and credential rotation are member sessions, not keys.
No scope, including full, can create keys, change the team, move money, or submit verification documents.