Less boo. More booked. Halloween offer: 30 days free on any paid plan. Claim 30 days freeEvery new account gets one free mailbox for warmup and replies. No domain to buy. See how it works

Skip to content

Export to CSV

API referenceLeads

From the Leads API reference. Requests use the base URL https://app.warmerly.com/api/v1 and an API key, see Authentication.

text
POST /leads/export

Exports matching companies as a CSV file (download, not JSON). Debits your monthly lead export quota by the number of rows actually delivered, not the number you asked for. The debit happens as each batch of rows is written, so a download you cancel part way is charged for the rows already sent.

Select rows with one of two shapes in the request body:

FieldTypeRequiredDescription
domainsstring[] (1-10,000, each up to 253 characters)One of domains/selectAllMatchingExplicit list of domains to export.
filtersobjectNoSame filter shape as search (q, country, city, category, provider, tech, channel, hasPhone, and the firmographic filters). Booleans are JSON booleans here, not the strings the query string uses, and tech is an array of up to 20 strings. Used with selectAllMatching; with an explicit domains list only channel is read from it. The channel default applies here too: an export never contains a company you cannot contact by email unless you named another channel.
selectAllMatchingtrueOne of domains/selectAllMatchingExport every row matching filters, re-resolved server-side.

The CSV export streams and has no per-request row cap: it stops when the rows run out or your spendable export allowance does (the monthly remainder plus any credit-bought block), so "select all matching" with a small allowance returns a shorter file rather than an error. The domains list is limited to 10,000 entries per request. Push to campaign is capped at 10,000 rows per request.

bash
curl -X POST https://app.warmerly.com/api/v1/leads/export \
  -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{ "filters": { "country": "GB", "tech": ["shopify"] }, "selectAllMatching": true }' \
  -o leads.csv

Returns 200 with content-type: text/csv, and the file starts with a UTF-8 byte-order mark. Because the file is streamed there is no row-count header. Count the rows you receive: the count can be lower than what you selected, because suppression and the contact-channel requirement are re-applied at export time. When the budget for the request is finite, the response carries an X-Lead-Budget header (CORS-exposed) with the most rows the file can hold. CSV columns, in order:

text
domain, company_name, legal_name, website_url, country, city, category, tech_stack,
email, all_emails, phone, street_address, region, postal_code, linkedin_url,
twitter_url, other_social, mail_provider, description, last_checked,
company_number, company_number_jurisdiction, vat_number, employee_count,
employee_band, hiring, careers_url, contact_form_url, founded_year,
opening_hours, currencies

New columns may be appended in future; existing columns won't be reordered or removed.

Errors: 400 bad_request with the message invalid_export_request for a malformed body, including a body that sets neither domains nor selectAllMatching. 402 quota_exhausted if your export allowance is already used up when the request starts:

json
{
  "error": {
    "code": "quota_exhausted",
    "message": "You've used 500 of 500 lead exports this month. Upgrade your plan to continue.",
    "details": {
      "label": "lead exports",
      "used": 500,
      "limit": 500,
      "topUpUrl": null,
      "upgradeUrl": "/settings/billing"
    }
  }
}

The message varies: when credits can cover the shortfall it offers them, and details.topUp and details.topUpUrl are set.

Was this page helpful?