Skip to main content
Looking for user-facing product updates? See the main changelog. Everything below is scoped to the Public API v1 surface and the TypeScript SDK.
Set an email's subject line from the API, MCP, and CLI

Subject Lines on Every Email Write

Every design carries a default inbox subject (subjectLine), and until now only the app could set it, so designs created through the API, MCP, or CLI landed without one. All four write surfaces now accept an optional subjectLine of 1 to 250 characters:
  • POST /v1/emails (MCP create_email_design). The email agent also sees the subject, so the preview text and opening copy complement it instead of repeating it.
  • POST /v1/emails/import (MCP import_email_design)
  • POST /v1/emails/figma (MCP import_figma_design)
  • PATCH /v1/emails/{emailId} (MCP edit_email_with_ai)
Each response echoes the persisted subjectLine, and GET /v1/emails?emailId= already returns it on the detail row.prompt is now optional on PATCH /v1/emails/{emailId}. Send subjectLine on its own and Brew sets the subject in place: no AI run, no new version, no credits. Send both and the subject lands on the new version the edit produces. At least one of the two is required, and emailVersionId still requires prompt, because pinning a source version means nothing for a subject change.A subject line is the design’s default, not the send. POST /v1/sends still takes its own subject per delivery.In the CLI this is --subject-line on emails generate, emails import, emails import-figma, and emails edit.
Run and copy any API capability from the dashboard

The API Catalog

The dashboard now has an API tab at brew.new/api that runs eleven v1 capabilities against your own brand and hands you the exact call afterwards. No endpoints changed, and nothing here is new API surface.
  • Covers Generate Email, Edit Email, Figma to Email, HTML to PNG, Image to GIF, Optimize Image, Resize Image, Validate Contacts, Accessibility Audit, Email Inbox Preview, and Inbox Placement, with each one’s credit cost on the row.
  • Every parameter you set rewrites a live request snippet, switchable between cURL, TypeScript (SDK), TypeScript, and Python. Copied snippets always carry the brew_your_api_key placeholder rather than the key the in-app run used.
  • Each capability also carries a copyable implementation prompt for a coding agent: endpoint, docs link, cost, the BREW_API_KEY auth pattern, the SDK method, the equivalent MCP tool, every request field, and an example body.
Runs are real API calls, so they charge credits and write to your brand exactly as a call from your backend would. Full walkthrough in API Catalog.
Validate contacts on ingestion & write-back; validationStatus rename

Public API v1: Validate Contacts as You Add Them

Contact deliverability validation now persists and reaches the ingestion endpoints:
  • POST /v1/contacts/validate now writes the verdict back onto matching contacts (it was read-only before), and each result adds risk, isDisposable, and isRole signals alongside the existing reason and didYouMean.
  • POST /v1/contacts and POST /v1/contacts/import-csv accept an optional validate: true, each address is deliverability-checked as it’s ingested and the verdict is saved. Metered 2 credits per address, charged only on success. Up to 100 addresses validate inline (the response carries a validation count summary); larger submissions upsert first and validate as a background job, returning a validationJobId.
  • The contact’s verdict field is renamed verificationStatusvalidationStatus. verificationStatus is dual-emitted with the same value for back-compat, so existing integrations keep working.
  • Also available via the create_contact, import_contacts_csv, and validate_contacts MCP tools.
Figma imports on the API, and full SDK parity

Figma to Email on the API, MCP, and SDK

Converting a Figma frame into an editable email was previously only possible in chat. It is now a first-class operation on every surface:
  • POST /v1/emails/figma takes { figmaUrl, title?, format?: 'jsx' | 'html' } and returns 201 { emailId, emailVersionId, title, format, content, warningCount, exportedNodeCount, previewImage? }. The figmaUrl must include a node-id, which is the link to one specific frame rather than the whole file.
  • The conversion is deterministic, with no model in the loop, so the same frame always converts the same way and the call is free.
  • Every surface uses the API-key brand’s connected Figma integration. Credentials are never accepted in the request or retained in API/MCP history. Without a usable connection you get 422 FIGMA_NOT_CONNECTED.
Also available as the import_figma_design MCP tool and as brew.emails.importFigma(...) in the SDK.

Every v1 operation now has an SDK method

The TypeScript SDK had drifted behind the API. These methods are new:
  • brew.emails.importFigma(), brew.emails.clone(), brew.emails.export()
  • brew.emails.createInboxPlacementTest() and brew.emails.getInboxPlacementResults(), the seed-list test of whether a design lands in the inbox or in spam
  • brew.sends.pause() and brew.sends.resume(), the reversible pair for an in-flight gradual send
  • brew.analytics.overview() for the exact totals, rates, and timeseries shown in Brew
  • brew.automations.run() plus brew.automations.audienceRuns.list() and .control() for manual-audience launch, scheduling, pause, resume, and cancel
  • brew.domains.health() for the aggregate deliverability score and signals
API v1, accessibility audits & contact deliverability validation

Public API v1: Check an Email and Your List Before You Send

