Developer docs
Authentication
Authenticate with a bearer API key. Keys have a read or write scope, optional per-key capabilities, optional expiry, and clear error codes.
Every request must send an API key as a bearer token:
Authorization: Bearer rp_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Getting a key
An org admin creates keys in the console: Settings → Developer → API keys → New key. The full
key (rp_live_…) is shown once at creation — copy it then; only a hash is stored, so it can’t be
retrieved later. Revoke a key from the same screen; revocation is immediate.
Scopes
Each key has a scope, chosen at creation:
| Scope | Can do |
|---|---|
| read | All GET endpoints. |
| write | Everything a read key can, plus every mutating endpoint (create / reply / assign / tag / close / reopen). |
A key acts with org-wide access — every inbox in the workspace.
Creator attribution (next grouped release)
API keys keep their own workspace grant when the person who created them leaves or loses inbox access. In the next grouped release, new conversations use that person as their default assignee only while they are active and can access the inbox; otherwise the conversation is unassigned. Replies and notes keep the existing assignment unless an assignee is explicitly requested.
New conversation messages, replies and notes resolve their credited creator from the current
key record. An inactive creator in the same workspace can still be credited; a missing creator
leaves authorUserId empty. Earlier message history is preserved. Key revocation, expiry and
write-scope checks still apply independently. These checks apply when the message is committed.
Extra capabilities
Some powers are granted per key, on top of the scope above, because scope alone answers the wrong question for them. They are a second axis — not a finer slice of the first:
| Capability | Grants |
|---|---|
drafts:write | Stage and withdraw drafts (POST / DELETE /conversations/:id/draft). |
ai:draft | Generate AI drafts (POST /conversations/:id/ai-draft) — spends your AI budget. |
The two interact deliberately, and in opposite directions:
drafts:writeworks withoutwrite. That is the point of it. A bot that can put a reply in front of a human and cannot send anything is the safe default for automation. Awritekey can already send a reply, so it may stage one without the capability.ai:draftis required even of awritekey. It is the only capability that spends money rather than changing data, and granting “write” is consent to edits, not to a bill.
Expiry
A key can be given an optional expiry. A key past its expiry is rejected exactly like an unknown
one (401). Leave it unset for a key that never expires. Rotate by creating a new key, switching your
integration over, then revoking the old one.
Errors
| Status | Meaning |
|---|---|
401 Unauthorized | Missing, malformed, expired, or unknown API key. |
403 Forbidden | A read key used on a write endpoint, or a key missing a required capability — the message names the capability to grant. |
400 Bad Request | Invalid body/params (Zod validation) — the message names the problem. |
404 Not Found | The resource doesn’t exist (or isn’t in your workspace). |
409 Conflict | An Idempotency-Key was reused with a different body, or a same-key request is still in flight. |
429 Too Many Requests | Rate limit exceeded — honor Retry-After. |