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.
POST endpoints support idempotency via the Idempotency-Key HTTP header. Same key + same body within 24 hours returns the cached original response instead of doing the work twice. Same key + a different body returns 409 IDEMPOTENCY_CONFLICT. Set this on every retried POST.
Contract
| Property | Value |
|---|---|
| Header | Idempotency-Key: <≤ 100 chars> |
| Methods | POST only. (PATCH is naturally idempotent at the resource level.) |
| Window | 24 hours from the first request. |
| Same key + same body | Returns the original cached response (same status, same body, same headers). |
| Same key + different body | 409 IDEMPOTENCY_CONFLICT. |
| Different key | Treated as a fresh request. |
| Scope | Namespaced per-organization (one tenant’s key cannot collide with another’s). |
Why every retry needs it
Network errors, timeouts, and re-delivered webhooks all cause your code to call the same API twice. Without idempotency that means duplicate workflow runs, duplicate emails sent, duplicate contact rows created. WithIdempotency-Key, the retry replays the original outcome without doing the work again.
The endpoints that need it most:
POST /v1/automation/runs— fire branch. A doubled fire = doubled welcome / drip / receipt emails.POST /v1/sends—EMAIL_ALREADY_SENT(409) blocks a same-email retry; an idempotency key lets a retry return the originalrunIdcleanly.POST /v1/emails— generate is expensive (~30–90s). Idempotency makes a flaky-network retry free.POST /v1/contacts(single OR batch) — the underlying upsert is naturally idempotent onemail, butIdempotency-Keysaves you the second batch run.
Body-field fallback on the fire branch
POST /v1/automation/runs (fire branch) additionally honors a body idempotencyKey field for back-compat with the legacy /v1/events route:
Recommended key patterns
The key MUST be stable per logical operation. Common recipes:| Operation | Recommended key |
|---|---|
| Trigger fire from a webhook | <eventName>-<userId>-<eventTimestamp> (e.g. signup-user_123-1779292800) |
| Trigger fire from an internal job | <jobName>-<runId>-<targetUserId> |
| Campaign send | send-<emailId>-<audienceId>-<scheduledAt or "now"> |
| Email generate from a chat | email-gen-<conversationId>-<turnId> |
| Batch contact upsert | contacts-batch-<importId> |
| Cron-driven daily blast | daily-promo-<YYYY-MM-DD> |
<uuid()>per call — defeats the purpose; every retry gets a fresh key.Date.now()per call — same as above.<sha256(body)>— vulnerable to partial replays where body bytes change.
Worked example — fire a trigger with retry
- Reuse the same
idempotencyKeyacross every retry of the same logical operation. The first request wins; the rest return the cached response. - Mint a fresh
idempotencyKeywhen the body genuinely changes. A new email recipient = a new key.
409 IDEMPOTENCY_CONFLICT envelope
Where it interacts with other contracts
- Rate limits — an idempotent replay counts against the rate-limit window. If you saw a
429on the first attempt, the retry will hit the gate too. HonorRetry-After, don’t burn keys. - Workflow runs —
POST /v1/automation/runsfire creates rows inautomationExecutions. An idempotent replay returns the originalautomationRunIds[]underdetailsso polling stays consistent. - Sends —
POST /v1/sendsreserves the email atomically viareserveEmailSend. An idempotent replay short-circuits before re-reservation; a fresh key on a same-email send produces409 EMAIL_ALREADY_SENT.
SDK behaviour
The official@brew.new/sdk ships idempotency keys automatically on every POST call (auto-generated UUID, scoped to the in-process operation) so you get safe-by-default retries. Override the auto-key by passing { idempotencyKey: 'your-key' } in RequestOptions:
See also
- Rate limits — pair with idempotency for safe retry loops.
- Errors — full
409 IDEMPOTENCY_CONFLICTenvelope. - Async jobs & polling — for fire / send retries you typically don’t need to call again — poll the run instead.
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.