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

# Sync audiences

> Sync first-party CRM audiences for an advertiser

`POST /api/v2/buyer/advertisers/{advertiserId}/audiences/sync`

Syncs first-party CRM audiences for an advertiser by adding, removing, or deleting members. Processing is **asynchronous** — the call returns `202` with a `taskId` you poll for completion.

## Request

```bash curl theme={null}
curl -X POST https://api.apostra.com/api/v2/buyer/advertisers/25/audiences/sync \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "audiences": [
      {
        "audienceId": "loyalty-members-2026",
        "name": "Loyalty members",
        "consentBasis": "consent",
        "add": [
          { "externalId": "cust_8841", "email": "person@example.com" },
          { "externalId": "cust_8842", "hashedEmail": "a1b2c3d4e5f6071829304152637485960718293041526374859607182930a1b2" }
        ],
        "remove": [
          { "externalId": "cust_2210" }
        ]
      }
    ],
    "deleteMissing": false
  }'
```

## Parameters

| Field                      | Type          | Required | Notes                                                                                                                                |
| -------------------------- | ------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `advertiserId`             | string (path) | Yes      | Advertiser ID (numeric string, e.g. `25`)                                                                                            |
| `audiences`                | array         | Yes      | Audiences to sync (at least 1)                                                                                                       |
| `audiences[].audienceId`   | string        | Yes      | Buyer's identifier for the audience (1–255 chars). Used in targeting overlays                                                        |
| `audiences[].name`         | string        | No       | Human-readable name (max 255 chars)                                                                                                  |
| `audiences[].consentBasis` | enum          | No       | GDPR lawful basis: `consent`, `legitimate_interest`, `contract`, `legal_obligation`                                                  |
| `audiences[].add`          | array         | No       | Members to add (max 100000). Each needs `externalId` and at least one of `email`, `phone`, `hashedEmail`, `hashedPhone`, or `uids[]` |
| `audiences[].remove`       | array         | No       | Members to remove by `externalId` (max 100000)                                                                                       |
| `audiences[].delete`       | boolean       | No       | When `true`, delete this audience entirely                                                                                           |
| `deleteMissing`            | boolean       | No       | When `true`, audiences not in this request are marked deleted                                                                        |
| `pushNotificationConfig`   | object        | No       | ADCP push notification config to receive a callback when processing completes                                                        |

<Note>
  You may send raw `email` and `phone` values or their pre-hashed equivalents.
  Apostra immediately trims and lowercases raw email, canonicalizes an
  international phone number to E.164, and SHA-256 hashes it before task
  creation, audit capture, persistence, or forwarding. Raw phone values must
  include a leading `+` country code; Apostra never guesses a region.
</Note>

<Note>
  `hashedEmail` and `hashedPhone` must be 64-character SHA-256 hex values and
  are canonicalized to lowercase. If you send both a raw value and its hash,
  they must match after normalization. Use `externalId` only for an opaque,
  audience-scoped member ID, and use `uids[]` only for universal identifiers
  such as UID2, RampID, or MAID. Do not place email addresses or phone numbers
  in `externalId` or `uids[]`; those values are treated as opaque identifiers
  and are not normalized or hashed for you.
</Note>

<Note>
  TikTok Customer File audiences require at least 1,000 valid members when the
  audience is first created. TikTok processing is asynchronous and can take up
  to 24–48 hours. TikTok additions and removals must include a SHA-256 email,
  phone, or MAID; `externalId` alone cannot identify a TikTok member. Retry with
  the same audience ID and idempotency key if a create, update, or delete
  response is interrupted. Apostra reuses the provider audience and checks
  TikTok's current state instead of creating a duplicate. An accepted upload
  does not mean matching is finished: wait while the audience is `processing`
  and poll its status until TikTok reports a final result. If a failed create
  cannot be cleaned up immediately, the response tells you to retry the delete;
  Apostra does not report success until TikTok confirms the audience is
  gone.
</Note>

## Response

```json theme={null}
{
  "success": true,
  "accountId": "25",
  "operationId": "550e8400-e29b-41d4-a716-446655440000",
  "taskId": "550e8400-e29b-41d4-a716-446655440000"
}
```

Returns `202 Accepted`. `taskId` (identical to `operationId`) tracks async processing — poll `GET /api/v2/buyer/tasks/{taskId}` until `status` is `completed` or `failed`. See [Async tasks](/v2/guides/tasks). The synced audiences then appear via [List audiences](/v2/buyer/advertisers/tasks/list-audiences).

## Errors

* `400 VALIDATION_ERROR` — empty `audiences`, malformed email/phone identifiers, raw/hash mismatches, or a batch exceeding 100000 members.
* `404 NOT_FOUND` — `advertiserId` does not exist or is not visible to the authenticated account.

See [Errors](/v2/reference/errors) for the full error contract.

## Related

<CardGroup cols={2}>
  <Card title="Advertiser tasks" href="/v2/buyer/advertisers/tasks" icon="list-check">
    All advertiser operations
  </Card>

  <Card title="Async tasks" href="/v2/guides/tasks" icon="hourglass-half">
    Poll a taskId to completion
  </Card>

  <Card title="List audiences" href="/v2/buyer/advertisers/tasks/list-audiences" icon="users">
    Check match status after sync
  </Card>

  <Card title="Advertiser overview" href="/v2/object-guides/advertiser" icon="user-tie">
    Fields, lifecycle, and concepts
  </Card>
</CardGroup>
