Skip to main content
A scope is a single permission. You tick scopes when you create a key under Settings → API → API Keys, and you can edit them afterwards without issuing a new key. Every endpoint states the scope it needs, both in its description and in the x-required-scopes field of the OpenAPI document. Grant exactly those and no more.

The full catalogue

That’s 21 scopes in total.
media:read doesn’t reach your customers’ files. Media a customer sent in over WhatsApp is returned only when a key holds conversations:read as well and explicitly asks for it. A media-only key sees the project’s own uploads and nothing else. See Storage.
The table scopes reach your tables only. Paige’s own platform tables — contacts, conversations, messages, execution logs, and broadcast recipients — are not addressable through /v1/tables, whatever scopes the key holds. Read those through their own endpoints instead, where the rules that protect them still apply. A write must also always carry a filter, so there is no way to accidentally update or delete a whole table in one call.
broadcasts:manage is not a licence to send. POST /v1/broadcasts always lands the campaign in pending_approval, whatever scopes the credential holds. There is no send, launch, approve, or retry endpoint — a human releases the campaign from the Broadcasts tab in the dashboard. Don’t design a flow that expects the API to send; it never will. See Broadcasts.

When a scope is missing

A valid key calling an endpoint it isn’t scoped for gets:
with HTTP 403. Fix it by editing the key’s scopes in Settings → API — you don’t need a new key.
GET /v1/ping echoes back the scopes the credential actually holds. When a call 403s unexpectedly, ping first and compare against the endpoint’s x-required-scopes before changing anything else.

Two things that catch people out

webhooks:manage isn’t enough on its own. Registering a webhook always needs webhooks:manage, but subscribing to a platform event also needs that event’s own events:* scope. Asking for message.received without events:message_received fails with 403 insufficient_scope at registration time, not at delivery time. Custom events your own bot emits need only webhooks:manage. See Webhooks. Scopes don’t pool across projects. If an AI agent is connected to several projects at once, each project carries its own grant. Being allowed to edit code in one project never implies it in another — the check runs against the selected project only.

Picking scopes for a job