> ## Documentation index
> Fetch the complete documentation index at: https://docs.leadmcp.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Start an export

`POST /exports`

Starts one file job for a filter and reserves the quota without charging it. The job counts the filter itself. `POST /contacts/count` is free and tells you the price before you pay it. One export runs per account: a second call while one runs returns 409 export.running with the running id. A job delivers at most 50,000 rows. Near a cap the job is truncated to the contact credits left under the cap that runs out first, and a warning gives the reason and the reset time. On the free plan the cap is the lifetime pool: the reason is `monthly_cap`, `resets_at` is `9999-12-31T23:59:59.000Z`, and the hint says the pool does not reset. When the count passes its budget, the server checks for one matching row. A filter that matches nothing still answers 400 export.no_matches, because that check finds no row, and no job starts. A started job then has rows_available null and a count_unavailable warning.

Starts one file job for a filter and reserves the quota without charging it. The job counts the filter itself. `POST /contacts/count` is free and tells you the price before you pay it. One export runs per account: a second call while one runs returns 409 export.running with the running id. A job delivers at most 50,000 rows. Near a cap the job is truncated to the contact credits left under the cap that runs out first, and a warning gives the reason and the reset time. On the free plan the cap is the lifetime pool: the reason is `monthly_cap`, `resets_at` is `9999-12-31T23:59:59.000Z`, and the hint says the pool does not reset. When the count passes its budget, the server checks for one matching row. A filter that matches nothing still answers 400 export.no_matches, because that check finds no row, and no job starts. A started job then has rows_available null and a count_unavailable warning.

Cost: One contact credit per exported contact, charged on completion.

## Request body

