> Reverse Contact API documentation. This is the Markdown copy of https://docs.reversecontact.com/endpoints/list-export
> Every page is listed at https://docs.reversecontact.com/llms.txt, every endpoint with its credit cost and status at https://docs.reversecontact.com/catalog.json

# Export a List

> Export List members and Pending Intake as CSV for free, including stored profile, company, email and phone data without new lookups.

- Endpoint: `GET https://api.reversecontact.com/v2/lists/:listId/export`
- Credits: Free.
- Answer: synchronous.
- Available in: REST API, MCP tool `export_list`, TypeScript and Python SDKs, CLI command `rc lists export`.
- Last verified: 2026-11-04

## Introduction

The Export a List endpoint downloads a List as a CSV file: the List Members, with the data the List already holds for each of them (profile fields, company, and the email and phone found by an [import](https://docs.reversecontact.com/endpoints/list-intake-signals) with the `contact_email` or `contact_phone` family), and the [Pending Intake](https://docs.reversecontact.com/guides/lists#pending-intake) lines, with what was sent for them.

Exporting is **free** (0 credits): the file holds what the List stored, and nothing is looked up again. It counts toward your per-minute rate limit like any other call.

The API key needs the `lists` permission (see [API key management](https://docs.reversecontact.com/guides/api-key-management)).

## Authorization

| Name     | Type   | Required | Description                                                                                         |
| -------- | ------ | -------- | --------------------------------------------------------------------------------------------------- |
| `apikey` | string | Yes      | Your API key from the developer dashboard. Pass it via `Authorization: Bearer YOUR_API_KEY` header. |

## Request

The route is `GET /v2/lists/:listId/export`.

### Path parameters

| Name     | Type   | Required | Description    |
| -------- | ------ | -------- | -------------- |
| `listId` | string | Yes      | List id (UUID) |

## Response structure

A successful response is the CSV file itself (`Content-Type: text/csv; charset=utf-8`), not the JSON envelope: `Content-Disposition` names it `list-<name>-<entity>.csv`, where `<name>` is the List name in lowercase, without accents, with a dash in place of spaces and signs (`list-q4-sales-leaders-persons.csv`). The file has one header row, then one row per line of the List, members and Pending Intake mixed, in the order they were added. A value your team typed over a cell in the app replaces the enriched one, and an email or phone number typed in the app reads `found` with the source `manual`. A value that starts with `=`, `+`, `-`, `@`, a tab or a carriage return is prefixed with `'`, so a spreadsheet never reads it as a formula. Columns you added to the List in the app follow the default columns, headed by their name.

A Pending Intake row holds what was sent for it: `linkedin_url` is the URL of the Signal, `name` its first and last name (or else its company name, email or domain), `currentCompanyName` its company name. Its contact columns read `not_attempted`, unless your team typed a contact over the line in the app.

A people List has these columns:

| Column                         | Content                                                                 |
| ------------------------------ | ----------------------------------------------------------------------- |
| `linkedin_url`                 | Profile URL of the member                                               |
| `name`                         | Full name                                                               |
| `headline`                     | Profile headline                                                        |
| `location`                     | Location, as text                                                       |
| `currentCompanyName`           | Current company                                                         |
| `currentCompanyLinkedInUrl`    | Company page URL of the current company                                 |
| `contact_email_status`         | `found`, `not_found`, `error` or `not_attempted`                        |
| `contact_email`                | Email found, empty otherwise                                            |
| `contact_email_source`         | Where the email came from, when known                                   |
| `contact_email_attempted_at`   | When the email was looked for (ISO 8601)                                |
| `contact_email_freshness_at`   | Date of the email data (ISO 8601)                                       |
| `contact_phone_status`         | `found`, `not_found`, `error` or `not_attempted`                        |
| `contact_phone`                | Phone number found, empty otherwise                                     |
| `contact_phone_type`           | Kind of number when the provider gives one, such as `mobile`            |
| `contact_phone_source`         | Where the number came from, when known                                  |
| `contact_phone_attempted_at`   | When the number was looked for (ISO 8601)                               |
| `contact_phone_freshness_at`   | Date of the phone data (ISO 8601)                                       |
| `currentCompanyWebsite`        | Website of the current company                                          |

A companies List has these columns: `linkedin_url`, `name`, `industry`, `location`, `website`, `employeeCount`, `foundedOn`, `phone` and `description`.

An error returns the usual JSON envelope, with `quotas` and `metadata` (see [Usage](https://docs.reversecontact.com/endpoints/usage#response-structure)): `404 LIST_NOT_FOUND` when no List has this id in your workspace, or `404 LISTS_NOT_ACTIVATED` when the workspace has never had a List.

The `200` status is sent with the first bytes of the file. An error during the download, or the 30-minute limit, ends the file early with that same `200`: check that it holds one row per line of the List, the `memberCount` plus the `pendingIntakeCount` of [Get a List](https://docs.reversecontact.com/endpoints/list), and export it again when rows are missing.

A workspace exports one List at a time. While a file is downloading, a second export returns `429 LIST_EXPORT_IN_PROGRESS`, whichever API key asks: wait for the first to finish, then retry. `429 LIST_EXPORT_BUSY` means the server is serving another export, and a retry usually gets through within seconds. Neither costs a credit. `error.details.retryAfter` and the `Retry-After` header give the seconds to wait. A download that stops reading is closed after 75 seconds, and one export runs for 30 minutes at most.

## Code examples

**Code Examples**

```bash [cURL]
curl https://api.reversecontact.com/v2/lists/3f6c2a8e-1b4d-4f0a-9c7e-5d2b8a1e6f40/export \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -o q4-sales-leaders.csv
```
```javascript [JavaScript]
import { writeFile } from "node:fs/promises";

const listId = "3f6c2a8e-1b4d-4f0a-9c7e-5d2b8a1e6f40";
const response = await fetch(
  `https://api.reversecontact.com/v2/lists/${listId}/export`,
  { headers: { "Authorization": "Bearer YOUR_API_KEY" } }
);

if (!response.ok) throw new Error((await response.json()).error.message);
await writeFile("q4-sales-leaders.csv", await response.text());
```
```python [Python]
import requests

list_id = "3f6c2a8e-1b4d-4f0a-9c7e-5d2b8a1e6f40"
response = requests.get(
    f"https://api.reversecontact.com/v2/lists/{list_id}/export",
    headers={"Authorization": "Bearer YOUR_API_KEY"}
)
response.raise_for_status()

with open("q4-sales-leaders.csv", "wb") as file:
    file.write(response.content)
```

## Example response

The second row of this file is a Pending Intake line: an email no one matched.

**Example Response**

```text [200 - CSV file]
linkedin_url,name,headline,location,currentCompanyName,currentCompanyLinkedInUrl,contact_email_status,contact_email,contact_email_source,contact_email_attempted_at,contact_email_freshness_at,contact_phone_status,contact_phone,contact_phone_type,contact_phone_source,contact_phone_attempted_at,contact_phone_freshness_at,currentCompanyWebsite
https://www.social.com/in/janedoe,Jane Doe,VP Sales at Acme Corp,"Paris, France",Acme Corp,https://www.social.com/company/acme-corp,found,jane.doe@acme.com,,2026-10-28T09:16:02.000Z,2026-10-28T09:16:02.000Z,not_attempted,,,,,,https://acme.com
,unknown.person@example.com,,,,,not_attempted,,,,,not_attempted,,,,,,
```
```json [429 - Export already running]
{
  "success": false,
  "data": null,
  "error": {
    "code": "LIST_EXPORT_IN_PROGRESS",
    "message": "This workspace is already exporting a List. Wait for it to finish, then retry.",
    "details": { "retryAfter": 30 }
  },
  "quotas": {
    "creditsConsumed": 0,
    "workspace": {
      "id": "ws_abc123",
      "credits": { "total": 10000, "used": 4521, "left": 5479 }
    }
  },
  "metadata": {
    "requestId": "d86ecf64-fcc2-489b-9747-1ad0fa9630b2",
    "executionTimeMs": 4
  }
}
```
```json [404 - List not found]
{
  "success": false,
  "data": null,
  "error": {
    "code": "LIST_NOT_FOUND",
    "message": "List not found"
  },
  "quotas": {
    "creditsConsumed": 0,
    "workspace": {
      "id": "ws_abc123",
      "credits": { "total": 10000, "used": 4521, "left": 5479 }
    }
  },
  "metadata": {
    "requestId": "bd792a47-a27b-40b1-b587-5ed509ce36bd",
    "executionTimeMs": 18
  }
}
```
