Ad-hoc audience CSV export
A saved segment is the right home for an audience you target repeatedly. But sometimes you need the rows behind a filter exactly once — a compliance spot-check, a partner handoff, an analyst’s exploratory pull — and creating a segment purely to hold a transient membership is noise. The ad-hoc export endpoint resolves your filter live against your contacts and hands you the CSV directly: nothing is persisted, nothing waits on a refresh schedule.Ad-hoc vs. saved segment export
Two CSV export surfaces exist; pick by how long the audience needs to live.
Rule of thumb: if you would delete the segment right after downloading, use the ad-hoc export.
Authentication and permissions
PII bulk pulls are privileged, and this endpoint gates exactly like the saved export:- The caller must hold an owner, admin, or developer role.
- The API key must carry the
contacts:writescope. Viewer roles andcontacts:read-only keys are rejected with a 403. - Exports are rate-limited to 5 requests per minute, and every download — row counts included — is written to your audit log (
segment.audience_exported).
Request shape
The body carries the same Filter AST the segment builder andPOST /api/v1/segments/auto-suggest produce — fields come from the segment filter allowlist, and groups nest up to three levels deep.
Row cap and truncation
A single ad-hoc export resolves at most 50,000 rows (unlike the saved export, which streams up to 500,000). If the filter reaches the cap, the response still succeeds with the first 50,000 rows and sets theX-Export-Truncated: true response header — check that header whenever the row count matters. To pull more than the cap, persist the audience as a segment and use the saved export path.
CSV columns and PII visibility
One row per matched contact, with this header row:phone and email columns are masked or revealed to match what the caller’s role and reveal context would see in the UI. An owner with an active reveal gets full values; a caller without one gets masked values. A CSV pulled by two different callers can differ in exactly those columns — never assume a second pull by another teammate will match byte-for-byte.
Use cases
- GDPR ingest verification. After a bulk import, export “contacts created in the last hour with missing consent fields” and confirm the ingest mapped them before anything downstream picks them up.
- Partner handoff. A partner asks for a segment of your audience once. Send the filter, get the CSV, delete nothing because you never created anything.
- Exploratory analysis. An analyst iterating on a filter — preview the size with
POST /api/v1/contacts/segments/preview, then pull the rows to a spreadsheet the moment the definition is right.
When to save the segment instead
Materialize a real segment —POST /api/v1/contacts/segments — when the audience has a future, because several downstream surfaces only read saved segments:
- Scheduled refresh.
auto_refreshkeeps membership current on a schedule (12 hours up to monthly), so exports and campaigns track a moving population without re-sending the filter. - Campaigns and flows. Targeting, enroll-on-entry, and suppression all reference a segment id; a one-shot export cannot.
- Ad-network activation. Audience sync to Meta, Google, TikTok, and the other supported platforms pushes a saved segment.
- Above-cap or repeat downloads. The saved export streams over the 50,000-row ad-hoc ceiling, and re-downloading a saved segment skips re-resolving the filter.
See also
- CDP audiences — build and save segments, computed traits, and ad-network activation
- Segments API reference — full endpoint list for segments, exports, and overlap
- Import contacts — the ingest side of the GDPR verification flow above