Two pre-send quality checks are now on the Public API, the MCP tools, and the in-app agent:
  • POST /v1/emails/{emailId}/accessibility-audit runs a WCAG 2.1 audit of a design’s rendered HTML, colour contrast, image alt text, link text, heading structure, font size, language, and returns a score (0-100), a summary, and the specific issues with their WCAG criterion. Fixed 5 credits, charged only on success. (This endpoint is now a POST and credit-metered; it previously returned a lightweight local result.)
  • POST /v1/contacts/validate now runs a real deliverability check on up to 100 addresses at once, each comes back valid, risky (role account, disposable, catch-all), or invalid, with a machine-readable reason and a didYouMean typo correction. Metered 2 credits per address, charged only on success.
  • Both are value-aligned: if the check can’t complete, you get a retryable 503 and are not billed. Also available as the audit_email_accessibility and validate_contacts MCP tools.
API v1, preview a design across real inboxes & devices

Public API v1: See How an Email Renders in Real Inboxes

New POST /v1/emails/{emailId}/client-previews renders a design’s latest version across real email clients & devices: Gmail, Outlook, Apple Mail, iOS (with dark-mode variants), plus Yahoo, and returns a screenshot per client, rehosted on the Brew CDN.
  • Pass clients (ids from the supported catalogue) to target specific inboxes/devices, e.g. outlook2021_win11_dm_dt for Outlook 2021 on Windows in dark mode, or send {} for a popular default spread.
  • Fixed cost of 10 credits, charged only when at least one client renders (X-Credit-Cost: 10). A batch where zero clients finish in time returns a retryable 503 and is not billed; unknown client ids are rejected with a 422 before any paid work.
  • Slow clients that outlive the bounded render window come back in pending. Call again to retry just those.
  • Also available as the preview_email_across_clients MCP tool and as brew.emails.previewClients(...) in the SDK.
API v1, new POST /v1/sends/{sendId}/cancel

Public API v1: Cancel a Send

New endpoint to pull back a send before it goes out.
  • POST /v1/sends/{sendId}/cancel (“Cancel a send”). Cancels a scheduled or queued send → 200 { sendId, status: 'canceled' }. Idempotent, an already-canceled send returns 200. Once the send is sending, sent, or failed it is 409 SEND_NOT_CANCELLABLE; an unknown / cross-brand id is 404 SEND_NOT_FOUND. sends scope. The SDK method is brew.sends.cancel(sendId).
API v1 renames, /v1/account → /v1/usage, host-image → add-image

Public API v1: Two Operation Renames

Two endpoints (and their SDK methods) were renamed for clarity. The request and response shapes are unchanged.
  • GET /v1/accountGET /v1/usage (“Get usage”). The billing/quota surface, { plan, credits, emailSends, period }: keeps the same shape and the emails scope. The SDK method moves from brew.account.get() to brew.usage.get().
  • POST /v1/content/host-imagePOST /v1/content/add-image (“Add image”). Still optimizes the source image and saves it to the brand image library (fixed credit cost). The SDK method moves from brew.content.hostImage() to brew.content.addImage().
API v1 read-collapse, flat reads, polymorphic send, email import

Public API v1: Flat Reads + Unified Send

The v1 surface collapsed from 71 to 55 endpoints around one rule: one flat read per resource, identity in the query, ?include= opt-ins for the heavy detail. Plus a new way to bring existing designs into Brew.
  • Reads are flat. The per-resource get-one paths are gone. Pass the id key to the list endpoint instead: emails GET /v1/emails?emailId= (?include=html,versions), domains ?domainId=, audiences ?audienceId= (?include=count), automations ?automationId= (?include=graph,versions), automation runs GET /v1/automations/runs?automationRunId= (?include=logs), triggers ?triggerEventId=, trigger instances ?triggerInstanceId=, and sends GET /v1/analytics/sends?sendId= (?include=events, also ?emailId=). The single-send detail row carries previewImage, so POST /v1/emails/{emailId}/preview, GET /v1/emails/{emailId}/versions, and GET /v1/emails/{emailId}/sends were removed (on-demand rendering is POST /v1/content/html-to-png).
  • One polymorphic send. POST /v1/sends/test folded into POST /v1/sends. Pass { test: true } for the synchronous one-off QA send (200 { recipient }); omit it for the campaign send (202 { sendId }).
  • One contact read. GET /v1/contacts and GET /v1/contacts/{email} were replaced by POST /v1/contacts/search ({ filters, audienceId?, search?, sort, count?, cursor }); a by-email lookup is a { field: 'email', operator: 'equals' } filter.
  • New, POST /v1/emails/import. Bring existing html, mjml, or jsx into an editable Brew design (external images are re-hosted on the CDN). Usage-metered.
  • Semantic brand-image search. GET /v1/brand/images?q= runs a credit-metered vector search (plus ?type / ?aspectRatio); the no-q browse stays free.
  • Also removed: POST /v1/audiences/{audienceId}/duplicate.
