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

# Import contacts

> Upload a CSV file of contacts, record how you obtained consent, and put the new contacts on a list.

Use an import to add many contacts at once, or to update names and custom fields for contacts you already have. The import dialog is on **Contacts → All Contacts** (the **Import Contacts** button in the toolbar). You can also open it from the dashboard and the getting-started guide.

## Before you start

Prepare a `.csv` file with a header row and one column holding the email address. Other columns are optional. In the dialog you choose what each column is, so the headers can be named however you like.

| Maps To                       | Used for                                                                                                             |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| **Email (required)**          | The contact's address. Rows with a missing or invalid address are skipped.                                           |
| **First Name**, **Last Name** | The contact's name                                                                                                   |
| **Status**                    | The contact's status. See [Status column](#status-column).                                                           |
| **Source**                    | Where a new contact came from. Without it, new contacts get the source `csv_import`.                                 |
| A custom field                | The value of that [custom field](/guides/audience-and-campaigns/custom-fields). See [Custom fields](#custom-fields). |
| **Skip**                      | Nothing. The column is ignored.                                                                                      |

The dialog suggests a mapping from each header: `email`, `Email Address` and `E-mail` map to Email, `first_name` and `First Name` to First Name, `last_name` and `Last Name` to Last Name, `status` to Status, `source` to Source, and a header matching a custom field's key or name maps to that field. Everything else starts as **Skip**.

## Import a file

<Steps>
  <Step title="Upload">
    Click **Import Contacts**. Drop your file on **Drop your CSV file here, or click to browse**, or click to choose it. Only `.csv` files are accepted. The dialog shows an approximate row count. Click **Next**.
  </Step>

  <Step title="Review the columns">
    Check the **Column Header**, **Maps To** and **Sample Value** table and change any suggestion that's wrong. Make sure a column is mapped to **Email (required)**; the import won't start otherwise.

    To put the contacts on a list, choose it under **Add imported contacts to a list**. Leave **Don't add to a list** to import without one.
  </Step>

  <Step title="Record consent">
    Under **Consent**, answer **Why are you allowed to email these contacts?**:

    * **They opted in — signed up, ticked a box, or asked to hear from us**
    * **Existing customers, similar products, opt-out offered every time**
    * **Legitimate interest — business contacts in a relevant role**
    * **Necessary to perform a contract with them**

    Under **How did you collect this list?**, describe the source in at least 20 characters, for example which signup form and over what dates. Then tick the confirmation that the list was not purchased, rented, scraped or appended.
  </Step>

  <Step title="Import">
    Click **Import**. The results show how many contacts were **imported or updated** and how many were **skipped (invalid email or duplicate)**.
  </Step>
</Steps>

The consent answer is saved as a consent record on every imported contact. It is the evidence you would need if a recipient complains, so be specific.

## What happens to existing contacts

Contacts are matched by email address (case-insensitive).

* **New address**: a contact is created with the mapped name, source, status and custom fields.
* **Existing address**: the contact is kept. Mapped names and custom fields are updated; an empty cell leaves the current value alone. The source is not changed.
* **Duplicate rows** in the same file: the last row wins.

## Status column

A column mapped to **Status** is read as follows (case doesn't matter):

| Cell                        | Status                               |
| --------------------------- | ------------------------------------ |
| `active`, `subscribed`      | Active                               |
| `pending`, `unconfirmed`    | Pending (not mailed until confirmed) |
| `unsubscribed`, `opted out` | Unsubscribed                         |
| `bounced`, `cleaned`        | Bounced                              |
| `complained`, `spam`        | Complained                           |

Any other value, or an empty cell, leaves the status alone. New contacts without a status are Active.

For contacts you already have, an import only ever stops mail: it can mark an Active or Pending contact as unsubscribed, bounced or complained, but it never makes an unsubscribed, bounced or complained contact Active again. A contact marked unsubscribed is unsubscribed from every list. Status changes appear in the contact's status history with the source "import".

## Custom fields

Create the field under **Settings → Custom Fields** before importing; the dialog lists your custom fields under **Custom Fields** in each **Maps To** menu. Each cell is checked against the field's type. A cell that doesn't fit is skipped, and the rest of the row is still imported:

* **Number**: must be a number.
* **Boolean**: `true`, `yes`, `y`, `1` or `false`, `no`, `n`, `0`.
* **Date**: must be a recognisable date, such as `2026-09-24`.
* **Select**: must be one of the field's options (case doesn't matter).
* **JSON**: must be valid JSON.

## Put imported contacts on a list

Choose a list under **Add imported contacts to a list** in the column step. Every contact in the file is added to it, including contacts you already had:

* Contacts already on the list keep their subscription on it. An import never re-subscribes someone who unsubscribed from the list.
* Contacts imported with the status pending join the list as pending.
* Contacts imported as unsubscribed are unsubscribed from every list, this one included.

To add contacts to a list after importing, filter or search the contacts table, select the rows, and use **Bulk update → Add to list**. See [Lists](/guides/audience-and-campaigns/lists).

<Tip>
  Adding contacts to a list can start automations that use a **Contact Added to List** trigger; only Active contacts enter them. Check your active [automations](/guides/audience-and-campaigns/automation-triggers) before importing a large file into a list.
</Tip>

## Limits

| Limit                         | Value                                                                                   |
| ----------------------------- | --------------------------------------------------------------------------------------- |
| File size                     | 10 MB                                                                                   |
| Rows per file                 | 50,000 (no limit on Enterprise). Extra rows are dropped and the result shows a warning. |
| Import attempts per workspace | 2 per hour. Refused attempts count too.                                                 |
| Contacts                      | Your plan's contact allowance. The import is refused once you have reached it.          |

To import programmatically, use the public API. See the [API reference](/api-reference/introduction).

## Troubleshooting

<AccordionGroup>
  <Accordion title="&#x22;CSV must have a column mapped to Email&#x22;">
    No column is mapped to **Email (required)**. Go back to the column table and pick Email for the address column.
  </Accordion>

  <Accordion title="A column didn't import">
    Check that the column is mapped to something other than **Skip**. For a custom field, check that the cells fit the field's type; cells that don't fit are skipped.
  </Accordion>

  <Accordion title="&#x22;Too many imports. Please wait before importing again.&#x22;">
    Your workspace has made two import attempts in the last hour, including any that were refused. Wait and try again, or combine your files into one.
  </Accordion>

  <Accordion title="The Import button stays disabled">
    Describe how you collected the list in at least 20 characters and tick the consent confirmation.
  </Accordion>
</AccordionGroup>
