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.

Current Client Surface

The TypeScript SDK is resource-oriented.
import { createBrewClient } from '@brew.new/sdk'

const brew = createBrewClient({
  apiKey: process.env.BREW_API_KEY!,
})

Resources And Methods

ResourceMethods
brew.audienceslist()
brew.automationscreate(), list(), get(), patch(), publish(), unpublish(), delete()
brew.contactslist(), listAll(), count(), getByEmail(), upsert(), upsertMany(), patch(), delete(), deleteMany()
brew.domainslist()
brew.emailslist(), generate(), edit()
brew.eventsfire() (deprecated alias — use brew.automationRuns.fire())
brew.automationRunsfire(), test(), replay(), list(), get(), cancel()
brew.fieldslist(), create(), delete()
brew.sendscreate()
brew.templateslist()
brew.triggerscreate(), list(), get(), patch(), delete()
The public SDK surface is deterministic-onlybrew.triggers and brew.automations do not expose AI authoring methods. AI body generation is still available on brew.emails.generate({ emailType, prompt }); chain it with brew.automations.create({ … }) to assemble automations programmatically. There is no brew.brands resource. Brand management lives in the Brew dashboard, and the single brand bound to your API key is the only brand the SDK can act on.

Common Flow — Trigger → Emails → Automation → Publish → Fire

End-to-end deterministic recipe: create a custom trigger, mint each automation-typed email body in parallel, assemble the graph referencing those emailIds, publish, and fire. Every step returns a typed result.
import { createBrewClient } from '@brew.new/sdk'

const brew = createBrewClient({ apiKey: process.env.BREW_API_KEY! })

// 1. Create the trigger (deterministic shape — provider is hardcoded brew_api).
const { trigger } = await brew.triggers.create({
  title: 'Subscription Renewed',
  description: 'Fires when a subscription is renewed.',
  payloadSchema: {
    type: 'object',
    fields: [
      { key: 'email', type: 'string', required: true },
      { key: 'plan', type: 'string', required: true },
      { key: 'amount', type: 'int', required: true },
    ],
  },
})

// 2. Pre-mint each automation-typed email body. emailType: 'automation'
//    keeps these rows off the /emails canvas — they're referenced by
//    sendEmail nodes inside the automation graph instead.
const [welcome, gettingStarted] = await Promise.all([
  brew.emails.generate({
    prompt: 'Thank-you email for a successful renewal.',
    emailType: 'automation',
  }),
  brew.emails.generate({
    prompt:
      'Getting-started tips for renewed subscribers — focus on the Pro features.',
    emailType: 'automation',
  }),
])

// 3. Assemble the automation graph; sendEmail nodes reference the
//    pre-minted emailIds + emailVersionIds.
const { automations } = await brew.automations.create({
  name: 'Renewal welcome flow',
  triggerEventId: trigger.triggerEventId,
  nodes: [
    {
      id: 'trg',
      label: 'On renewal',
      type: 'trigger',
      config: { triggerEventId: trigger.triggerEventId },
    },
    {
      id: 'send_welcome',
      label: 'Welcome',
      type: 'sendEmail',
      config: {
        emailId: welcome.emailId,
        emailVersionId: welcome.emailVersionId,
        domainId: 'dom_brand_primary',
        subject: 'Welcome back, {{firstName | there}}!',
        previewText: 'Quick thanks + 2 things to try first.',
      },
    },
    {
      id: 'wait_2d',
      label: 'Wait 2 days',
      type: 'wait',
      config: { duration: 2, unit: 'days' },
    },
    {
      id: 'send_getting_started',
      label: 'Getting started',
      type: 'sendEmail',
      config: {
        emailId: gettingStarted.emailId,
        emailVersionId: gettingStarted.emailVersionId,
        domainId: 'dom_brand_primary',
        subject: 'Getting started with Pro',
        previewText: 'Three feature tips for your first week.',
      },
    },
  ],
  connections: [
    { from: 'trg', to: 'send_welcome' },
    { from: 'send_welcome', to: 'wait_2d' },
    { from: 'wait_2d', to: 'send_getting_started' },
  ],
})
const automation = automations[0]

// 4. Publish.
await brew.automations.publish({
  automationId: automation.automationId,
})

// 5. Fire the trigger with a real payload.
const fire = await brew.automationRuns.fire({
  triggerEventId: trigger.triggerEventId,
  payload: {
    email: 'jane@example.com',
    plan: 'Pro',
    amount: 4200,
  },
  idempotencyKey: 'renewal-jane-2026-04-08',
})
console.log('Started automation runs:', fire.automationRunIds)

// 6. Poll the run lifecycle.
const run = await brew.automationRuns.get({
  automationRunId: fire.automationRunIds[0]!,
  include: ['logs'],
})
console.log('Status:', run.runs[0]?.status)

emailType on brew.emails.generate + brew.emails.list

brew.emails.generate({ emailType }) is required — the categorisation controls canvas placement and downstream filtering:
emailTypeCanvas board surfaceTypical use
campaignVisibleOne-shot sends to an audience / contact list.
automationHiddenBodies referenced by sendEmail nodes.
transactionalVisibleSystem-triggered (welcome / receipt / reset).
brew.emails.list({ emailType }) accepts the same enum as an optional filter so you can list every automation-typed body the brand has minted before authoring the next graph.

AutomationNodeInput — per-kind discriminated union

AutomationNodeInput is a discriminated union by type; setting node.type narrows node.config automatically. The five node kinds map 1:1 to the server-side Zod schemas:
node.typenode.config shape
trigger{ triggerEventId? }
sendEmail{ emailId, subject?, previewText?, fromAddress?, … }
wait{ duration, unit: 'minutes' | 'hours' | 'days' | 'weeks' }
filter{ logicalOperator, conditions[] }
split{ mode: 'percentage' | 'condition', … }
Each sendEmail node’s subject / previewText support {{variable | fallback}} interpolation against the trigger payload.

Source Of Truth

The SDK follows the Brew OpenAPI contract. If you want the raw HTTP shape behind any method, use the API reference in this docs site.

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.