Tracking and authenticity
Watch a post's views for a set period, read the raw samples, and get an authenticity score with the reasons behind it.
Tracking watches a post for a fixed period and keeps every reading. The authenticity score says whether those readings look organic. Every number comes from the platform on Zernio's own analytics sync, so it is read, never self-reported.
All endpoints require the Analytics add-on.
Tracking windows
A tracking window watches one post for trackingDays days (30 by default, 90 at most). When it ends, Zernio runs one final read and fires post.tracking_completed.
curl -X POST https://zernio.com/api/v1/analytics/tracking \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "accountId": "6507a1b2c3d4e5f6a7b8c9d0", "url": "https://www.tiktok.com/@creator/video/7685731010461371662", "trackingDays": 30 }'Identify the post with postId, or with accountId and the post's url. A new window returns 201. Opening a window for a post that already has one returns that window with 200.
A window moves through these statuses:
| Status | Meaning |
|---|---|
open | The window is running and samples are being collected. |
completing | The window ended and the final read is in progress. |
completed | The final read finished. completionReason says how. |
cancelled | You cancelled the window. It gets no final read and fires no webhook. |
completionReason is final_read (the read succeeded), unreachable (the sync failed or no sample exists), post_deleted (the post is gone from the platform) or cancelled.
Read windows with GET /v1/analytics/tracking and GET /v1/analytics/tracking/{windowId}. Cancel one with DELETE /v1/analytics/tracking/{windowId}. Each window carries latest, the newest verified numbers.
Samples
GET /v1/analytics/samples?postId=... returns every reading behind a post's numbers, oldest first. One sample is one analytics sync.
shares and saves are null on platforms that do not return that counter. That is different from a real zero. watchSeconds and completionRate are null when the platform gives no watch signal.
Authenticity score
GET /v1/posts/{postId}/authenticity returns a score from 0 to 100. Higher means the view pattern looks more like organic viewing. The score is Zernio's own, computed from the verified samples.
{
"postId": "6507a1b2c3d4e5f6a7b8c9d0",
"score": 62,
"confidence": 0.8,
"reasons": [{ "code": "late_block", "weight": 35 }],
"version": "2026-10-22.1",
"computedAt": "2026-10-23T03:00:00.000Z",
"sampleCount": 14
}confidence is 0 to 1 and says how much data the score rests on. A stored score newer than 30 minutes is returned as is, otherwise it is recomputed. List stored scores for an account with GET /v1/analytics/authenticity, filtering by minScore and maxScore.
Each reason lowers the score by its weight in points:
| Code | What it means |
|---|---|
late_block | One large jump in views arrived long after publishing, instead of building up gradually. |
flat_engagement | Likes, comments and the other counters the platform returns are low compared with the views. |
view_follower_gap | Views are far above the account's follower count while the post has no shares. |
cap_seeking | Views sit repeatedly close to a payout cap. |
prior_flags | The account has earlier posts that were flagged. |
no_watch_signal | The platform gives no watch-time or completion data. Weight is 0 and only confidence drops. |
Authenticity webhook
post.authenticity_changed fires when a tracked post's score crosses 40, in either direction, while its window is open. A post's first score never fires it. The payload carries the new and previous score, confidence and reasons.
Related
- Webhooks: create an endpoint, retries, signatures.
- Get analytics: metrics for every post.
Pixels and tracking tags
One API for every ad platform's pixel or site tag: list, create, update, read stats, share, manage users and conversion events, and install on Shopify, WordPress, Wix or Webflow.
Automated ad rules
Pause, reactivate or rebudget campaigns and ad sets automatically when their metrics cross a threshold, or get a webhook when they do.