Skip to main content
POST
/
api
/
lists
/
{id}
/
export
Export a list as CSV
curl --request POST \
  --url https://app.puffle.ai/api/lists/{id}/export \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "rowIds": [
    "3c90c3cc-0d44-4b50-8888-8dd25736052a"
  ]
}
'
{
  "error": "Unauthorized"
}

Overview

Streams the list as a CSV file (Content-Type: text/csv, Content-Disposition: attachment). The export bundles together everything the UI normally splits across tabs:
  • Built-in person columns (name, role, company, location, domain, LinkedIn, headline, seniority, departments, functions, experience).
  • Company built-ins (industry, employee count, funding stage, location, description) — included only when the list has linked companies.
  • Every custom cell, filtered to non-empty columns only. First name and last name are always kept even if empty.
  • Company signals across five types — new initiative, capital event, leadership change, hiring, partnership — fetched from the caller’s signals table.
  • Hiring enrichment (status + open roles) when any column has enrichment_type = "hiring_status".
  • News enrichments (company + person news columns), formatted as title\nurl\ncontent joined by ---.
Pass rowIds in the body to export only those rows. Empty body or missing rowIds exports the whole list.

AI agent notes

Response is binary-ish. The body is CSV text, not JSON. Do not JSON.parse the response — save it to a file or stream it to the user. The Content-Disposition header contains the list name (with quotes and newlines stripped) as the suggested filename.Sized for humans. Rows and cells are paginated server-side in 1000-row batches; cells fetched in 100-id IN batches. Extremely large lists (100k+ rows) will take tens of seconds. No streaming download — the server composes the full CSV before responding.Empty column filtering. The server drops columns that are empty across every row (except first/last name). If you need a stable schema, do not rely on the header row matching a specific layout — inspect the first line of the CSV after you receive it.Permissions. The list must be owned by the caller. 404 means “not yours or doesn’t exist” — the server does not differentiate.Signals filter. Only dismissed = false + relevant = true signals are included. Dismissed or irrelevant signals never appear in the export.

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Path Parameters

id
string<uuid>
required

List UUID

Pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$

Body

application/json

JSON body. May be empty ({}) or omitted — in that case all rows are exported.

rowIds
string<uuid>[]

Optional allowlist of list_rows.id to include. If omitted or empty, every row in the list is exported.

Pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$

Response

CSV file stream. The OpenAPI spec only describes JSON response bodies — the real response is text/csv. Headers include Content-Type: text/csv and Content-Disposition: attachment; filename="<list>.csv".