---
title: "Batch Upsert Contacts"
method: POST
path: "/v2/contacts/batch"
---

# Batch Upsert Contacts

`POST /v2/contacts/batch`

## Request

- Base URL: `https://pub-api.conversion.ai/api`
- URL: `https://pub-api.conversion.ai/api/v2/contacts/batch`
- Auth: one of:
  - API key in header `X-API-Key`
  - API key in query parameter `api_key`

Create or update up to 1,000 contacts in a single request, with a result for each contact. Optionally pass `audienceId` to add successfully upserted contacts to a static audience.

## Request body

- object
  - `contacts` object[], required: An array of contact objects to upsert.
    - `email` string, email: The contact's email address. Required when creating a new contact; updates the email when matching an existing contact by ID.
    - `cnvContactId` string, uuid: The Conversion contact ID. Takes precedence over `userId` and email when identifying an existing contact.
    - `userId` string: Your stable contact identifier, scoped to your workspace. If unmatched, email can match a contact with no user ID and assign this ID; a different existing user ID creates a separate contact unless `updateOnly` is true. Blank values are ignored and do not clear the ID.
    - `subscriptionStatus` 'SUBSCRIBED' | 'UNSUBSCRIBED' | 'NO_STATUS': The contact's email subscription status. System-managed statuses (`BOUNCED`, `COMPLAINED`, etc.) cannot be set through the API.
    - `fields` ContactFields: A map of contact field keys to values. Keys must match existing field definitions in your Conversion account.
    - `companyFields` CompanyFields: A map of company field keys to values for the contact's associated company.
  - `updateOnly` boolean: When `true`, restricts all operations to updates only. Contacts that are not found will be returned with a `contact_not_found` error in their result item.
  - `syncToCRM` boolean: When `true`, syncs upserted contacts to the connected CRM (e.g., Salesforce) if they do not already have an external CRM record.
  - `preserveExistingFields` boolean: When `true`, prevents overwriting existing non-empty field values for all contacts in the batch. New values are only written to fields that are currently empty or unset.
  - `audienceId` string, uuid: Optional Conversion static audience ID. Add successfully upserted contacts to this audience. The audience must belong to the API key workspace.

## Response `200`

Batch processed. Check data.failed and each result for contact or audience failures. An invalid audience is reported for each contact before any writes.

- object
  - `data` object
    - `processed` integer, required: The total number of contacts in the batch.
    - `succeeded` integer, required: The number of contacts with all requested operations completed.
    - `failed` integer, required: The number of contacts that failed.
    - `results` object[], required: An array of result objects in the same order as the input `contacts` array.
      - `success` boolean, required: True if the contact was upserted and, when audienceId is supplied, added to that audience.
      - `cnvContactId` string, uuid: The saved contact ID, including when the audience add fails.
      - `contactCreated` boolean: True if a new contact was created. Retained if the audience add fails.
      - `error` string: A machine-readable error code. Present on failure.
      - `message` string: A human-readable error description. Present on failure.

## Other responses

- `400`: Malformed request.
- `401`: Authentication failed.
- `403`: The API key lacks contact write permissions or edit access to the audience.
- `500`: An internal error prevented batch processing.

---

[API](https://skmtc.dev/conversion/apis/conversion-api.md) - [All operations](https://skmtc.dev/conversion/apis/conversion-api/llms.txt) - [OpenAPI document](https://skmtc.dev/conversion/apis/conversion-api/revisions/8422f815402a?raw)
