Skip to main content
Every Brew credential answers two separate questions before an operation runs. What can it reach? is the credential’s scope: one brand, or the whole organization. Who is asking? is the person’s role. The two produce different 403 codes, and no amount of permission scopes fixes either one.

Two Kinds of Credential

A key is bound at creation. POST /v1/api-keys takes brandId in the body as the new key’s binding, and omitting it mints an organization-wide key. That is the only brandId field anywhere in v1; no other endpoint accepts a brand in a body or query string.

Naming the Brand

There is no default brand. An organization-scoped credential that omits X-Brand-Id on a brand-scoped operation gets 400 BRAND_ID_REQUIRED, not a guess. Discover the ids with GET /v1/brands, which returns every brand in the organization for an organization-scoped credential and exactly the one bound brand for a brand-bound key.
A brand-bound key may omit the header. If it sends one naming a different brand, that is 403 BRAND_SCOPE_MISMATCH: use the brand it is bound to, or switch to an organization-scoped key. A brand id from outside the organization is 404 BRAND_NOT_FOUND, so the API never confirms that another organization’s resources exist.

Organization Operations

A few operations act on the organization itself, not on a brand. They take no X-Brand-Id, and a brand-bound key cannot call the ones that write or bill:

403 ORG_SCOPE_REQUIRED

A brand-bound key calling an organization operation gets:
This is about the credential’s binding, not its permission list. A brand-bound key holding all still gets ORG_SCOPE_REQUIRED on GET /v1/usage. The fix is to mint an organization-scoped key at brew.new/settings/api (create the key without choosing a brand) and use that one for billing and brand-directory reads. Over MCP, reconnect at the organization level instead of picking a single brand.

403 INSUFFICIENT_ROLE

A person, rather than a key, can fail for a different reason: they do not hold the access the operation needs. error.param says which: INSUFFICIENT_ROLE and ORG_SCOPE_REQUIRED are not interchangeable. Minting an organization-scoped key does not grant a person a role, and granting a role does not re-bind a key. A third code, 403 INSUFFICIENT_PERMISSIONS, is the only one that a different scope set on the key fixes; see Authentication for the scope table.

Key Management Is Session-Only

The three /v1/api-keys operations back the dashboard’s own API page. They accept only a signed-in session whose active organization role is exactly org:admin. An API key, an OAuth connection, the MCP server, and the CLI all receive 403 on them, so a leaked key can never mint or revoke another one.

Choosing a Scope

  • One product, one brand. Use a brand-bound key. It cannot touch another brand even if it leaks, and it never has to send a header.
  • An agency, a platform, or anything multi-brand. Use an organization-scoped key and pass X-Brand-Id per request. Read GET /v1/brands once at startup and cache the mapping.
  • Billing dashboards and provisioning. Use an organization-scoped key: GET /v1/usage and POST /v1/brands accept nothing less.

See Also

Need Help?

Our team is ready to support you at every step of your journey with Brew. Choose the option that works best for you:

Search Documentation

Type in the “Ask any question” search bar at the top left to instantly find relevant documentation pages.

ChatGPT/Claude Integration

Click “Open in ChatGPT” at the top right of any page to explore it further with ChatGPT or Claude.