WASync · Developers

Scopes

Four scopes, resolved live on every request. Which endpoints need which, and why marking read is a send.

Scopes are per credential — per API key, or per OAuth grant. There are four.

ScopeGrants
whatsapp.readGET /connections, GET /connections/{id}, GET /account, GET /messages
whatsapp.sendPOST /messages, POST /messages/read
whatsapp.eventsGET /webhook, PUT /webhook, POST /webhook/rotate, and receiving deliveries at all
whatsapp.managePOST /connections, POST /connections/{id}/pairing-code, POST /connections/{id}/restart, POST /connections/{id}/logout, DELETE /connections/{id}

Marking read is a send, not a read

POST /messages/read needs whatsapp.send. It looks like a read operation, but it transmits a receipt from your number to the customer's device — it is outbound. The upside is that any client which can already send can also mark read: no new scope, no re-consent.

Resolution is live

Scopes and the reachable connection list are resolved on every request. Nothing is cached in the token and nothing has to be refreshed. Two consequences:

  • Revoking a key, or narrowing its scopes, takes effect on the very next call.
  • A connection you just created is visible on the next call. There is no propagation delay and nothing to re-issue.

Insufficient scope

A credential that lacks the scope an endpoint needs gets 403 insufficient_scope. Branch on the code, not the status — 403 is also what an IP-allowlist refusal returns (ip_not_allowed) and the two need opposite fixes: one means edit the key's scopes, the other means add an address. See Errors & idempotency.

Ask for less

The scope you do not grant is the one that cannot be abused if the key leaks. A read-only reporting job wants whatsapp.read and nothing else; a notification sender wants whatsapp.send; only a provisioning flow needs whatsapp.manage, which can delete connections.

On this page