Machine credentials act with full scope
A secret key (sk_…) or an OAuth token carries scope * — full authority within its one tenant and one mode. There’s no per-key permission slicing; a server integration is trusted to act as the merchant. Its blast radius is bounded by the tenant boundary and the mode, not by scopes.
A publishable key (pk_…) is the exception: it can only start checkout sessions, never read or mutate data, so it’s safe in the browser or the inline SDK.
Dashboard members are role-gated
Human users in the dashboard hold one of five roles. Every write endpoint is gated by aPermissionGuard.
| Role | Can do |
|---|---|
| owner | Everything, including tenant management. Cannot be removed or demoted. |
| admin | Everything except tenant management. |
| developer | Plans, customers, subscriptions, invoices, API keys, webhooks, appearance, read. |
| finance | Plans, customers, subscriptions, invoices, refunds, read. |
| read_only | Read only. |
The permission set
The guard checks named permissions, derived from the role:tenant:manage · member:manage · plan:write · customer:write · subscription:write · invoice:write · refund:write · apikey:manage · webhook:manage · appearance:manage · read
A 403 with code forbidden means the credential authenticated but lacks the permission for that route — distinct from a 401, which means the credential itself was missing or invalid. See Errors.
Customer identity tokens
The customer-facing endpoints (/identity/*, /portal/*) use an identity token, which resolves to a person, not a tenant. It can read and manage only that customer’s own data, and is rejected outright by the merchant /v1 API.