Browse contacts with filters
const url = 'https://api.tryletterhead.com/api/v3/contacts/browse?api=true';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"tags":["engaged-readers"],"statuses":[1],"pageSize":25}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url 'https://api.tryletterhead.com/api/v3/contacts/browse?api=true' \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "tags": [ "engaged-readers" ], "statuses": [ 1 ], "pageSize": 25 }'Returns a filtered, paginated page of your company’s contacts — the same query the contacts table on your audience page runs. Unlike Search contacts, this endpoint accepts a fuller filter set: multiple channels and statuses (OR’d together), tag terms, typed custom-field comparisons, a saved segment to intersect with, and a created-date window. Results are cursor-paginated with searchAfter.
Each returned contact also carries the segments it currently belongs to.
This is a company-level (v3) read. Authenticate with a company API key as a Bearer token.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Query Parameters
Section titled “Query Parameters ”Required. Set to true.
Request Body
Section titled “Request Body ”object
Free-text search across email, first name, and last name. Max 500 characters.
Restrict to contacts subscribed to any of these channel identifiers (slugs).
Restrict to contacts whose subscription status (on any matched channel) is one of these values. See the subscription status table on Add or update subscriptions in bulk.
Restrict to contacts carrying any of these tags.
Restrict to contacts with no tags at all. Mutually exclusive with a non-empty tags.
Typed custom-field comparisons, AND’d together with the rest of the filter.
object
The custom field’s name.
eq, ne, gt, gte, lt, lte, contains, or exists.
Comparison value. Omit when op is exists.
A saved segment (see List segments) whose criteria are AND-merged with the rest of this filter set.
Restrict to contacts created on or after this date (inclusive). Date-only (YYYY-MM-DD) or a full ISO 8601 timestamp.
Restrict to contacts created on or before this date (inclusive).
name, email, status, or dateAdded. Defaults to dateAdded.
asc or desc. Defaults to desc.
Page size, 1–100. Defaults to 25.
Opaque cursor from the previous page’s searchAfter. Omit or send null for the first page.
Narrow the browse to a single channel identifier (slug) — the shape the channel-level audience page uses.
Example
{ "tags": [ "engaged-readers" ], "statuses": [ 1 ], "pageSize": 25}Responses
Section titled “ Responses ”200 OK
object
object
The matched contacts for this page.
object
object
object
object
object
The segments this contact currently belongs to.
object
Opaque cursor for the next page — pass it back as searchAfter.
Whether the top-level total is exact (eq) or a lower bound (gte).
Example
{ "items": { "contacts": [ { "firstName": "Avery", "lastName": "Chen", "tags": [ "engaged-readers" ], "customFields": { "__lh.mailboxProvider": "gmail", "lastOpenDate": "2026-06-18 05:11:33" }, "endpoints": [], "channelConsents": [], "consents": [], "createdAt": "2026-05-23T11:43:15+00:00", "updatedAt": "2026-06-18T09:12:04+00:00", "segments": [ { "id": 7, "name": "Highly engaged readers" } ] } ], "searchAfter": "WzE3MTg3NTUxOTUwMDAsImF2ZXJ5LmNoZW5AZXhhbXBsZS5jb20iXQ==", "totalRelation": "eq" }, "message": "Contacts retrieved.", "total": 842}Still can’t find what you need? Contact support.