> ## 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.

# TypeScript Quickstart

> Upsert contacts, browse templates, generate on-brand emails, list domains and audiences, and send your first campaign using the Brew TypeScript SDK.

## Create The Client

Get an API key from
[brew.new/settings/api](https://brew.new/settings/api). Each key is
bound to one brand at creation — pick the brand you want this client
to act on before generating.

```ts theme={null}
import { createBrewClient } from '@brew.new/sdk'

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

## 1. Upsert A Contact

```ts theme={null}
const contactResult = await brew.contacts.upsert({
  email: 'john@example.com',
  firstName: 'John',
  lastName: 'Doe',
  subscribed: true,
  customFields: {
    plan: 'enterprise',
  },
})

console.log(contactResult.contact.email)
console.log(contactResult.created)
```

`created: false` means the contact already existed and was updated. Both outcomes are successful.

## 2. Browse Public Templates (optional)

```ts theme={null}
const { data: templates } = await brew.templates.list({
  brand: 'vercel.com',
})
```

Templates are public reference emails. Pass any one as
`referenceEmailId` to email generation when you want to anchor the
output on its layout. Your own brand design context is automatic —
every API key is bound to one brand at creation, and `brew.emails.generate`
grounds itself in that brand without you ever passing a `brandId`.

## 3. Generate An Email

```ts theme={null}
const generated = await brew.emails.generate({
  prompt: 'Create a welcome email for new subscribers',
  referenceEmailId: templates[0]?.emailId,
})

if ('emailId' in generated) {
  console.log(generated.emailId)
  console.log(generated.html)
} else {
  console.log(generated.response)
}
```

## 4. Edit A Saved Email (optional)

`brew.emails.edit` runs the agent against an existing email's current
`latest` version and persists a new `version: "latest"` row on the same
`emailId`, demoting the previous head to a numeric historical version.

```ts theme={null}
if ('emailId' in generated) {
  const edited = await brew.emails.edit({
    emailId: generated.emailId,
    prompt: 'Tighten the headline and add a friendlier sign-off.',
  })

  if ('emailId' in edited) {
    console.log(edited.emailId, edited.html)
  }
}
```

The brand is resolved from the API key. The `emailId` is a path
parameter — neither `brandId` nor `emailId` may appear in the body.

## 4b. Import An Existing Email (optional)

Already have HTML or react-email JSX? `brew.emails.import` ingests it
into an editable Brew design — external images are re-hosted on the CDN.
It is usage-metered.

```ts theme={null}
const imported = await brew.emails.import({
  format: 'html', // or 'mjml' / 'jsx'
  content: '<html><body><h1>Hello</h1></body></html>',
  title: 'Imported welcome',
})

console.log(imported.emailId, imported.emailVersionId)
```

## 5. List Verified Domains

```ts theme={null}
const { data: domains } = await brew.domains.list()

if (domains.length === 0) {
  throw new Error('You need a verified sending domain before sending.')
}
```

## 6. Send An Email

`brew.emails.send(...)` delivers a design to a target — a saved
brand-owned `audienceId`, an inline `to` list (≤ 50), or a single
address — via a verified domain. It is not campaign-specific: send the
same design as many times as you like. For per-recipient event-driven
delivery — welcome flows, drip campaigns, transactional fires — chain
`brew.automations.triggers.fire(...)` against a published automation
graph instead (see the cookbook).

Audience send example:

```ts theme={null}
const { data: audiences } = await brew.audiences.list()

if ('emailId' in generated) {
  const sendResult = await brew.emails.send({
    emailId: generated.emailId,
    domainId: domains[0]!.domainId,
    audienceId: audiences[0]!.audienceId,
    subject: 'Welcome to Brew',
  })

  console.log(sendResult.status)
  console.log(sendResult.runId)
}
```

Scheduled send example (pin to a specific email version with
`emailVersionId`):

```ts theme={null}
await brew.emails.send({
  emailId: 'email_123',
  emailVersionId: 'emv_123_v2',
  domainId: 'domain_123',
  audienceId: 'audience_123',
  subject: 'Launch update',
  scheduledAt: '2099-01-01T00:00:00.000Z',
})
```

QA a design before the blast with the same `send` method — pass
`test: true` and a single `to` address. It delivers synchronously from
the Brew sender (no verified domain or audience needed) and returns
`{ status: 'sent', recipient }`:

```ts theme={null}
const test = await brew.emails.send({
  test: true,
  emailId: 'email_123',
  subject: 'Welcome to Brew',
  to: 'you@example.com',
})

console.log(test.recipient)
```

## Handle Errors

```ts theme={null}
import { BrewApiError } from '@brew.new/sdk'

try {
  await brew.domains.list()
} catch (error) {
  if (error instanceof BrewApiError) {
    console.error(error.code, error.message, error.requestId)
  }
  throw error
}
```

## Next Steps

<CardGroup cols="2">
  <Card title="Resource Surface" icon="boxes-stacked" href="/sdks/typescript/resources">
    See the current TypeScript SDK resources and methods.
  </Card>

  <Card title="API Reference" icon="book" href="/api-reference/api/api-introduction">
    See the raw HTTP contract behind the SDK.
  </Card>
</CardGroup>

## 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:

<Tabs>
  <Tab title="Self-Service Tools">
    <CardGroup cols="2">
      <Card title="Search Documentation" icon="magnifying-glass" color="#c44925">
        Type in the "Ask any question" search bar at the top left to instantly find relevant documentation pages.
      </Card>

      <Card title="ChatGPT/Claude Integration" icon="robot" color="#c44925">
        Click "Open in ChatGPT" at the top right of any page to analyze documentation with ChatGPT or Claude for deeper insights.
      </Card>
    </CardGroup>
  </Tab>

  <Tab title="Talk to Our Team">
    <CardGroup cols="2">
      <Card title="Schedule a Call" icon="calendar" color="#c44925" href="https://calendar.google.com/calendar/u/0/appointments/schedules/AcZssZ1iYoRUG1J792XQpbuQLjSRRDupr7MwraFK-HQRCtTYdBmrQi8nZu2qXfzKQigb8gbKJK3KN3-R">
        Book time with our founders for personalized guidance on strategy, best practices, or complex implementation questions.
      </Card>

      <Card title="Call Us Directly" icon="phone" color="#c44925">
        Need immediate assistance? Reach us at **+1-(332)-203-2145** for urgent issues or time-sensitive questions.
      </Card>

      <Card title="Slack Channel" icon="slack" color="#c44925">
        Our preferred support channel. You'll receive an invite after signup for direct founder support and fast responses.
      </Card>

      <Card title="Email Support" icon="envelope" color="#c44925" href="mailto:support@brew.new">
        Contact us at **[support@brew.new](mailto:support@brew.new)** for detailed inquiries or if you prefer not to use Slack.
      </Card>
    </CardGroup>
  </Tab>
</Tabs>
