Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.brew.new/llms.txt

Use this file to discover all available pages before exploring further.

Brew uses API key authentication. Each key is bound to exactly one brand at creation time, carries a permission scope set, and ships over HTTPS as either an Authorization: Bearer header or the convenience X-API-Key header.

Quickstart

curl -H "Authorization: Bearer brew_your_api_key" \
  https://brew.new/api/v1/domains
import { createBrewClient } from '@brew.new/sdk'

const brew = createBrewClient({ apiKey: process.env.BREW_API_KEY! })
const { domains } = await brew.domains.list()
Get a key at brew.new/settings/api.

Headers (use ONE)

HeaderFormatNotes
AuthorizationBearer brew_…Recommended. Plays nicely with most HTTP clients + observability tooling.
X-API-Keybrew_…Convenience header. Same behaviour as the bearer form.
Send exactly one. Sending both is allowed; sending neither returns 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 brandId field. Sending one returns 400 INVALID_REQUEST with param: "brandId".
  • All brand-scoped reads filter to the key’s brand automatically. Cross-brand identifiers surface as 404 (not 403) so the API never confirms the existence of resources in another brand.
  • All brand-scoped writes target only the key’s brand.
The lone organization-wide endpoint is 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 listed scope or all. Missing permission returns 403 INSUFFICIENT_PERMISSIONS with error.param pointing at the missing scope name.
ScopeEndpoints
contacts/v1/contacts, /v1/fields, /v1/audiences
emails/v1/domains, /v1/emails, /v1/templates
sends/v1/sends
automations/v1/triggers, /v1/automations, /v1/automation/runs, /v1/events (legacy)
allEvery endpoint above. Default for new dashboard-issued keys.
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 back-end that does audience campaigns, issue emails + sends. The dashboard surfaces each key’s scope set so you can audit + rotate.

Key lifecycle

ActionWhere
CreateDashboard → API Keys. Choose a brand and a scope set; the secret is shown ONCE — store it in your secret manager.
ListDashboard. The list shows the key id, prefix, scope, brand binding, and last-used timestamp. The full secret is never re-exposed.
RotateDashboard. Create a fresh key with the same scope set; cut traffic over (zero-downtime); revoke the old key after a grace window.
RevokeDashboard. Revoked keys immediately return 401 API_KEY_REVOKED on every request.
AuditDashboard surfaces the last-used timestamp per key. Pair with your platform’s request logs (e.g. Vercel) for full attribution via x-request-id.
There is no API for key CRUD today — provisioning is human-in-the-loop through the dashboard so a compromised key can’t mint more. If you need programmatic key management for a SOC2 / SAST pipeline, contact us.

Production security checklist

PracticeWhy
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-Key header is honored only on POST. PATCH operations are naturally idempotent at the resource level — re-sending the same body is safe.
  • Public key-management API. Keys are minted from the dashboard.
These are roadmap items where there’s customer pull; tell us at the link below if your integration needs any of them.

Errors

CodeHTTPWhen
AUTHENTICATION_REQUIRED401No Authorization / X-API-Key header.
INVALID_API_KEY401The key doesn’t parse (e.g. wrong prefix).
API_KEY_REVOKED401The key was revoked in the dashboard.
INSUFFICIENT_PERMISSIONS403The key’s scope set doesn’t include the route’s required scope. error.param carries the missing scope name.
See Errors for the full error envelope + every code in the catalog.

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 analyze documentation with ChatGPT or Claude for deeper insights.