Create an automation
Deterministic create — the body carries the full graph ({ name, triggerEventId?, nodes, connections }). Returns 201 with the bare AutomationRow.
Trigger binding (exactly one): for an EVENT automation pass triggerEventId (then publish with PATCH … { "published": true }). For a MANUAL-AUDIENCE automation OMIT triggerEventId and give the trigger node config: { "mode": "manualAudience", "audienceId": "aud_…" } — it is launched on demand with POST /v1/automations/{automationId}/run rather than published.
Typed conditions: every filter and condition-mode split uses a non-empty conditions array. Each condition requires field, type (string, number, date, or bool), and a canonical snake_case operator. Unary operators omit value; comparisons require a type-correct scalar, non-empty array, or exact two-value between tuple as documented by AutomationNode.
Chain POST /v1/emails { prompt } first to mint the design each sendEmail node references — every sendEmail node MUST carry emailId, emailVersionId, domainId, subject, previewText. The graph resolver checks every foreign key and structural constraint before writing; failures return AUTOMATION_GRAPH_INVALID. Each sendEmail node creates one sends row per recipient that reaches it.
Dry-run — add dryRun: true to validate without persisting; returns 200 with { valid, blockers[], warnings[], blockingIssues[], nodeCounts }. blockingIssues[] lists per-node references to a trigger-payload variable the bound trigger cannot provide ({ nodeId, nodeLabel, surface, variable, reason, fatal }) — e.g. after swapping the trigger or removing a payload field. fatal: true (filter/split conditions and triple-brace {{{ }}} body tokens) fails publish; fatal: false (subject/previewText/fromName/replyTo and double-brace body tags) renders empty at send time and is advisory only. valid is false when any fatal blocking issue is present.
Authorizations
Send your Brew API key as Authorization: Bearer brew_xxx.
Headers
Optional idempotency key for safe retries. Reusing the same key with the same request body returns the original response for 24 hours.
1 - 100Body
Response
Dry-run result (no writes). valid indicates whether the graph would publish cleanly.