> 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/remove-contacts-in-bulk.md).

# Remove Contacts in Bulk

Permanently remove many contacts from a list in one call.

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

Permanently removes many contacts from a list in one call. Same matching as Remove a Contact, but every identifier field takes an array.

{% hint style="danger" %}
**This cannot be undone.** Send `dry_run: true` first on anything but a handful of contacts. It reports how many would be removed and removes nothing.
{% endhint %}

{% 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 %}

## Headers

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

## Body

| Name                   | Type             | Description                                                                      |
| ---------------------- | ---------------- | -------------------------------------------------------------------------------- |
| `api_key`              | string           | **Required.** Your API key.                                                      |
| `listname`             | string           | **Required.** The list to remove the contacts from. One word, not `list_name`.   |
| `emails`               | array of strings | Email addresses to remove.                                                       |
| `person_linkedin_urls` | array of strings | LinkedIn profile URLs to remove.                                                 |
| `phone_numbers`        | array of strings | Phone numbers to remove, in any format.                                          |
| `person_names`         | array of strings | Full names to remove.                                                            |
| `dry_run`              | boolean          | Default `false`. When `true`, reports what would be removed and removes nothing. |

Pass **at least one** non-empty array. Passing none returns `422`.

**Up to 5,000 values in one call**, counted across all four arrays together. More than that returns `422` with the limit in the message.

Matching is identical to the single endpoint, including the forgiveness around case, URL formatting and phone formatting. See Remove a Contact for the details.

## Response

The same shape as the single endpoint. `rows_matched` and `rows_removed` are totals across every value you passed, not per value.

| Field               | Description                                                 |
| ------------------- | ----------------------------------------------------------- |
| `status`            | `success`, or `not_found` when nothing in the list matched. |
| `data.rows_matched` | How many contacts matched in total.                         |
| `data.rows_removed` | How many were removed. `0` on a dry run.                    |
| `data.matched_on`   | Which identifier fields were used.                          |
| `data.dry_run`      | Whether this was a dry run.                                 |
| `credits_used`      | Always `0`.                                                 |

{% hint style="warning" %}
`rows_removed` can be **higher** than the number of values you sent, because every contact matching a value is removed. Ten names that each match two contacts remove twenty contacts. Always read `rows_removed` rather than assuming it equals the length of your input.
{% endhint %}

## Example

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

```json
{
  "api_key": "your_api_key",
  "listname": "Roofing Owners in California",
  "emails": [
    "jane@example.com",
    "sam@example.com"
  ],
  "person_names": [
    "John Smith"
  ]
}
```

{% endtab %}

{% tab title="Output" %}

```json
{
  "status": "success",
  "data": {
    "list_name": "Roofing Owners in California",
    "rows_matched": 4,
    "rows_removed": 4,
    "matched_on": ["email", "person_name"],
    "dry_run": false
  },
  "credits_used": 0,
  "credits_remaining": 448.5,
  "message": "Removed 4 contacts."
}
```

{% endtab %}
{% endtabs %}

Three values were sent and four contacts were removed, because two contacts shared the name `John Smith`.

## Recommended flow

1. Send the call with `dry_run: true`.
2. Read `rows_matched`. If it is higher than you expected, narrow your input by swapping names for emails or LinkedIn URLs, which identify one person each.
3. Send the same call without `dry_run` and check `rows_removed`.