- `filter` | Filter | required. The audience to write to the file.
  - `countries` | array of Country | optional. Contact countries to include. Send ISO-2 codes such as us, or English names such as Germany.
  - `exclude_countries` | array of Country | optional. Contact countries to exclude. Send ISO-2 codes such as us, or English names such as Germany.
  - `has_linkedin` | boolean | optional. True keeps only contacts that carry a LinkedIn URL.
  - `has_work_email` | boolean | optional. True keeps only contacts that carry a work email.
  - `has_phone` | boolean | optional. True matches contacts with a mobile or direct phone. False matches contacts without either.
  - `include_secondary_roles` | boolean | optional. By default, filters match a person's main role. Set include_secondary_roles to true to also match their other current roles; the contact's top-level fields still show the main role. Default `false`.
  - `title_query` | string or array of string | optional. Words in the current title. The match is case-insensitive and uses whole words: 'CTO' matches 'Co-founder & CTO' but not 'Director'. The words also match across punctuation: 'VP Sales' also matches 'VP, Sales' and 'VP-Sales'. Send an array to match any one of several phrases, for example ["VP Sales", "Vice President of Sales"]. A phrase that is blank after trimming answers 400 request.invalid. A leading or trailing wildcard answers 422 filter.rejected. For a substring match, use `where` with the `contains` operator on `title`.
  - `functions` | array of JobFunction | optional. Job functions to include. Values: `operations`, `general_management`, `sales_and_bizdev`, `information_technology`, `education`, `healthcare_and_social_services`, `finance_and_accounting`, `manufacturing_and_production`, `engineering`, `customer_service`, `government_and_public_safety`, `marketing_and_advertising`, `human_resources`, `arts_and_creative`, `construction_and_trades`, `legal`, `supply_chain_and_logistics`, `procurement`, `writing_and_editorial`, `research_and_science`, `other`.
  - `exclude_functions` | array of JobFunction | optional. Job functions to exclude. Values: `operations`, `general_management`, `sales_and_bizdev`, `information_technology`, `education`, `healthcare_and_social_services`, `finance_and_accounting`, `manufacturing_and_production`, `engineering`, `customer_service`, `government_and_public_safety`, `marketing_and_advertising`, `human_resources`, `arts_and_creative`, `construction_and_trades`, `legal`, `supply_chain_and_logistics`, `procurement`, `writing_and_editorial`, `research_and_science`, `other`.
  - `seniority` | array of Seniority | optional. Seniority rungs to include. Values: `c_level`, `vp`, `director`, `manager`, `senior_ic`, `entry`, `founder_or_partner`, `unknown`.
  - `exclude_seniority` | array of Seniority | optional. Seniority rungs to exclude. Values: `c_level`, `vp`, `director`, `manager`, `senior_ic`, `entry`, `founder_or_partner`, `unknown`.
  - `domains` | array of string | optional. Current employer domains. A full URL reduces to a bare domain on input.
  - `exclude_domains` | array of string | optional. Current employer domains to exclude.
  - `company_names` | array of string | optional. Current employer names. Case-insensitive exact match after normalization. Lowercase, trim and collapse whitespace. Strip one trailing legal suffix with an optional comma, then a leading "the ". Legal suffixes: inc, inc., incorporated, llc, l.l.c., ltd, ltd., limited, corp, corp., corporation, co, co., gmbh, ag, sa, s.a., bv, b.v., plc, pty ltd, srl. An empty normalized name returns 400 request.invalid. Values are OR within this key and AND across keys.
  - `exclude_company_names` | array of string | optional. The NOT of company_names after the same normalization. Lowercase, trim and collapse whitespace. Strip one trailing legal suffix with an optional comma, then a leading "the ". Legal suffixes: inc, inc., incorporated, llc, l.l.c., ltd, ltd., limited, corp, corp., corporation, co, co., gmbh, ag, sa, s.a., bv, b.v., plc, pty ltd, srl. An empty normalized name returns 400 request.invalid. Values are OR within this key and AND across keys.
  - `company_size` | array of CompanySize | optional. Company employee bands to include. Values: `1-10`, `11-50`, `51-200`, `201-500`, `501-1K`, `1K-5K`, `5K-10K`, `10K+`.
  - `company_revenue` | array of CompanyRevenue | optional. Company revenue ranges to include. Only companies with a known revenue range match; most small companies have none, so this key leaves them out. Values: `0-1M`, `1M-10M`, `10M-50M`, `50M-100M`, `100M-1B`, `1B+`.
  - `industries` | array of Industry | optional. Company industries to include, as slugs such as software_development. A label such as 'Software Development' or 'IT Services & IT Consulting' is folded to its slug. Read the values from GET /contacts/schema/industries/values.
  - `exclude_industries` | array of Industry | optional. Company industries to exclude, as slugs such as software_development. A label such as 'Software Development' or 'IT Services & IT Consulting' is folded to its slug. Read the values from GET /contacts/schema/industries/values.
  - `schools` | array of string | optional. School names. It matches any school on the record. The match is exact on the stored value, so send the name as the record holds it.
  - `skills` | array of string | optional. Skill names. It matches any skill on the record. The match is exact on the stored value, which is lowercase, and the input is lowercased. Read the values from GET /contacts/schema/skills/values.
  - `employee_count_min` | integer | optional. The smallest company employee count, inclusive.
  - `employee_count_max` | integer | optional. The largest company employee count, inclusive.
  - `founded_year_min` | integer | optional. The earliest company founding year, inclusive.
  - `founded_year_max` | integer | optional. The latest company founding year, inclusive.
  - `company_hq_countries` | array of Country | optional. Company headquarters countries to include. Send ISO-2 codes such as us, or English names such as Germany.
  - `last_round_after` | YearMonth | optional. The latest financing event is after this month, exclusive.
  - `last_round_before` | YearMonth | optional. The latest financing event is before this month, exclusive.
  - `last_round_types` | array of FundingRoundType | optional. Types of the latest financing event to include. Values: `pre_seed`, `seed`, `series_a`, `series_b`, `series_c_plus`, `private_equity`, `debt`, `other`.
  - `total_funding_min` | integer | optional. The smallest total funding in US dollars, inclusive. Missing funding is null and never matches.
  - `total_funding_max` | integer | optional. The largest total funding in US dollars, inclusive.
  - `company_ids` | array of CompanyId | optional. Company ids (`com_`) of the current employer to include. Take them from `POST /companies/search` or `POST /companies/lookup`. Values are OR within this key and AND across keys. Takes up to 1,000 ids.
  - `where` | WhereNode | optional. The condition tree. It is opened per account when the named keys cannot express the audience. The `signals` column is filtered here, with `in` or `not_in`.
    - `WhereGroup` | WhereGroup | optional. A boolean group of child nodes.
      - `and` | array of WhereNode | optional. Every child must match.
      - `or` | array of WhereNode | optional. At least one child must match.
      - `not` | WhereNode | optional. The child must not match.
    - `WhereLeaf` | WhereLeaf | optional. One bound condition on one column.
      - `field` | string | required. A contact column name, as `GET /contacts/schema` prints it, or signals. The name match is case-insensitive.
      - `op` | enum | required. The comparison to apply. The operator list is frozen. Values: `eq`, `neq`, `in`, `not_in`, `gt`, `gte`, `lt`, `lte`, `contains`, `exists`.
      - `value` | any | optional. The bound value: a string, a number, a boolean, or a list of at most 50 values for `in` and `not_in`. Text columns take eq, neq, in, not_in, contains, exists, gt, gte, lt and lte with text values. role_since takes eq, neq, gt, gte, lt, lte, in, not_in and exists with YYYY-MM-DD dates. The number columns (company_employee_count, company_founded_year, company_total_funding_usd) take eq, neq, gt, gte, lt, lte, in, not_in and exists, where exists means the value is known. has_work_email and has_phone take eq and neq with true or false. The list columns (company_industries, signals, skills, languages) take in, not_in, contains, exists, eq (the list holds the value) and neq. experience, education, certifications and social take contains and exists only. exists takes no value or true; false means the column is empty. A leaf other than exists needs a value. A refused operator, value type or shape answers 422 filter.rejected and names what the column takes.
