Authorization: Bearer <key>. Keys are created in the dashboard, shown once, and stored only as a SHA-256 hash. There is no OAuth flow, so a person creates a key and your backend uses it.
Which key to use
Most integrations need one workspace key. Reach for a tenant key when a customer or a semi-trusted service should have direct access with a single tenant’s blast radius. Ship a client key in the app; it cannot read other subscribers or send.
Selecting a tenant
A workspace key implies its workspace. AddBuzzKit-Tenant: <slug> to work inside a specific tenant, the way a Stripe platform passes Stripe-Account. Leave it off and the default tenant is used, so a single-app integration never has to think about tenants.
Scopes
Every route declares one required scope, written asresource:action: messages:send, subscribers:read, events:write, topics:*, or * for everything a key may hold. The scope each operation needs is listed on its page in the API reference. A key without it gets a 403 with the code missing_permission.
Errors
Every response, success or failure, uses the same envelope:
error.code, never on error.message. Quote metadata.requestId in support requests; it is also returned as the Request-Id header.
Rotation
For a zero-downtime rotation, create the replacement key first, move your backend over, then revoke the old one from the dashboard or withDELETE /v1/workspaces/:workspaceSlug/keys/:id. When a secret has leaked, rotate the key in place instead: POST /v1/workspaces/:workspaceSlug/keys/:id/rotate (or Rotate key on the dashboard’s API keys page) keeps the key’s id, name and scopes, kills the old secret at once and returns the new one exactly once. Revocation and rotation take effect immediately in the region that served the request and within about a minute everywhere else.