Authorization: Bearer header or the convenience X-API-Key header.
Quickstart
Headers (use ONE)
| Header | Format | Notes |
|---|---|---|
Authorization | Bearer brew_… | Recommended. Plays nicely with most HTTP clients + observability tooling. |
X-API-Key | brew_… | Convenience header. Same behaviour as the bearer form. |
401 AUTHENTICATION_REQUIRED. Malformed keys return 401 INVALID_API_KEY; revoked keys return 401 API_KEY_REVOKED.
Brand binding (one brand per key)
Every API key is bound to exactly one brand at creation time. The binding is enforced server-side:- The brand id is resolved from the key on every request — clients never send a
brandIdfield. Sending one returns400 INVALID_REQUESTwithparam: "brandId". - All brand-scoped reads filter to the key’s brand automatically. Cross-brand identifiers surface as
404(not403) so the API never confirms the existence of resources in another brand. - All brand-scoped writes target only the key’s brand.
GET /v1/templates (the public template catalog) — every other endpoint is brand-scoped.
To operate on a different brand, switch brands in the dashboard at brew.new/settings/api and create a new key for that brand. A brand can have any number of keys (dev, staging, production, per-service, per-teammate); each acts on the same single brand it was created against.
Permission scopes
Each key carries one or more permission scopes. Routes require either the route’s scope orall. Missing permission returns 403 INSUFFICIENT_PERMISSIONS with error.param pointing at the missing scope name.
Scope implication (coarse scopes satisfy granular ones)
Brew supports both coarse scopes (contacts, emails, automations) and granular least-privilege scopes (audiences, domains, sends). A coarse scope automatically satisfies the granular scopes it implies, so existing keys keep working — you only reach for the granular scopes when you want to lock a key down further.
| Granted scope | Satisfies |
|---|---|
contacts | contacts, audiences |
emails | emails, domains, sends |
automations | automations |
all | everything |
each granular scope (audiences, domains, sends) | itself only (least privilege) |
contacts, emails, automations, audiences, domains, sends, transactional, and all.
Per-route required scope
| Route | Required scope (or an implier) |
|---|---|
/v1/contacts, /v1/fields | contacts |
/v1/audiences (all methods) | audiences (or contacts) |
/v1/domains (all methods) | domains (or emails) |
/v1/emails, /v1/templates | emails |
/v1/sends (GET + POST) | sends (or emails) |
/v1/brand, /v1/usage | emails |
/v1/analytics/campaigns, /v1/analytics/events | emails |
/v1/analytics/automations | automations |
/v1/integrations | automations |
/v1/triggers, /v1/automations, /v1/automation/runs | automations |
/v1/events (legacy) | automations |
transactional is a reserved scope with no route today.
Principle of least privilege. For a back-end that only fires triggers, issue a key with automations only — even if it leaks, it can’t list contacts. For a service that only inspects send health, issue sends (it can read /v1/sends but not generate emails or manage domains). The dashboard surfaces each key’s scope set so you can audit + rotate.
Key lifecycle
| Action | Where |
|---|---|
| Create | Dashboard → API Keys. Choose a brand and a scope set; the secret is shown ONCE — store it in your secret manager. |
| List | Dashboard. The list shows the key id, prefix, scope, brand binding, and last-used timestamp. The full secret is never re-exposed. |
| Rotate | Dashboard. Create a fresh key with the same scope set; cut traffic over (zero-downtime); revoke the old key after a grace window. |
| Revoke | Dashboard. Revoked keys immediately return 401 API_KEY_REVOKED on every request. |
| Audit | Dashboard surfaces the last-used timestamp per key. Pair with your platform’s request logs (e.g. Vercel) for full attribution via x-request-id. |
Production security checklist
| Practice | Why |
|---|---|
| Keys live in environment variables on the server only. Never in client JS, mobile binaries, or git. | A key in the browser can be exfiltrated and used against your brand. |
| Use short-lived deploys’ env vars + a secret manager. Vercel + Vault / Doppler / 1Password / AWS Secrets Manager all work. | Centralised rotation, audit trail. |
| One key per environment. Separate dev / staging / prod keys. | Blast radius — revoke staging without touching prod. |
| One key per service when feasible. Webhook receiver gets a key; cron worker gets a different key. | Granular audit + rotation. |
Set Idempotency-Key on every retried POST so a replayed key burst doesn’t double-fire. | See Idempotency. |
Honor Retry-After on 429. | See Rate limits. |
Log every API call’s x-request-id from the response. | Support diagnostics; correlate end-to-end through Brew’s pipeline. |
Pin to the official TypeScript SDK when possible (@brew.new/sdk@latest). | Auto-retries, auto-idempotency keys, typed error envelope. |
| Verify webhook signatures (when outbound webhooks ship). | See Webhooks & events. |
What we do NOT support today
For transparency:- OAuth 2.0 / token exchange for end-user authorization. The Brew Public API is server-to-server today; if you want per-user OAuth on top of the API, build it in your app and hold the Brew key on your server. Contact us if you have a use case that genuinely needs OAuth.
- PATCH idempotency. The
Idempotency-Keyheader is honored only onPOST.PATCHoperations are naturally idempotent at the resource level — re-sending the same body is safe. - Public key-management API. Keys are minted from the dashboard.
Errors
| Code | HTTP | When |
|---|---|---|
AUTHENTICATION_REQUIRED | 401 | No Authorization / X-API-Key header. |
INVALID_API_KEY | 401 | The key doesn’t parse (e.g. wrong prefix). |
API_KEY_REVOKED | 401 | The key was revoked in the dashboard. |
INSUFFICIENT_PERMISSIONS | 403 | The key’s scope set doesn’t include the route’s required scope. error.param carries the missing scope name. |
See also
- API introduction — the overview that links every reference page.
- Idempotency — set
Idempotency-Keyon every retriedPOST. - Rate limits — per-route policies + the
429cookbook. - SDK authentication — TypeScript SDK auth specifics.
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:- Self-Service Tools
- Talk to Our Team
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 analyze documentation with ChatGPT or Claude for deeper insights.