GET /v1/webhooks/signing-secret returns 403: key needs account:read

Sume returns 403 insufficient_scope with required_scope account:read when a key cannot read the webhook secret. Scopes cannot be added, so mint a new key.

5 min readSume
All posts

GET /v1/webhooks/signing-secret answers 403 insufficient_scope when the API key does not carry account:read, and the error details name the missing scope as required_scope. Scopes are fixed when a key is created, so the fix is a new key, not a patch.

Rotating the secret with POST /v1/webhooks/signing-secret/rotate needs account:write, according to the Verifying webhooks page.

What does the 403 look like?

The documented error example has code: "insufficient_scope", the message "This API key does not have permission to access this endpoint.", category: "auth", retryable: false, next_action: "authenticate", and details: { required_scope: "account:read" }.

The OpenAPI description adds that every self-service key minted from the dashboard carries the scope, so a 403 usually means an older or specially scoped key.

Why can't I add the scope to my key?

The Authentication page is blunt: scopes are fixed at creation, keys created before a scope existed do not carry it, and there is no API to patch scopes onto an existing key. The same rule explains 403 insufficient_scope on Format and Action runs.

Create a new key, move your service to it, and then revoke the old one.

Webhook secret routes and scopes (docs and API code read 2026-10-02)
RouteScopeNotes
GET /v1/webhooks/signing-secretaccount:readReturns secret, version, fingerprint, rotation window
POST /v1/webhooks/signing-secret/rotateaccount:writeOld secret still verifies for 24 hours
POST /v1/webhooks/test-deliveriesaccount:writeSends a dummy webhook.test payload

Can I skip the API and read it in the dashboard?

Yes. The Webhooks tab of the dashboard (/dashboard/webhooks, then Reveal) shows the same secret. Dashboard access follows workspace permissions: the dashboard route in the repo refuses callers without the integrations-management capability, since reading the secret is enough to forge deliveries.

One secret covers both generation-job and run webhooks, so a single verifier works for both.

Confirm both sides hold the same secret

After you fetch the secret, compare its fingerprint with the x-sume-webhook-secret-fingerprint header on a delivery, which lets you check without pasting the secret anywhere.

curl -s https://api.sume.com/v1/webhooks/signing-secret \
  -H "Authorization: Bearer $SUME_API_KEY" \
  | jq '.data | {version, fingerprint, rotation}'

What else can this route return?

The route also documents a 503 when per-recipient signing is not configured in the environment you call; in that case the API refuses rather than hand back a shared platform secret. A 401 means the key itself is missing or invalid.

Quick checklist

The points above reduce to a short list you can paste into a runbook.

  • Confirm the key carries account:read before you call the route.
  • Create a new key when a scope is missing; scopes cannot be patched.
  • Store the secret as SUME_COM_WEBHOOK_SIGNING_SECRET.
  • Compare fingerprints, not secrets, when a signature fails.
  • Upgrade your verifier before rotating, because the header can carry two sume-v1 entries for 24 hours.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume