# Import and export contacts

> Import contacts from a CSV or Excel file with the import wizard, export filtered contacts to CSV or XLSX, and run bulk actions and exports with the API.

Use the import wizard to bring contacts in from a spreadsheet, and export to download the contacts that match your current filters. This page also covers the API's bulk actions and export endpoint for doing the same from code.

## Before you begin

- Create any [custom fields](/docs/contacts/custom-fields/) you want to fill from the file. The wizard can only map columns to fields that already exist.
- Create the [audiences](/docs/audiences/) you want the contacts to join. Imports count toward the subscriber limit of each audience.
- Only import people who agreed to hear from you. Production access reviews ask how you collect subscribers. See [Production access](/docs/workspaces/production-access/).

## Prepare your file

The wizard reads `.csv`, `.xlsx` and `.xls` files with up to **2,500 contacts per file**. Split larger lists into several files.

```csv title="contacts.csv"
email,first_name,last_name,company,birthday
ada@example.com,Ada,Lovelace,Acme,1990-04-12
grace@example.com,Grace,Hopper,Acme,1906-12-09
alan@example.com,Alan,Turing,,
```

Tips for a clean import:

- **Put one contact on each row** and the column names in the first row. Excel files are read from the first sheet only.
- **Name columns after your fields** so the wizard maps them for you. A column header maps automatically when it matches a field's name or key, ignoring case, for example `email`, `First name`, `first_name` or a custom field key such as `company`.
- **Save CSV files as UTF-8** so names with accents come through correctly.
- **Write dates as `YYYY-MM-DD`.** Date cells in Excel files work too. Other date formats are rejected.
- **Check the addresses.** One invalid email address stops the whole import with an error that names the row, for example "Contact #12 has an invalid email address." Rows with an empty email cell are skipped.
- **Multi select values** import as a single text value. To store several options as a list, set them with the API.

## Import contacts

1. **Open the wizard.** Go to **Email Marketing → Contacts** and select **Import**.

2. **Choose the file.** Under **CSV File**, select your file. Leave **File has header** checked if the first row holds column names. The wizard shows the first rows and the total row count, with a warning if the file has more than 2,500 rows. Select **Continue**.

3. **Map the columns.** For each column, pick the contact field it fills: **Email**, **First name**, **Last name**, one of your custom fields, or **Exclude** to skip it. You must map one column to **Email**. Each row shows sample values so you can check the mapping.

4. **Pick audiences.** Under **Audiences**, choose the audiences the contacts should join, or leave it empty to import contacts without adding them to a list. Select **Continue**.

5. **Review and import.** The preview shows the file, the contact count, the audiences, the column mapping and the first 10 contacts as they'll be saved. Select **Import**.

Emailit validates the whole file first. If anything is wrong, such as an invalid address, an unknown custom field or an audience that's full, nothing is imported and the errors are listed so you can fix the file. Otherwise the import runs in the background in batches of 500. Refresh the Contacts list after a moment to see the new contacts.

### What happens to existing contacts

Contacts are matched by email address, ignoring case.

| Case | Result |
| --- | --- |
| The address is new | A contact is created. |
| The address already exists | The contact is updated. Names are overwritten only when the file has a value. Custom field values from the file replace the stored ones, and a blank cell in a mapped custom field column clears that field. Other custom fields are kept. |
| The address appears twice in the file | Both rows are applied in order, so the later row wins. |
| The contact isn't in the selected audience yet | It joins the audience as subscribed. |
| The contact was unsubscribed from the selected audience | It's subscribed to that audience again. |

> **Imports resubscribe people:** Importing a contact into an audience it unsubscribed from subscribes it again. Before you import into an existing audience, remove people who opted out from your file, or import without picking that audience.

A few more things to know:

