Commune

403insufficient_scope

Missing permission

The credential reaches the newsletter but does not hold the permission this operation, filter or expansion needs.

Permissions are granted per newsletter, in six families: content, audience, sending, insights, settings and webhooks, each at none, read or write (write includes read). Separately, a credential may hold account: read, which covers the operations about the person who owns it (GET /me and the collections beside it) and is never implied by anything granted on a newsletter.

This error names what was needed, spelt the way the key form spells it (for example audience: read), and what the credential actually holds on the newsletter the request was for. allowed_values carries the needed permission. When the refusal is about one parameter value rather than the whole operation, param names the parameter and allowed_values lists what this credential may send instead, or is left out when it may send nothing there.

Two things decide what a credential holds: what was ticked when it was created, and what its owner can do on the newsletter right now. A person can only grant what they can do themselves, so the same key can lose a permission when its owner's role changes. The same key may also be allowed on one newsletter and refused on the next.

Why it happens, and how to fix it

  1. The credential lacks the permission family

    The operation needs a family at a level this credential does not hold on this newsletter: reading subscribers needs audience: read, creating or editing an article needs content: write, sending or scheduling needs sending: write, insights need insights: read, and so on. The message says which one, and what the credential holds there (for example "On that newsletter this credential holds: content: read, insights: read.").

    Fix: A key's permissions are fixed when it is minted. Mint a new key on Settings, API keys with the family named in allowed_values ticked for this newsletter, switch your integration to it, then revoke the old key. For an OAuth app, send the creator through authorisation again asking for the scope (for example audience:read), and read the scopes actually granted from the token response.
  2. The owner's role caps what the key can hold

    The key was minted with the family, but its owner cannot do that on this newsletter, either because their role never allowed it (an editor can hold at most settings: read) or because their role was narrowed after the key was made. The cap is applied on every request, so the message shows what the key holds after it.

    Fix: Have a newsletter owner or admin mint the key instead, or change the person's role on the newsletter's team page. A new key is not needed if the role is widened; the next request picks it up.
  3. The operation needs account access

    GET /me and the account collections (GET /memberships, GET /subscriptions, GET /saved-articles, GET /liked-articles) are about the credential's owner rather than a newsletter, and need account: read. Nothing granted on any newsletter adds up to it. The message reads "This credential does not hold it anywhere it reaches."

    Fix: Mint a key with account access turned on, on Settings, API keys, or authorise your OAuth app with the account:read scope.
  4. A read-only credential asked for unpublished content

    A credential that holds only read on a newsletter sees it as a reader does. On GET /newsletters/{newsletter}/articles it may filter status by sent only, and may not filter by tag; on GET /newsletters/{newsletter}/threads it may filter visibility by public only. Anything else would be a view of what is not published, so it is refused rather than answered with an empty page. param names the filter.

    Fix: Drop the filter, or use a value from allowed_values (absent for tag, which a read-only credential may not filter by at all). To see drafts, scheduled articles, tag-scoped articles or private threads, use a credential holding write in one of the newsletter's families.
  5. An expansion needs a family the operation does not

    Some expand paths inline rows from another family. ?expand=subscriber on GET /newsletters/{newsletter}/insights inlines subscribers with their email addresses, so it needs audience: read on top of the insights: read the operation needs. param is expand, and allowed_values lists the paths this credential may expand, or is left out when it may expand none.

    Fix: Remove the path from expand and read the reference it returns instead, or use a credential that also holds the family the message names.

Retrying

No: the credential has to gain the permission first (a new key, a re-authorisation or a wider role), or the request has to drop the filter or expansion that needs it.

Example response

HTTP 403
{
  "error": {
    "code": "insufficient_scope",
    "message": "This operation needs `audience: read`. On that newsletter this credential holds: content: read, insights: read. Permissions are granted per newsletter, and a credential's holder can only grant what they can do themselves, so check both the credential and your standing on the newsletter.",
    "allowed_values": [
      "audience: read"
    ],
    "request_id": "req_01j9c8h1q7m3n4p5r6s7t8u9v0",
    "docs_url": "https://usecommune.dev/errors/insufficient_scope"
  }
}

Often confused with forbidden, not_found, payment_required.