TikTok and Instagram analytics API
If your product posts to social platforms, users will ask how the posts did. Getting views and likes means four different analytics APIs with four auth flows and four field names for the same thing. This guide explains what each platform returns and how UGC API gives you one shape for all of them.
Updated
Four platforms, four analytics APIs
Each platform exposes post metrics differently. At a high level:
| Platform | Where metrics come from | What you get | Catches |
|---|---|---|---|
| TikTok | The video list endpoint of TikTok's Display API, with fields you request | View, like, comment and share counts per video | Needs a separate scope from posting. You match the published video to your post yourself. |
| Media insights in the Graph API | Views, reach, likes, comments, shares, saves | Metric names differ by media type and change between Graph API versions. Business or Creator accounts only. | |
| Facebook Pages | Page post and video insights in the Graph API | Views, reactions, comments, shares | Needs Page insights permission. Reels and photo posts report different metrics. |
| YouTube | YouTube Data API statistics and YouTube Analytics API | Views, likes, comments | Analytics reports lag. Calls count against the project's daily quota. |
Building this yourself means four app reviews for read permissions, four token refresh flows, rate limits per platform, and a mapping table that breaks whenever a platform renames a metric.
One shape for every platform
UGC API reads metrics for every post it publishes and stores them in one normalised object per result:
| Field | Meaning |
|---|---|
views | Plays or views as the platform counts them |
likes | Likes, or reactions on Facebook |
comments | Comment count |
shares | Share count |
saves | Saves, where the platform reports them |
reach | Unique accounts reached, where the platform reports it |
Not every platform reports every metric. YouTube has no saves, for example, so compare like with like. Each result also carries metrics_at, the time the numbers were last read, so you can tell a new post from one with no engagement.
Read metrics for one post
const post = await fetch("https://ugcapi.dev/v1/posts/post_abc", {
headers: { "Authorization": "Bearer " + process.env.UGCAPI_KEY },
}).then((r) => r.json());
for (const r of post.results) {
console.log(r.platform, r.placement, r.url, r.metrics, r.metrics_at);
}
// tiktok video https://www.tiktok.com/@... { views: 48200, likes: 2900, comments: 81, shares: 140 } 2026-11-06T09:23:00Z
// instagram reel https://www.instagram.com/reel/... { views: 21000, likes: 1100, saves: 95, reach: 17400 } ...The post also has a summed metrics object across all its results, so a cross-posted clip has one total and a per-platform breakdown.
Read totals for a period
GET /v1/stats returns totals for a date range, optionally for one account. The engagement object sums views, likes, comments, shares, saves and reach across published posts, with posts_measured and a by_platform split. top_posts lists the five posts with the most views.
curl "https://ugcapi.dev/v1/stats?from=2026-11-01&to=2026-12-01&account_id=acc_ig_01" -H "Authorization: Bearer ugc_live_..."See the stats doc for every field. To report on one campaign, list its posts with GET /v1/posts?campaign_id=... and sum their metrics.
Refresh cadence
- Metrics for published posts are read hourly in the background. You don't call the platforms or spend their quota.
POST /v1/metrics/refreshreads them again now, at most every 5 minutes per UGC API account. Use it before generating a report, not on every page load.- Short-form posts get most of their views in the first few days. Hourly is enough for reporting and for picking winners.
Webhooks plus polling
There is no webhook for every change in views, since numbers move constantly. The usual pattern combines a webhook with polling:
Polling more often than hourly won't give you fresher numbers, because the background read runs hourly. A nightly copy is enough for most products. Poll more often only for the first day after a post publishes, if your users watch early numbers closely.
- Listen for
post.published. Store thepost_id,account_id,placementand publicurlagainst your own record usingexternal_id. - Verify each webhook with the
X-UGCAPI-Signatureheader, an HMAC-SHA256 of the raw body. See webhooks. - On a schedule, such as hourly or nightly, read
GET /v1/posts?status=published&from=...and update the metrics you store. - For dashboards, read
GET /v1/statswhen the page loads and cache it for an hour.
// Nightly job: copy metrics for last week's posts into your database
let cursor = null;
do {
const url = new URL("https://ugcapi.dev/v1/posts");
url.searchParams.set("status", "published");
url.searchParams.set("from", "2026-11-01");
url.searchParams.set("limit", "100");
if (cursor) url.searchParams.set("cursor", cursor);
const page = await fetch(url, { headers: { "Authorization": "Bearer " + process.env.UGCAPI_KEY } }).then((r) => r.json());
for (const p of page.data) await db.saveMetrics(p.external_id, p.metrics);
cursor = page.next_cursor;
} while (cursor);Storing metrics in your own database
Most products keep a copy of the numbers next to their own records. A simple schema works well:
- One row per result: your record ID,
post_id,account_id,platform,placementand publicurl. - The latest
metricsobject as JSON, plusmetrics_at. - Optionally a daily snapshot table if you want to chart growth over time. Copy the metrics once a day and keep the history yourself.
Key everything on external_id, which you set when creating the post and which comes back in results and webhooks. That way you never need to store UGC API IDs in your main tables.
Rate limits and cost on your side
Reading from UGC API doesn't touch the platforms' quotas, so you won't burn YouTube Data API units or Meta rate limits on reporting. Still, avoid calling stats on every page view. Cache results for an hour, since the numbers only change hourly.
What this API is not
It measures posts published through UGC API. It is not a general social listening tool, and it doesn't return follower growth or audience demographics. If you need those for accounts you don't post to, you still need the native APIs. For the common case, "how did the posts we published do", one endpoint covers all four platforms.
Using it from agents and automations
The same numbers are available through the remote MCP server, so Claude or ChatGPT can answer "which clips did best this week" from your real data. In n8n, the n8n-nodes-ugcapi node can read stats on a schedule and write them to a sheet. See the MCP doc and n8n and Make.
Metrics come with posting at no extra cost. You pay $10 per 1,000 posts and nothing for reading analytics. See pricing.
FAQ
Do I need my own TikTok or Meta app for analytics?
No. UGC API reads metrics through its own approved apps for posts it publishes. You call one API with one key.
Which metrics are normalised?
Views, likes, comments, shares, saves and reach. Not every platform reports all six, so totals for some metrics cover fewer posts.
Is there a webhook when views change?
No. Webhooks cover published, failed and disconnected events. Poll GET /v1/posts or GET /v1/stats for metrics, hourly or less often.
Can I get analytics for posts I didn't publish through UGC API?
Metrics are read for posts UGC API knows about. For other posts on an account, such as ones made in the app, use the platform's own analytics.
Does reading metrics cost credits?
No. Credits are only used for posts. Reading stats and metrics is included.