- The mapping list includes **Unsubscribed**, but the import doesn't apply it. To mark imported people as unsubscribed, select them afterwards on the Contacts list and use the **Unsubscribe** bulk action.
- Imports don't send `contact.*` or `subscriber.*` webhook events, and they don't start automations such as **Added to audience**.
- If an audience would go over its subscriber limit, the import is rejected with the limit in the message, for example "Pay as you go includes 10,000 subscribers per audience." See [Audiences](/docs/audiences/#limits).

## Export contacts

1. **Narrow the list.** On **Email Marketing → Contacts**, use search and **Filter** to show the contacts you want. With no search or filters, the export includes every contact.

2. **Export.** Select **Export** and choose **CSV** or **XLSX**. Your browser downloads `contacts.csv` or `contacts.xlsx`.

An export can include up to **10,000 contacts**. If more contacts match, the export fails, so add filters, such as an audience or a creation date range, and export in parts.

The file has one row per contact and these columns:

| Column | Value |
| --- | --- |
| `email` | The contact's email address. |
| `first_name`, `last_name` | The contact's names. |
| `unsubscribed` | `true` if the marketing status is **Unsubscribed**, otherwise `false`. |
| `audiences` | Names of every audience the contact belongs to, separated by `; `. |
| One column per custom field key | The stored value. Multi select values are joined with `;`. |
| `created_at`, `updated_at` | ISO 8601 timestamps. |

## Use the API

The API has no file import. To add many contacts from code, call [Create a contact](/docs/api-reference/contacts/create/) for each one, or [Add a subscriber](/docs/api-reference/audiences/subscribers/add/) to create the contact and its audience membership in one call.

### Bulk actions

[`POST /v2/contacts/bulk`](/docs/api-reference/contacts/bulk/) runs one action on up to 100 contacts, given by `con_` ID:

| `action` | Effect | Needs `audience_id` |
| --- | --- | --- |
| `add_to_audience` | Adds the contacts to the audience. Contacts with `unsubscribed: true` join as unsubscribed. | Yes |
| `remove_from_audience` | Deletes their membership in the audience. | Yes |
| `unsubscribe` | Sets `unsubscribed: true` (marketing status **Unsubscribed**). | No |
| `resubscribe` | Sets `unsubscribed: false`. | No |
| `delete` | Deletes the contacts and their memberships. | No |

```bash
curl https://api.emailit.com/v2/contacts/bulk \
  -X POST \
  -H "Authorization: Bearer $EMAILIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "add_to_audience",
    "ids": ["con_2kq8Vt4xLm7Rz", "con_9fW3pQ1nBc6Yt"],
    "audience_id": "aud_5hJ2kL8mNp4Qr"
  }'
```

```json
{
  "object": "contact_bulk",
  "action": "add_to_audience",
  "processed": 2,
  "ids": ["con_2kq8Vt4xLm7Rz", "con_9fW3pQ1nBc6Yt"]
}
```

The request fails as a whole if `ids` has more than 100 entries (`400`) or if any contact or the audience doesn't exist (`404`, with the unknown IDs in `missing`). To process more contacts, page through [List contacts](/docs/api-reference/contacts/list/) and send batches of 100.

### Export

[`GET /v2/contacts/export`](/docs/api-reference/contacts/export/) returns the same file as the dashboard. Set `format` to `csv` (the default) or `xlsx`, and add any [List contacts](/docs/api-reference/contacts/list/) filters, search and sort:

```bash
curl "https://api.emailit.com/v2/contacts/export?format=csv&audience_id=aud_5hJ2kL8mNp4Qr&unsubscribed=false" \
  -H "Authorization: Bearer $EMAILIT_API_KEY" \
  -o contacts.csv
```

If more than 10,000 contacts match, the endpoint returns `422` with "Export is limited to 10000 contacts. Narrow your filters and try again."

## Related

  - [Custom fields](/docs/contacts/custom-fields/): Define the fields your columns map to.
  - [Subscribers](/docs/audiences/subscribers/): Manage who is on each audience.

---
Source: https://emailit.com/docs/contacts/import-export/
