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

# Syncing Audiences from Hightouch

> Keep audience membership in sync with Hightouch, with optional contact creation and updates.

Sync a Hightouch audience into a static audience in Conversion. Choose whether to sync membership for existing contacts or create and update contacts as part of the sync.

## Before you begin

* Set up the **Conversion** HTTP Request destination using the [contact sync guide](/product-docs/sync/hightouch/syncing-contacts#connect-hightouch-to-conversion).
* [Create a static audience](/product-docs/audiences/creating-an-audience) in Conversion and copy its audience ID from the URL.
* Choose a Hightouch audience, or a model containing its members, with one row per contact and a stable, unique primary key. Hightouch uses this key to detect who joins or leaves.
* If sending fields, create them in Conversion first and use their writable keys from [List Fields](/api-reference/list-fields).

Open your Hightouch audience, add a sync, and select the **Conversion** destination. Use one sync per Conversion audience, then choose one of the following setups.

## Sync membership for existing contacts

Use this when your contacts already exist in Conversion and another integration manages their fields.

| Trigger | Method | Endpoint path | Rows per request |
| :- | :- | :- | :- |
| Rows added | `POST` | `/api/v2/audiences/AUDIENCE_ID/contacts` | A single row |
| Rows removed | `DELETE` | `/api/v2/audiences/AUDIENCE_ID/contacts` | A single row |

Replace `AUDIENCE_ID` with the Conversion audience ID. Leave **Rows changed** disabled. Use this JSON payload for both triggers, replacing `row.email` with your email column:

```json theme={null}
{
  "email": "{{row.email}}"
}
```

This changes membership only. A missing contact returns an error on addition, so run any separate contact sync first. See [Add Contact to Audience](/api-reference/add-contact-to-audience).

## Create or update contacts and sync membership

Use [Batch Upsert Contacts](/api-reference/batch-upsert-contacts) to save contacts and add them to the audience in the same request.

| Trigger | Method | Endpoint path | Rows per request |
| :- | :- | :- | :- |
| Rows added | `POST` | `/api/v2/contacts/batch` | A batch of multiple rows |
| Rows changed | `POST` | `/api/v2/contacts/batch` | A batch of multiple rows |
| Rows removed | `DELETE` | `/api/v2/audiences/AUDIENCE_ID/contacts` | A single row |

For added and changed rows, set the batch size to **100** (maximum **1,000**) and use the JSON editor:

```liquid theme={null}
{
  "audienceId": "AUDIENCE_ID",
  "contacts": [
    {% for row in rows %}
    {
      "email": "{{row.email}}",
      "fields": {
        "first_name": "{{row.first_name}}"
      }
    }{% unless forloop.last %},{% endunless %}
    {% endfor %}
  ]
}
```

Replace `AUDIENCE_ID` with the Conversion audience ID and the column names with your own. Preview the rendered payload before saving.

New contacts are created; existing contacts receive the fields you send. Successfully saved contacts are added to the audience without removing other members. Set `updateOnly` to `true` to update and add existing contacts only; missing contacts then return an error. Your API key needs contact create and edit permissions and edit access to the audience.

For removed rows, use the single-row email payload from the membership-only setup above.

## Removals and matching

[Remove Contact from Audience](/api-reference/remove-contact-from-audience) removes membership from this audience only. The contact, other memberships, and subscription status stay unchanged. Repeating a removal succeeds even if the contact or membership is already absent.

These examples match by email. If emails can change, use a stable `cnvContactId` available in your source for both additions and removals. The membership-only endpoints also accept an existing contact's `userId`.

## Handling errors

Batch requests return HTTP `200` with per-contact outcomes in `data.results` and a failure count in `data.failed`. An `audience_add_failed` result means the contact was saved but its membership could not be confirmed. These failures need response-aware retry handling; Hightouch's HTTP-error retries do not catch errors inside a `200` response.
