Paging Audience Records

Read a built audience as JSON pages instead of downloading files

Overview

GET /api/v1/audiences/{id}/records returns a built audience as JSON, one page at a time. Each result is one row with the same columns the download files carry. Dates render as YYYY-MM-DD, timestamps as RFC 3339 UTC, and missing values as null.

The audience must be built first. Call GET /api/v1/audiences/{id}/download and poll until its status is ready. Until then, records returns 409 with "error": "not_ready". A status of expired there means the build's output aged out; calling the download endpoint rebuilds it.

Paging Loop

Follow next_cursor until a response has none. page_size (1-5000, default 1000) is a maximum, so a page can hold fewer rows and still have more after it: loop on the cursor, not the row count. Send Accept-Encoding: gzip to get compressed responses.

import time
import requests

url = "https://api.delivr.ai/api/v1/audiences/AUDIENCE_ID/records"
headers = {
    "X-Api-Key": "YOUR_API_KEY",
    "X-Api-Secret": "YOUR_API_SECRET",
    "Accept-Encoding": "gzip",
}
params = {"project_id": "YOUR_PROJECT_ID", "page_size": 5000}

records = []
while True:
    r = requests.get(url, params=params, headers=headers)
    if r.status_code == 503:
        time.sleep(int(r.headers.get("Retry-After", 5)))
        continue
    r.raise_for_status()
    page = r.json()
    records.extend(page["results"])
    if "next_cursor" not in page:
        break
    params["cursor"] = page["next_cursor"]

A response looks like this (count is the build's total rows, omitted when unknown):

{
  "audience_id": "123",
  "count": 4221397,
  "results": [{"first_name": "Ana", "job_title": "VP Marketing", "perc_score": 92}],
  "next_cursor": "..."
}

Errors

StatusMeaning
400Invalid page_size, an unknown query parameter, or an invalid cursor.
402The organization cannot be charged, as with the download endpoint.
404Audience not found.
409 not_readyNot built yet. Call the download endpoint and poll until ready.
409 cursor_staleThe audience was rebuilt after the cursor was issued. Restart without a cursor.
422This audience cannot be served as records. Use the download endpoint.
429 platform_cap_exceededUsage limit reached, as with the download endpoint.
503 busyWait the number of seconds in Retry-After, then retry. Other 503s: retry with backoff.

Billing

Records are billed per record returned, at the audience's meter (Predictive Signals audiences bill at the Predictive Signals rate).

  • A record read again on the same UTC day is not charged again.
  • In one day, paging a build never costs more than downloading it.
  • If the build's file download was already charged, paging that build is free.
  • A page that fails partway is not charged.

Test API keys get deterministic sample data, marked with the response header X-Delivr-Mode: test, and are never billed.


Did this page help you?