---
title: "Ads initial sync completed event"
method: POST
path: "account.ads.initial_sync_completed"
tags: ["Webhook Events"]
---

# Ads initial sync completed event

`POST account.ads.initial_sync_completed` (webhook)

Fired once per ads-enabled account when the initial sync (ad-account
discovery + 90-day historical ad backfill) completes. The `sync` block
reports whether the backfill succeeded and how many ads were synced.

## Payload

- WebhookPayloadAccountAdsInitialSyncCompleted — Webhook payload for `account.ads.initial_sync_completed` events. Fired once per ads-enabled account when the initial discovery + 90-day ad backfill finishes (whether it succeeded fully, partially, or failed).
  - `id` string, required — Stable webhook event ID
  - `event` 'account.ads.initial_sync_completed', required
  - `account` object, required
    - `accountId` string, required — The account's unique identifier (same as used in /v1/accounts/{accountId})
    - `profileId` string, required — The profile's unique identifier this account belongs to
    - `platform` string, required
    - `username` string, required
    - `displayName` string
    - `platformUserId` string — The platform-side account/ad-account ID (e.g. Meta ad account ID).
    - `profilePicture` string, uri — URL of the account's profile picture, when available.
    - `platformAdAccountId` string — When the consumer scoped the connect call to a single ad account, this echoes that ID back so the webhook can be correlated to the originating connect request without consulting the consumer's DB. Meta uses the `act_*` shape.
    - `platformAdAccountIds` string[] — Every ad-account ID that the connected token could see at discovery time. Useful for "we synced ads from these accounts" UX without a follow-up API call. Empty array when the token had no ad-account visibility.
  - `sync` object, required — Summary of the initial ads sync backfill results.
    - `status` 'success' | 'failure', required — Overall outcome of the initial sync.
    - `totalAds` integer, required — Total number of ads discovered for backfill.
    - `synced` integer, required — Number of ads successfully synced.
    - `failed` integer, required — Number of ads that failed to sync.
    - `error` string — Free-form error message from the platform (typically Meta's Marketing API). Truncated to ~2KB. Present when `status` is `failure` (and sometimes on `success` when discovery saw zero ad accounts). For UX branching prefer `errorCategory`; this field is for human display and debugging.
    - `errorCode` string — Platform-native error code if parsed (e.g. Meta `190`, `10`, `200`).
    - `errorSubcode` string — Platform-native error subcode if parsed.
    - `errorCategory` 'token_invalid' | 'permission_denied' | 'no_ad_accounts' | 'rate_limited' | 'discovery_failed' | 'unknown' — Stable category for UX branching. New values may be added; existing ones are stable. Mapping: - `token_invalid`: access token is expired or revoked. Reconnect. - `permission_denied`: token lacks required scope, or the user has no role on the Business Manager that owns the ad account. Reconnect with full permissions, or have an admin grant access. - `no_ad_accounts`: token is valid but sees zero ad accounts. The user needs to connect a Business Manager that owns ad accounts. - `rate_limited`: platform throttled us. Sync will retry automatically. - `discovery_failed`: any other platform-side failure. Inspect `error`. - `unknown`: classifier could not categorize the failure.
  - `timestamp` string, date-time, required

## Acknowledgement `200`

Webhook received successfully

---

[API](https://skmtc.net/zernio/apis/zernio-api.md) · [All operations](https://skmtc.net/zernio/apis/zernio-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/zernio/zernio-api/revisions/f81ca70ea6b9/schema)
