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

# Bulk upsert contacts

> Creates or updates 1 to 100 contacts in one call and returns one result per row, in request order. Each row is matched on `matchBy`: a row that matches an existing contact updates it, and any other row creates a contact. When a row matches several contacts, the most recently created one is updated and the others stay as they are, as on [Create a contact](/api-reference/contacts/create-a-contact). Rows in the same call that match each other end up as one contact, and each of those rows reports its id. When they create it, every one of those rows reports `operation: created`. Every row must carry a value it can be matched on, so retrying the same call updates the contacts it created instead of duplicating them. That is why this endpoint takes no `Idempotency-Key`.

**Check each row.** The call answers `200` even when some rows fail. A row with `status: error` carries an `error` with a `code`, a `message` and a `target` that names the row, for example `contacts[1].emails[0]`. Row error codes: `VALIDATION.INVALID_FIELD` (including a row with nothing to match on, a row whose `customFields` has more than 100 keys, a `tagIds` value that is not a tag id, and a `favoriteUserId` that is not a user id), `CONTACTS.UNKNOWN_TAG` (a tag id that names no tag in your account), `CONTACTS.TAG_READ_ONLY`, `CONTACTS.UNKNOWN_CUSTOM_FIELD` and `CONTACTS.UNKNOWN_USER` (a user id that names no user in your account). A failed row is not written. Text fields are cleaned up before their length is checked and they are stored, as on [Create a contact](/api-reference/contacts/create-a-contact): emojis and other characters that take 4 bytes in UTF-8, and control characters such as line breaks and tabs, become a space; repeated whitespace becomes one space; and spaces at the start and end are removed.

**After a server error.** Created rows are committed before updated rows, so a `5xx` answer can leave some rows applied. Retry the same call with the same `matchBy`: rows already applied are matched and updated, not created twice.

Each `ok` row sends [`contact.created`](/guides/webhooks/events/contacts#contact-created), or [`contact.updated`](/guides/webhooks/events/contacts#contact-updated) when an existing contact changed. An updated row that changed nothing sends no webhook. CloudTalk also exports the contacts to your active CRM integrations.



## API Specification

The full API specification for this endpoint is available in the [documentation index](https://help.cloudtalk.io/llms.txt).


## Related topics

- [Contact actions](https://help.cloudtalk.io/api-reference/bulks-legacy/contact-actions.md)
- [Manage contacts with the API](https://help.cloudtalk.io/guides/contacts/manage-with-api.md)
- [CloudTalk API Rate Limits, Headers, and Throttling](https://help.cloudtalk.io/guides/rate-limiting.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.