- `columns` | array of string | optional. The columns to write, in this order. Send `["*"]` for every column.
- `max_rows_per_company` | integer | optional. The most contacts to return from one company. On search the cap holds inside one page, so next_cursor is null when it is set; use start_export for the full capped list. On export the file can hold fewer rows than rows_to_export, and only exported rows are charged.
- `max_rows` | integer | optional. The ceiling for this job. One job writes at most 50,000 rows, so a bigger audience needs several jobs. Default `50000`.
- `format` | enum | optional. The file format. Both are gzipped. The list is frozen. Default `csv`. Values: `csv`, `jsonl`.
- `exclude_ids` | array of PersonId | optional. Person ids to leave out of count, search and export. Unknown ids have no effect. Takes up to 1,000 ids.

## Failures

| Status | Meaning |
| --- | --- |
| `400` | The request shape, a filter key, a value, a cursor or the enrichment mode was rejected. |
| `401` | The credential is missing, unknown or revoked. |
| `402` | The daily or the monthly contact credit cap is spent, or the free plan's lifetime pool is. |
| `409` | One export already runs on this account. |
| `422` | The filter was rejected before it ran: more than 32 predicates, deeper than 4, more than 25 leaves, more than 1,000 domains or company names, more than 50 values in another list, a leading wildcard in a where leaf, a leading or trailing wildcard in title_query, an operator, value type or shape the column does not take, a leaf other than exists with no value, or an empty `and` or `or` group. |
| `429` | The key passed 300 requests a minute or 2 concurrent requests. |
| `503` | The data is unavailable for a short time. |

## Example

```bash
curl -sS -X POST "https://api.leadmcp.ai/v1/exports" \
  -H "Authorization: Bearer lm_live_YOUR_API_KEY" \
  -H "LeadMCP-Version: 2026-09-19" \
  -H "Content-Type: application/json" \
  -d '{"filter":{"domains":["example.com"],"seniority":["vp","director"]},"columns":["*"],"format":"csv","max_rows":50000}'
```

Response `202`:

```json
{
  "ok": true,
  "request_id": "req_01JBQ2W8K9V6M3T0X5Y7Z4A1BC",
  "release": "b_2026_09_15",
  "data": {
    "id": "exp_01JBQ2W8K9V6M3T0X5Y7Z4A1BC",
    "status": "queued",
    "rows_available": 4210,
    "rows_to_export": 4210,
    "truncated": false,
    "truncation_reason": null,
    "resets_at": null,
    "format": "csv"
  },
  "quota": {
    "plan": "free",
    "contact_credits_used": 50,
    "month_remaining": 950,
    "today_remaining": 950,
    "binding": "month",
    "resets_at": "9999-12-31T23:59:59.000Z"
  },
  "warnings": []
}
```
