Reports: which platform, account and clip won
Every post has a clip_id: the same video or slideshow keeps one id wherever it went. Reports roll results up by clip, platform, account, caption variant or day, with one comparable views number, the winner, cost per 1,000 views and plain-language insights.
Updated
GET /v1/campaigns/:id/report
group_by is platform (default), account, clip, variant, placement or day. Each group has its totals, average and median views per result, engagement rate, lift over the campaign median, views at 1h, 6h, 1d, 3d and 7d, breakouts and cost. winner is the group with the most views per result, and insights says what stood out.
curl "https://ugcapi.dev/v1/campaigns/cmp_xyz/report?group_by=platform" -H "Authorization: Bearer ugc_live_..."{
"campaign_id": "cmp_xyz",
"group_by": "platform",
"overall": { "results": 40, "published": 40, "measured": 38, "views": 184200, "likes": 9310, "engagement_rate": 0.083, "median_views": 2100, "cost_usd": 0.4, "cost_per_1k_views": 0.0022, "breakouts": 2 },
"groups": [
{ "key": "tiktok", "avg_views": 5200, "lift": 2.48, "views": 52000, "saves": null, "reach": null, "engagement_rate": 0.089, "views_at": { "1h": 300, "6h": 1900, "1d": 4160, "3d": 5000, "7d": null } },
{ "key": "instagram", "avg_views": 2100, "lift": 1, "views": 21000, "saves": 400, "reach": 18000, "engagement_rate": 0.105 }
],
"winner": { "key": "tiktok", "avg_views": 5200, "times_runner_up": 2.5 },
"insights": ["tiktok led on views per post: 2.5× the next platform.", "instagram had the best engagement rate (10.5%)."]
}One clip across every platform
GET /v1/clips lists clips best first (filter with campaign_id, from, to). GET /v1/clips/:clip_id returns one clip's totals, the winning platform and account, results by platform, by account and by caption variant, its views over time, and every result with its URL and numbers.
curl "https://ugcapi.dev/v1/clips/clip_a634d29f5398886a" -H "Authorization: Bearer ugc_live_..."How numbers compare
| Platform | views | likes | comments | shares | saves | reach |
|---|---|---|---|---|---|---|
| TikTok | views | ✓ | ✓ | ✓ | null | null |
| Instagram Reels and posts | views (plays) | ✓ | ✓ | ✓ | ✓ | ✓ |
| Facebook Reels | Reel plays | reactions | ✓ | ✓ | null | null |
| Facebook photo posts | null | reactions | ✓ | ✓ | null | null |
| YouTube Shorts | views | ✓ | ✓ | null | null | null |
nullmeans the platform doesn't report that number, which is different from 0. Totals skip nulls.engagementis likes + comments + shares + saves;engagement_rateis engagement ÷ views.- Numbers refresh hourly (
POST /v1/metrics/refreshreads them again now). Snapshots are kept hourly for a result's first 48 hours and daily after that, which is whereviews_atcomes from. - Instagram Stories are left out of reports: their numbers disappear after 24 hours.
cost_usdis the credits used ($10 per 1,000 results);cost_per_1k_viewsdivides it by views.
Caption variants and A/B labels
Give a post caption_variants and UGC API rotates them across accounts; each result is labelled caption_1, caption_2… Or set variant (like hook-b) on posts yourself. group_by=variant then tells you which caption or hook won. You can also set your own clip_id to group different files (say, two edits of one shoot) as one clip.
Breakouts
When a result reaches 3× its account's median views (the account's other results at least a day old, with at least 100 views) within its first 48 hours, it gets breakout_at and a post.breakout webhook fires. A campaign can repost breakouts automatically: see repost rules.
FAQ
What is a clip?
The same content wherever it was posted. UGC API fingerprints the media when it's uploaded, so one video posted to 30 accounts on four platforms is one clip with one clip_id.
Why is TikTok views null?
TikTok numbers need the video.list permission, which is granted after TikTok's app review. Until then TikTok results show null rather than 0.
Can I compare caption variants?
Yes. Use caption_variants on a post (or the variant label) and call the campaign report with group_by=variant.