Skip to main content
A send is the unit of delivery and analytics in Brew. Every email you send with POST /v1/sends mints one sendId, the thing you poll for lifecycle status and aggregate stats. Reads are flat: one endpoint, identity in the query.
  • GET /v1/analytics/sends: list every send for the brand, with stats.
  • GET /v1/analytics/sends?sendId=…: one send’s lifecycle status + stats.
  • GET /v1/analytics/sends?sendId=…&include=events: the same row with its per-recipient event feed inlined.
  • GET /v1/analytics/sends?emailId=…: every send for one design.
These reads use the emails scope. The send action, POST /v1/sends, polymorphic by test, uses the sends scope (or emails).

List recent sends

curl -G "https://brew.new/api/v1/analytics/sends" \
  -H "Authorization: Bearer $BREW_API_KEY" \
  --data-urlencode "status=sent" \
  --data-urlencode "limit=50"
import { createBrewClient } from '@brew.new/sdk'

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

const { data, pagination } = await brew.analytics.sends.list({ status: 'sent', limit: 50 })
for (const send of data) {
  console.log(send.sendId, send.status, send.stats?.delivered, '/', send.stats?.sent)
}
The response is the uniform list envelope: { data, pagination }. See Pagination for the cursor loop, or use the SDK auto-pager:
for await (const send of brew.analytics.sends.listAll({ status: 'sent' })) {
  console.log(send.sendId, send.stats?.opened)
}

Poll a single send

Look one send up by passing ?sendId= to watch it move from queuedsendingsent and to read its rolled-up stats. An unknown or cross-brand id returns 404 SEND_NOT_FOUND.
curl -G "https://brew.new/api/v1/analytics/sends" \
  -H "Authorization: Bearer $BREW_API_KEY" \
  --data-urlencode "sendId=snd_8fK2mQ4p"
const { data } = await brew.analytics.sends.list({ sendId: 'snd_8fK2mQ4p' })
const send = data[0]!
console.log(send.status, send.completedAt, send.stats)

Read the per-recipient feed

Once a send is in flight, drill into its individual delivery events: sent / delivered / opened / clicked / bounced / complained / unsubscribed. Add ?include=events to the single-send read to inline the feed on the same row.
curl -G "https://brew.new/api/v1/analytics/sends" \
  -H "Authorization: Bearer $BREW_API_KEY" \
  --data-urlencode "sendId=snd_8fK2mQ4p" \
  --data-urlencode "include=events"
const { data } = await brew.analytics.sends.list({
  sendId: 'snd_8fK2mQ4p',
  include: 'events',
})
for (const event of data[0]?.events ?? []) {
  console.log(event.recipientEmail, event.url, event.occurredAt)
}

Send a test email

The same POST /v1/sends endpoint sends a test when you pass test: true. A test send forces the Brew default sender, requires no verified domain or audience, does not write a send row, and resolves synchronously to 200 { status: 'sent', recipient }.
curl -X POST "https://brew.new/api/v1/sends" \
  -H "Authorization: Bearer $BREW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "test": true,
    "emailId": "eml_promo",
    "subject": "Preview: Black Friday",
    "to": "qa@example.com"
  }'
const { status, recipient } = await brew.emails.send({
  test: true,
  emailId: 'eml_promo',
  subject: 'Preview: Black Friday',
  to: 'qa@example.com',
})
// { status: 'sent', recipient: 'qa@example.com' }
The live (campaign) send is the same endpoint without test. It returns 202 { status: 'queued' | 'scheduled', sendId, runId }. See Async jobs & polling.

See also

  • GET /v1/analytics/sends in the Public API v1 reference (sidebar), full parameter + schema reference.
  • Errors: SEND_NOT_FOUND, DOMAIN_NOT_READY, AUDIENCE_NOT_FOUND.
  • Sends (SDK): emails.send (pass test: true for a QA send), analytics.sends.{list,listAll} (?sendId, ?include=events).

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.