Export an Audience to S3, Email, or Slack
Use Case
- Deliver a saved audience to your own S3 bucket on a schedule (e.g. daily)
- Send the same file to teammates by email or to a Slack channel instead
- Control the record type, file format, and exact columns in the output
A scheduled export has two parts: an integration (the destination, set up once) and an export (what to send and when, pointed at that integration). This recipe creates an S3 integration, then a daily export to it, then shows the email and Slack variants.
Prerequisites
- Organization API key + secret pair (Authentication). Create one at
https://app.delivr.ai/{org_id}/settings/api-keys. - A project id (the workspace the export lives in).
- An audience id to export (Intent Audiences API).
- For S3: a bucket and an IAM access key with write access to it.
Steps
1. Create the S3 Integration
Create the destination once. The organization comes from your key; pass the project as project_id. Credentials are write-only: they are stored encrypted and never returned.
curl -X POST "https://api.delivr.ai/api/v1/integrations?project_id=YOUR_PROJECT_ID" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "X-Api-Secret: YOUR_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"type": "s3",
"name": "Warehouse bucket",
"region": "us-west-2",
"bucket_name": "my-company-exports",
"access_key_id": "AKIAEXAMPLE0123456789",
"secret_access_key": "your-aws-secret-access-key",
"prefix": "delivr/audiences",
"path_format": "date",
"file_format": "csv"
}'The response is the created integration. Note its id; the export references it.
{
"id": "b7c4e2a1-9f3d-4c8e-a1b2-3c4d5e6f7a8b",
"organization_id": "0a1b2c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
"project_id": "YOUR_PROJECT_ID",
"type": "s3",
"name": "Warehouse bucket",
"config": { "settings": { "bucket_name": "my-company-exports", "region": "us-west-2", "prefix": "delivr/audiences", "path_format": "date", "file_format": "csv" } },
"has_credentials": true,
"enabled": true,
"created_at": "2026-06-25T18:00:00Z",
"updated_at": "2026-06-25T18:00:00Z"
}2. Create the Export
Create a daily export that draws from your audience and delivers to the integration from step 1. The query selects what to send; the destination says where and in what shape.
curl -X POST "https://api.delivr.ai/api/v1/exports" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "X-Api-Secret: YOUR_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"project_id": "YOUR_PROJECT_ID",
"name": "Daily warehouse drop",
"query": {
"sourceType": "audience",
"sourceId": "YOUR_AUDIENCE_ID"
},
"schedule": "daily",
"run_time": "09:00",
"destination": {
"type": "s3",
"integration_id": "b7c4e2a1-9f3d-4c8e-a1b2-3c4d5e6f7a8b",
"record_type": "contacts_only",
"file_format": "csv",
"fields": ["first_name", "last_name", "email", "company_domain"],
"array_transform": "comma",
"combine_output": true
}
}'The response contains both the created export and its destination:
{
"export": {
"id": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
"name": "Daily warehouse drop",
"schedule": "daily",
"run_time": "09:00",
"status": "active",
"enabled": true,
"created_at": "2026-06-25T18:01:00Z",
"updated_at": "2026-06-25T18:01:00Z"
},
"destination": {
"id": "d4e5f6a7-b8c9-4d0e-1f2a-3b4c5d6e7f80",
"export_id": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
"type": "s3",
"status": "active",
"enabled": true
}
}The export now runs every day at 09:00 UTC and writes a CSV to s3://my-company-exports/delivr/audiences/<date>/.
Destination Config Reference
All file-delivery destinations (s3, email, slack) share these fields:
| Field | What it does |
|---|---|
record_type | What each output record encodes: hem, uid2, raw_events, raw_logs, contacts_only, ip, domain, or maid. The value valid for a given export depends on its source (here, contacts_only for an audience export; raw_events for a pixel / DSP event export). |
file_format | csv, json, jsonl, or parquet. |
fields | Output column allow-list. Omit to use the default set for the record type. |
array_transform | How to render a multi-value field in one cell: first, comma, pipe, semicolon, json, or count. Defaults to first. |
filename_template | Override the generated filename. |
S3 and email add two file-write options (not available on Slack):
| Field | What it does |
|---|---|
combine_output | Combine a multi-window run into one file. Not allowed with parquet. |
emit_empty_file | Deliver a file even when there are zero records. |
S3 also adds prefix and path_format (flat, date, or project).
Variations
Email the File
Use an email integration (recipients are configured on the integration in the dashboard). Same delivery fields, plus an optional subject_template:
"destination": {
"type": "email",
"integration_id": "YOUR_EMAIL_INTEGRATION_ID",
"record_type": "contacts_only",
"file_format": "csv",
"fields": ["first_name", "last_name", "email", "company_domain"],
"subject_template": "Daily audience export"
}Post to Slack
Use a slack integration (the channel is configured on the integration):
"destination": {
"type": "slack",
"integration_id": "YOUR_SLACK_INTEGRATION_ID",
"record_type": "contacts_only",
"file_format": "csv"
}Weekly Instead of Daily
Set schedule to weekly and add run_day_of_week (0 = Sunday … 6 = Saturday):
"schedule": "weekly",
"run_day_of_week": 1,
"run_time": "09:00"Cap the Row Count
Add a top-level record_limit to the export (max 10,000,000):
"record_limit": { "maxRecords": 50000, "failMode": "soft" }failMode decides what happens when the export has more records than the cap:
| Value | Behavior |
|---|---|
soft (default) | Deliver up to the limit and mark the run partial. |
hard | Check the count first and abort if it is over the limit, delivering nothing. |
Use hard when a truncated file is worse than no file, for example when the recipient treats each delivery as a complete list.
Send One Export to Several Destinations
An export can deliver to up to 5 destinations at once, for example the S3 bucket above plus a Slack channel for the team. Add the rest at create time with additional_destinations (same shape as destination, one saved integration each):
{
"project_id": "YOUR_PROJECT_ID",
"name": "Daily warehouse drop",
"query": { "sourceType": "audience", "sourceId": "YOUR_AUDIENCE_ID" },
"schedule": "daily",
"run_time": "09:00",
"destination": {
"type": "s3",
"integration_id": "b7c4e2a1-9f3d-4c8e-a1b2-3c4d5e6f7a8b",
"record_type": "contacts_only",
"file_format": "csv"
},
"additional_destinations": [
{
"type": "slack",
"integration_id": "YOUR_SLACK_INTEGRATION_ID",
"record_type": "contacts_only",
"file_format": "csv"
}
]
}The response's destination is the S3 row (the primary, "primary": true); additional_destinations holds the rest.
To add a destination to an export that already exists, call POST /api/v1/exports/{id}/destinations with one destination instead of resending the whole export:
curl -X POST "https://api.delivr.ai/api/v1/exports/YOUR_EXPORT_ID/destinations" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "X-Api-Secret: YOUR_API_SECRET" \
-H "Content-Type: application/json" \
-d '{
"type": "slack",
"integration_id": "YOUR_SLACK_INTEGRATION_ID",
"record_type": "contacts_only",
"file_format": "csv"
}'Every destination on an export is delivered as part of the same run, and the run is billed once for the data, not once per destination. When the destinations use different products, the run is billed at the highest-priced one, for the largest record count any billable destination received. DelivrDSP destinations are never billed as data.
additional_destinations is only accepted alongside destination on create; use POST /api/v1/exports/{id}/destinations to add to an export afterward. An export can have at most 5 destinations, each on a different connection. A marketplace destination cannot be combined with any other destination, and a DelivrDSP destination can only be an export's first destination.
Notes
- One call creates both the export and its destination, so you never get an export with nowhere to deliver. Create the integration first; the export references it by
integration_id. - Credentials (
access_key_id,secret_access_key) are write-only. List and get responses returnhas_credentials: trueinstead of the secret. - Export names are unique within a project; a duplicate returns
409. - An export's first destination is its "primary" (
"primary": truein responses). - The
project_idand the destination'sintegration_idmust both belong to your key's organization, or the call returns400. - Email (recipients) and Slack (OAuth) integrations are set up in the dashboard; S3 and DelivrDSP authenticate with credentials and can be created via the Integrations API.
Next Steps
- Integrations API: create, list, update, and delete destinations
- Exports API: create, list, get, update, and delete exports (all destination types and fields)
- Add an Export Destination: add a destination to an export that already exists
- Activate an Audience to DelivrDSP: push an audience to DelivrDSP for ad targeting
- Intent Audiences API: build the audiences you export
Updated 10 days ago
