Start a contacts export
const url = 'https://api.tryletterhead.com/api/v3/contacts/export?api=true';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"channel":"the-morning-brief","statuses":[1]}'};
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/export?api=true' \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "channel": "the-morning-brief", "statuses": [ 1 ] }'Starts a CSV export of every contact that matches your filters, built in the background. The request returns straight away with an exportId; poll Get a contacts export with it until the status is ready, then download the file from the downloadUrl it returns. Each download link works for 7 days.
The file has one row per contact: first name, last name, and email, then one column per custom field you’ve defined, then the contact’s tags (separated by |), then one column per newsletter, headed with its slug, holding 1 when the contact is subscribed to it. Engagement and date-added columns aren’t included — use Browse contacts with filters for those.
It takes the same filters as Browse contacts with filters, so you can try a filter there before exporting. Send an empty body to export your whole audience. Larger audiences take longer to build, so poll every minute or so rather than continuously.
This is a company-level (v3) request. 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.
Export only the contacts of this one newsletter, by its identifier (slug).
Restrict to contacts whose subscription status 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).
Example
{ "channel": "the-morning-brief", "statuses": [ 1 ]}Responses
Section titled “ Responses ”The export has started. Poll Get a contacts export with the returned exportId.
object
object
Identifies this export. Pass it to Get a contacts export.
Always processing when the export has just started.
Example
{ "items": { "exportId": "api-20261013_141502-Vq3kT9xLm2Pz8RwYc4HnJd6F", "status": "processing" }, "message": "Your export has started. Poll its status for the download link.", "total": 0}Still can’t find what you need? Contact support.