Skip to main content
The v1 cleanup gave every collection a real detail read, moved sends to their own root, turned lifecycle changes into action sub-paths, and collapsed four overlapping status vocabularies into one. There are no aliases and no deprecation window: the old spellings return 400 or 404 today. This page is the grep list. Each row is the old string to search your codebase for and the string to replace it with. The generated Public API v1 reference is the authority on the exact request and response shapes.

1. Read One Row by Its Path

The old trick was to call a list with an id filter and take data[0]. Those query keys are gone and now return 400 INVALID_REQUEST with param naming the key. Every detail read returns the bare row, so drop the data[0] unwrap too. New reads with no predecessor: GET /v1/automations/audience-runs/{audienceRunId}, GET /v1/automations/trigger-instances/{triggerInstanceId}, and GET /v1/emails/{emailId}/inbox-placement-tests/{testId}. The ?include= opt-ins still work, now on the path read: GET /v1/emails/{emailId}?include=html,versions. The full list is in Pagination.
An id in a query string is not always wrong. GET /v1/sends and GET /v1/automations/runs still take automationId, automationRunId, audienceRunId, and triggerInstanceId as deliberate join filters, because those return many rows, not one.

2. Sends Moved to Their Own Root

/v1/analytics keeps exactly three reports: overview, automations, and the unified events feed. See Monitor campaign sends.

3. Lifecycle Changes Are Action Sub-Paths

A status is no longer something you PATCH onto a row. Cancel answers 200 with the new status and, for an automation run, the previousStatus it left. The readiness body is bare: { ready, blockers[], payloadSchema, endpoint, publishedAutomations, counts }, with no details wrapper.

4. Renamed Request and Response Fields

Those two were the last snake_case fields on the wire. Everything v1 accepts and returns is camelCase now. Send rows gained automationId, nodeId, automationRunId, audienceRunId, and triggerInstanceId, so an automation delivery can be joined back to the run that produced it without a second call. Two responses became explicit rather than a bare count: POST /v1/contacts/batch-delete returns { deletedCount, notFound[] }, and DELETE /v1/api-keys/{keyId} returns { keyId, deleted, revokedAt? }.
The event row field is still recipientEmail. Only the query filter was renamed to recipient.

TriggerInstance.state Became an Enum

A fired trigger’s state used to be a free string. It is now a closed set you can branch on:
fired means every matched automation started. partially_fired means some starts are still being retried, so it is not a terminal answer: read the instance again rather than treating it as a failure.

5. One Status Vocabulary

Runs, sends, audience builds, and inbox-placement tests all report the same set. Anything typed against an old spelling in a status filter is now 400 INVALID_REQUEST.
A step or node inside a run reports running | completed | failed | skipped. An email design reports generating | ready | failed, so the old streaming and complete spellings are gone there too. A synchronous test send now resolves to 200 { status: 'completed', recipient }.

6. Errors

New this cleanup: 403 ORG_SCOPE_REQUIRED when a brand-bound key calls an operation that acts on the organization, such as GET /v1/usage. A person missing the role still gets 403 INSUFFICIENT_ROLE. See Organization and brand credentials. The full catalog, generated from the specification, is on Errors.

7. TypeScript SDK 10

Twenty methods were added, mostly the detail reads and the send root: And these were removed or retargeted: analytics keeps only the reports: overview, events, automations.

8. CLI 0.7

brew-cli 0.7 depends on @brew.new/sdk 10. Six commands were retargeted at the new routes, and the command names you already type are unchanged, so brew-cli automations triggers ready still works. New commands cover the detail reads, the sends root, trigger instances, and the four lifecycle actions. Raw brew-cli api calls in your scripts are not retargeted for you: they go straight to the path you typed, so grep those against section 1.

Migration Checklist

1

Grep for the retired query keys

Search for ?emailId=, ?audienceId=, ?automationId=, ?automationRunId=, ?triggerEventId=, ?sendId=, ?triggerInstanceId=, and ?domainId=. Each one that reads a single row becomes a path read.
2

Grep for the analytics paths

analytics/sends, analytics/campaigns, and analytics/trigger-instances have no replacement at the same path.
3

Grep for old status strings

'sent', 'sending', 'partially_sent', 'pending', 'streaming', 'complete', and 'cancelled' in filters and comparisons.
4

Drop the data[0] unwrap

A detail read returns the row. body.data[0] will be undefined.
5

Drop runId from send handling

POST /v1/sends no longer returns one. Persist sendId instead.
6

Grep for snake_case request keys

dry_run and stop_in_flight are rejected. Send dryRun and stopInFlight.
7

Re-check your credential

If any call now returns 403 ORG_SCOPE_REQUIRED, mint an organization-scoped key for it. See Organization and brand credentials.

See Also

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 explore it further with ChatGPT or Claude.