curl --request POST \
--url https://brew.new/api/v1/contacts/search \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"filters": [
{
"field": "plan",
"operator": "equals",
"value": "enterprise"
}
],
"sort": "createdAt",
"order": "desc",
"limit": 50
}
'{
"data": [
{
"email": "jane@example.com",
"firstName": "Jane",
"lastName": "Doe",
"subscribed": true,
"validationStatus": "valid",
"verificationStatus": "valid",
"suppressed": false,
"suppressedReason": null,
"consent": {
"source": "form",
"capturedAt": "2026-04-08T12:00:00.000Z",
"policyVersion": "2026-03"
},
"createdAt": "2026-04-08T12:00:00.000Z",
"updatedAt": "2026-04-08T12:05:00.000Z",
"importId": null,
"customFields": {
"plan": "enterprise",
"revenue": 4200
}
},
{
"email": "john@example.com",
"firstName": "John",
"lastName": "Smith",
"subscribed": true,
"validationStatus": "valid",
"verificationStatus": "valid",
"suppressed": false,
"suppressedReason": null,
"consent": {
"source": "form",
"capturedAt": "2026-04-08T12:00:00.000Z",
"policyVersion": "2026-03"
},
"createdAt": "2026-04-08T12:00:00.000Z",
"updatedAt": "2026-04-08T12:05:00.000Z",
"importId": null,
"customFields": {
"plan": "starter"
}
}
],
"pagination": {
"limit": 50,
"cursor": "eyJsYXN0SWQiOiIxMjMiLCJsYXN0U29ydCI6MTcxMjU5MjAwMDAwMH0=",
"hasMore": true
}
}Get contacts
The single “Get Contacts” read. Structured search over the brand’s contacts: free-text search, filters ({ field, operator, value } combined with logic: "and" | "or" | "none"; the allowed operators depend on the field’s type — see the operator schema — and an unsupported pairing is a 400, never a dropped clause), sort + order, and cursor pagination. Returns { data, pagination }.
Folds the former GET /v1/contacts (omit all filters to list everything) and GET /v1/contacts/{email} (use filters: [{ field: "email", operator: "equals", value: "…" }]).
Pass an optional audienceId to scope the search to a saved audience’s members — its stored filter set is evaluated as one unit with its own logicalOperator (an OR audience stays an OR) and then ANDed with filters, so the page is exactly who a send to that audience reaches (an unknown / cross-brand id, or an audience a send would refuse → 400).
Set count: true to get { count } instead of a page.
curl --request POST \
--url https://brew.new/api/v1/contacts/search \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"filters": [
{
"field": "plan",
"operator": "equals",
"value": "enterprise"
}
],
"sort": "createdAt",
"order": "desc",
"limit": 50
}
'{
"data": [
{
"email": "jane@example.com",
"firstName": "Jane",
"lastName": "Doe",
"subscribed": true,
"validationStatus": "valid",
"verificationStatus": "valid",
"suppressed": false,
"suppressedReason": null,
"consent": {
"source": "form",
"capturedAt": "2026-04-08T12:00:00.000Z",
"policyVersion": "2026-03"
},
"createdAt": "2026-04-08T12:00:00.000Z",
"updatedAt": "2026-04-08T12:05:00.000Z",
"importId": null,
"customFields": {
"plan": "enterprise",
"revenue": 4200
}
},
{
"email": "john@example.com",
"firstName": "John",
"lastName": "Smith",
"subscribed": true,
"validationStatus": "valid",
"verificationStatus": "valid",
"suppressed": false,
"suppressedReason": null,
"consent": {
"source": "form",
"capturedAt": "2026-04-08T12:00:00.000Z",
"policyVersion": "2026-03"
},
"createdAt": "2026-04-08T12:00:00.000Z",
"updatedAt": "2026-04-08T12:05:00.000Z",
"importId": null,
"customFields": {
"plan": "starter"
}
}
],
"pagination": {
"limit": 50,
"cursor": "eyJsYXN0SWQiOiIxMjMiLCJsYXN0U29ydCI6MTcxMjU5MjAwMDAwMH0=",
"hasMore": true
}
}Authorizations
Send your Brew API key as Authorization: Bearer brew_xxx.
Headers
The brand this request acts on. REQUIRED for organization-scoped credentials (otherwise 400 BRAND_ID_REQUIRED — there is no default brand); list ids with GET /v1/brands. Brand-scoped credentials may omit it, and sending a different brand returns 403 BRAND_SCOPE_MISMATCH. A brand outside your organization returns 404 BRAND_NOT_FOUND.
1 - 64Body
1Show child attributes
Show child attributes
Scope to a saved audience's members. The audience's stored filter set is evaluated as one unit with its own logicalOperator (an OR audience stays an OR), then ANDed with filters. Unknown / cross-brand id, or an audience a send would refuse (unusable filters, a cohort still building) → 400.
1and, or, none 1asc, desc 1 <= x <= 1001Was this page helpful?