The TypeScript SDK keeps its factory names: every read is one list() (id/include/filters in the args), send/sendTest merged into send(input) with test?, the contact read is search(), and emails.import() is new. See the updated API Introduction, SDK Overview, and the @brew.new/sdk changelog.
API v1 restructure, decoupled sends, 3-domain surface, /v1/help

Public API v1: Decoupled-Send Restructure

A breaking restructure of the v1 surface around a single insight: emails are pure designs, and a send is the unit of delivery and analytics. A design now carries no type and no send state. It can be sent any number of times.
  • Sends, unified. Campaign sends and automation sends are one entity. A campaign records one send; an automation records one send per recipient. Every delivery event attaches to its sendId.
  • Three clear domains. automations owns /v1/automations/* plus /v1/automations/triggers(/{id}/fire) (renamed from /v1/triggers) and /v1/automations/runs(/{runId}) (moved from /v1/analytics/automations/runs). analytics owns all reporting, including /v1/analytics/sends(/{sendId}/events) (send reads, moved off GET /v1/sends) and /v1/analytics/trigger-instances (the fired-trigger log, moved off /v1/events). sends is the action only: POST /v1/sends and POST /v1/sends/test.
  • POST /v1/sends now takes either a saved audienceId or an inline to list (≤ 50) and returns a sendId you poll under /v1/analytics/sends.
  • GET /v1/help: a no-auth, structured-JSON catalog of the whole API (scopes, credits, rate limits, every endpoint) for MCP / agent discovery, alongside GET /v1/llms.txt.
  • No more dry_run. Credit-metered operations just charge on success (402 INSUFFICIENT_CREDITS when short); check your balance with GET /v1/account.
  • POST /v1/content/host-image is now credit-metered and saves the image into the brand image library.
  • Removed: /v1/me, /v1/usage (use GET /v1/account), /v1/integrations, the single-template GET /v1/templates/{emailId} (the list GET /v1/templates stays and now returns html + previewImage per row), and automation-run replay.
See the updated API Introduction and the @brew.new/sdk changelog. The entries below describe earlier iterations of the v1 surface, paths noted there have since moved as summarized above.
API v1 hardening, 7 new endpoints, pagination, scopes

Public API v1: Hardening Pass

Seven new endpoints plus cross-cutting normalization across the whole API.
  • New observability + discovery endpoints: GET /v1/sends (campaign send list + stats), GET /v1/brand (the key’s brand + readiness), GET /v1/usage (API request volume + trend), GET /v1/analytics/events (unified event explorer, filter by recipientEmail for a contact’s full timeline), and GET /v1/integrations (triggerable integration-event catalog).
  • Test/preview sends: POST /v1/sends { mode: 'test' } sends a one-off preview to a single inbox, no verified domain or audience required, and it doesn’t consume the email’s live-send slot.
  • Automation run replay: POST /v1/automations/runs { automationRunId, mode: 'replay' } re-runs a prior run against the current saved draft.
  • Uniform cursor pagination: every list endpoint now accepts limit/cursor and returns a pagination envelope.
  • Lean lists + include=: GET /v1/templates and GET /v1/automations are lean by default. Pass ?include=html / ?include=graph to opt into the heavy fields.
  • Granular scopes: new least-privilege domains, sends, and audiences scopes; the coarse scopes still satisfy them, so existing keys are unaffected.
New TypeScript SDK methods: brew.brand.get(), brew.usage.get(), brew.integrations.list(), brew.analytics.sends.{list,listAll,get}() + brew.emails.sendTest(), and brew.analytics.{events,eventsAll}(). See the updated API reference, the new API Guides, and the @brew.new/sdk changelog.
API v1 lifecycle expansion

Public API v1: Full Lifecycle

The v1 API now covers the whole loop end-to-end for an org + brand API key.
  • Audiences are now full CRUD (POST/PATCH/DELETE + single fetch), and rows carry their filters, member count, and ISO timestamps.
  • Domains gained a full lifecycle: add → verify → set sender defaults → delete. GET /v1/domains now lists every domain (incl. pending rows + the DNS records to publish); ?sendableOnly=true returns just the send-ready set.
  • Analytics is now queryable: GET /v1/analytics/campaigns (lifetime per-campaign KPIs) and GET /v1/analytics/automations (windowed per-automation performance + totals).
  • Emails gained delete, version history (?include=versions), and non-destructive version restore.
Breaking: POST/PATCH /v1/triggers (since renamed to /v1/automations/triggers) now return the uniform { triggers: [row] } envelope (was { trigger }); contact timestamps are ISO-8601 strings. See the updated API reference + the @brew.new/sdk changelog.
OpenAPI 3.1 spec + TypeScript SDK

API Specification

Published OpenAPI 3.1 specification covering contacts, automations, triggers, automation runs, emails, sends, audiences, domains, fields, and templates. Official TypeScript SDK (@brew.new/sdk) is available; generate clients for other languages from the OpenAPI spec at https://brew.new/openapi/public-api-v1.yaml (see Generate Your Own SDK).