Zernio
Zernio
OverviewWebhooksPost webhooksInbox webhooksAccount webhooksAnalytics webhooksAds webhooksCall webhooksWhatsApp webhooksPhone number webhooks
Dashboard
llms.txtOpenAPI
OverviewPlatformsAPI ReferenceResources
Webhooks

Analytics webhooks

Receive a cursor each time an account's analytics sync completes, then read every changed post in one call to the delta feed.


analytics.synced tells you that an account's analytics changed and hands you the cursor to read what changed from GET /v1/analytics/delta. Subscribe with POST /v1/webhooks/settings and events: ["analytics.synced"] (first event); delivery, retries and signatures are the same for every event (how webhooks behave).

Events

EventDescription
analytics.syncedOne connected account's analytics sync cycle completed successfully. Carries a cursor for the delta feed, not metrics.

How it behaves

The payload is a cursor for the delta feed

Zernio sends no metrics in this event. It says an account's analytics changed; the delta feed says what changed. sync.cursor is an opaque GET /v1/analytics/delta cursor positioned immediately before this cycle's rows. Pass it straight to the delta feed and one call returns every post whose analytics changed, across every account you can see. That replaces polling GET /v1/analytics once per connected account, where a fleet of 1,000 accounts costs 1,000 requests an hour.

The two are designed to be used together:

  1. Bootstrap your baseline once from GET /v1/analytics.
  2. Receive analytics.synced.
  3. Call GET /v1/analytics/delta with the cursor you were given, then keep sending back each nextCursor.

If you would rather not run a webhook consumer, skip this event and poll the delta feed on a timer. The feed is the source of truth either way.

An empty page does not mean nothing changed

Zernio serves the delta feed from a materialized view, so a read issued the instant this event lands can return an empty data array while the rows are still landing. Re-poll with the same cursor rather than advancing. Advancing on an empty page is the one way to lose changes permanently.

Volume scales with your fleet

Zernio fires this event per account, per successful sync cycle, and sync runs roughly hourly per account. An integration with 1,000 connected accounts should expect on the order of 1,000 events an hour. Two consequences:

  • Subscribe on a dedicated webhook endpoint. An endpoint's consecutive-failure count is shared by every event on it, so an outage on this busy event can disable the whole endpoint and silence low-volume events like post.published with it.
  • Return 2xx first, then do the delta read out of band.

When it does not fire

Zernio skips the event when the sync cycle fails or is skipped because the account was synced recently, when the account is inactive or disconnected, and when the platform does not support analytics sync. GET /v1/analytics lists the supported set.


analytics.synced

One connected account's analytics sync cycle completed successfully. sync.cursor is the delta-feed cursor for this cycle.


Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Webhook payload for analytics.synced. Fired once per connected account each time its analytics sync cycle completes successfully. Poll-driven (roughly hourly per account), not real-time, and never fired for a skipped or failed cycle.

A TRIGGER, not a transport: it deliberately carries no metrics and no cursor. When it arrives, call GET /v1/analytics/delta with YOUR OWN last nextCursor to read what changed, across every account, in one paginated stream.

The absent cursor is deliberate. The feed's ordering position is assigned inside the analytics store when the row is materialized, which normally has not happened yet at the moment this event fires, so a cursor minted here could sit ahead of the very rows the event announces and make you skip them. Your own nextCursor is always in the feed's own ordering and can never do that.

Because of that same lag, a delta read issued the instant this event lands can legitimately come back empty. That is not "nothing changed": poll again with the same cursor you last used rather than treating the account as done.

Subscribe to this event on a DEDICATED webhook endpoint. It is high volume (roughly one delivery per connected account per hour) and a subscription's consecutive-failure count is shared across all of its events, so an outage while this event is flowing can suppress the low-volume publishing events that share the same subscription.

Response Body

Example Requests

Webhook payload for analytics.synced. Fired once per connected account each time its analytics sync cycle completes successfully. Poll-driven (roughly hourly per account), not real-time, and never fired for a skipped or failed cycle.

A TRIGGER, not a transport: it deliberately carries no metrics and no cursor. When it arrives, call GET /v1/analytics/delta with YOUR OWN last nextCursor to read what changed, across every account, in one paginated stream.

The absent cursor is deliberate. The feed's ordering position is assigned inside the analytics store when the row is materialized, which normally has not happened yet at the moment this event fires, so a cursor minted here could sit ahead of the very rows the event announces and make you skip them. Your own nextCursor is always in the feed's own ordering and can never do that.

Because of that same lag, a delta read issued the instant this event lands can legitimately come back empty. That is not "nothing changed": poll again with the same cursor you last used rather than treating the account as done.

Subscribe to this event on a DEDICATED webhook endpoint. It is high volume (roughly one delivery per connected account per hour) and a subscription's consecutive-failure count is shared across all of its events, so an outage while this event is flowing can suppress the low-volume publishing events that share the same subscription.

POST/analytics.synced

Related

  • Webhooks: create an endpoint, retries, signatures.
  • Analytics delta feed: the endpoint the cursor points at.
  • Get analytics: the baseline read.
  • Multi-tenant analytics: per-customer dashboards on top of the feed.
Was this page helpful?

Account webhooks

Receive an event when an account is connected to a profile or stops working, and know how fast each disconnect path reaches you.

Ads webhooks

Receive an event when an ads account finishes its first sync, when a Meta Lead Gen form gets a lead, and when an ad object changes status.

On this page

EventsHow it behavesThe payload is a cursor for the delta feedAn empty page does not mean nothing changedVolume scales with your fleetWhen it does not fireanalytics.syncedRelated
id*string

Stable webhook event ID

event*"analytics.synced"

Value in

  • "analytics.synced"
account*
sync*

Summary of the analytics sync cycle that completed.

timestamp*string

UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued).

Formatdate-time