> For the complete documentation index, see [llms.txt](https://developer.parvenu.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.parvenu.io/manage-lists/add-contacts-in-bulk.md).

# Add Contacts in Bulk

Add up to 5,000 contacts you already have to a list in one call.

<mark style="color:green;">`POST`</mark> `/add_contacts_bulk`

Adds many contacts to `listname` in one call, from data you already hold. Same fields, same duplicate handling and the same history line as [Add a Contact](/manage-lists/add-a-contact.md).

{% hint style="info" %}
**Free.** `credits_used` is always `0`.
{% endhint %}

{% hint style="info" %}
**Synchronous, not a background job.** Unlike the bulk enrichment endpoints, this returns the result immediately. There is no `job_id`, and you do not need to call Check List Status or Download List Data afterwards.
{% endhint %}

{% hint style="success" %}
**One bad contact does not sink the call.** Contacts that cannot be added are listed in `rows_rejected` with their position and the reason. Everything else still goes in. Only when every contact is rejected does the call return an error, and its message lists each reason.
{% endhint %}

## Headers

| Name         | Value              |
| ------------ | ------------------ |
| Content-Type | `application/json` |

## Body

| Name          | Type             | Description                                                                                                  |
| ------------- | ---------------- | ------------------------------------------------------------------------------------------------------------ |
| `api_key`     | string           | **Required.** Your API key.                                                                                  |
| `listname`    | string           | **Required.** The list to add to.                                                                            |
| `contacts`    | array of objects | **Required.** The contacts. Each takes the fields listed on [Add a Contact](/manage-lists/add-a-contact.md). |
| `create_list` | boolean          | Default `true`. Creates the list when it does not exist. Set `false` to get `not_found` instead.             |
| `dry_run`     | boolean          | Default `false`. When `true`, counts what would be added and writes nothing. No list is created.             |

Each contact needs at least one identifier: `email`, `person_linkedin_url`, `person_name`, `organization_name`, `domain`, `company_website`, `company_linkedin_url` or `place_id`.

## Limits

Up to **5,000 contacts** in one call. Past that, the call is refused rather than quietly truncated — add them in batches.

## Duplicates

A contact the list already has is combined with it, not added twice: blank fields are filled in and existing values are kept. See [Add a Contact](/manage-lists/add-a-contact.md) for what counts as the same contact.

The same contact sent twice in one call is combined too, so a file with repeated rows does not create repeated contacts.

## Response

| Field                | Description                                                                                          |
| -------------------- | ---------------------------------------------------------------------------------------------------- |
| `status`             | `success`, or `not_found` when the list does not exist and `create_list` is `false`.                 |
| `data.list_name`     | The list.                                                                                            |
| `data.list_created`  | `true` when the list did not exist and was made.                                                     |
| `data.rows_received` | How many contacts were sent.                                                                         |
| `data.rows_added`    | How many were added as new contacts.                                                                 |
| `data.rows_merged`   | How many were combined with a contact already in the list, or with another contact in the same call. |
| `data.rows_rejected` | Contacts that could not be added, each as `{index, reason}`. `index` counts from `0`.                |
| `data.dry_run`       | Whether this was a dry run.                                                                          |
| `credits_used`       | Always `0`.                                                                                          |

## Example

{% tabs %}
{% tab title="Input" %}

```json
{
  "api_key": "your_api_key",
  "listname": "Q4 Roofers",
  "contacts": [
    {
      "person_name": "Jane Doe",
      "email": "jane@acmeroofing.com",
      "organization_name": "Acme Roofing"
    },
    {
      "person_name": "Sam Rivera",
      "person_linkedin_url": "https://www.linkedin.com/in/samrivera",
      "organization_name": "Summit Roofing"
    },
    {
      "organization_name": "Summit Roofing",
      "domain": "summitroofing.com",
      "company_size": "11-50"
    },
    {
      "person_name": "Alex Kim",
      "email_address": "alex@example.com"
    },
    {
      "city": "Fresno"
    },
    {
      "email": "jane@acmeroofing.com",
      "phone_number": "+1 916 555 0100"
    }
  ]
}
```

{% endtab %}

{% tab title="Output" %}

```json
{
  "status": "success",
  "credits_used": 0.0,
  "credits_remaining": 6041.2,
  "message": "Added to 'Q4 Roofers': 3 new, 1 combined with contacts already there, 2 rejected.",
  "data": {
    "list_name": "Q4 Roofers",
    "list_created": false,
    "rows_received": 6,
    "rows_added": 3,
    "rows_merged": 1,
    "rows_rejected": [
      {
        "index": 3,
        "reason": "'email_address' is not a Parvenu field. Use one of: ..."
      },
      {
        "index": 4,
        "reason": "No identifier. Send at least one of email, person_linkedin_url, person_name, organization_name, domain, company_website, company_linkedin_url or place_id."
      }
    ],
    "dry_run": false
  }
}
```

{% endtab %}
{% endtabs %}

Three contacts were added. The last one shares Jane's email, so it was combined with her and her phone number filled in. Contact `3` used a field name Parvenu does not have, and contact `4` had nothing to identify it by — both are listed with the reason and the rest went in.
