Skip to main content

Scopes

A key gets exactly the scopes you grant. Each endpoint requires one.

ScopeAllows
messages:sendPOST /v1/messages
messages:readGET /v1/messages, GET /v1/messages/{id}
templates:readGET /v1/templates
templates:writePOST /v1/templates, POST /v1/templates/{id}/submit
numbers:readGET /v1/numbers
campaigns:readGET /v1/campaigns, GET /v1/campaigns/{id}
contacts:readGET /v1/contacts, GET /v1/contacts/tags

Defaults when you create a key without choosing: messages:send, messages:read, templates:read.

What keys cannot do​

API keys cannot reach management endpoints — /v1/keys, /v1/logs, /v1/segments, auth, number onboarding or campaign creation. Those require a dashboard session. This is deliberate: a leaked integration key can send messages, not reconfigure your workspace.

Combining restrictions​

Scopes, number binding and IP allowlists combine with AND:

request allowed = token valid
AND scope granted for the endpoint
AND (no number binding OR the number is bound)
AND (no IP allowlist OR the address matches)

Checking from your side​

A cheap way to verify a new key is scoped correctly:

# should be 200
curl -o /dev/null -w '%{http_code}\n' https://api.msgpanda.com/v1/templates \
-H "Authorization: Bearer $API_KEY"

# should be 403 scope_not_permitted for a send-only key
curl -o /dev/null -w '%{http_code}\n' https://api.msgpanda.com/v1/numbers \
-H "Authorization: Bearer $API_KEY"