Tracking - Creator & Video Monitoring
Monitor creators and videos over time with configurable scrape cadences. Each tracking cycle collects metric snapshots AND generates an AI analysis report as one bundled operation. On-demand reports are also available. Supports TikTok, YouTube, and Instagram.
All Tracking V1 endpoints use the base URL https://api.virlo.ai/v1/tracking. All parameter names and response fields use snake_case. All responses are wrapped in a { "data": { ... } } envelope. POST endpoints return 202 Accepted because each cycle (metrics + AI analysis) is processed asynchronously as a single bundled operation.
Key Concepts
Scrape Cadence — How often a tracking cycle runs for a tracked creator or video. Each cycle collects metrics AND generates a fresh AI analysis report as one bundled operation. Options: six_hours, twelve_hours, daily, every_other_day, weekly, bi_weekly, monthly. Default: daily. Each cycle costs $0.25.
Snapshots — Point-in-time metric captures stored each time a cycle runs: followers, total*likes, total_videos, total_views, plus collected_post_count (how many posts contributed to total_views for TikTok/Instagram). All metrics include delta*\* fields showing change from the previous snapshot. Use snapshots to build growth charts and track performance over time.
AI Reports — Comprehensive analysis generated by Virlo's AI engine on every tracking cycle. Creator reports include content strategy insights, audience analysis, and growth recommendations. Video reports analyze performance, engagement patterns, and audience sentiment. Reports are generated automatically — retrieve them with the GET report endpoint at any time.
Audience Snapshots — Demographic (age band, gender, language) and geographic (country, city) profile of a creator's engaged audience — the people actually showing up in the replies, not the raw follower count on paper. Snapshots are derived by sampling and analyzing the creator's public commenters, with a follower-list fallback on TikTok when comment volume is too sparse to draw a confident sample. Generated on demand (no automatic cron) and cached for 30 days by default. The two GET endpoints (audience-demographics, audience-geography) are always free cache reads; the POST audience-refresh endpoint triggers a fresh snapshot when the cache is stale. Each fresh snapshot costs a flat $0.50 on any platform.
A snapshot can be returned for almost any creator: when commenter signal is too sparse for a confident sample, the pipeline falls back gracefully — by widening the comment window (Instagram + YouTube), by blending in follower-list signals (TikTok), and as a last resort by synthesizing a low-confidence hint from the creator's own declared profile (country, language, bio). The data_source field on every snapshot tells you exactly which path produced it. Profile-only outcomes are marked data_source: 'profile_only' and confidence_level: 'low', and are always refunded — you only see a $0 charge in usage history.
When a fresh snapshot is requested, the endpoint returns a job_id to poll, and the audience.snapshot.completed webhook fires when ready. If the job ultimately fails INSUFFICIENT_SAMPLE (the creator has zero profile metadata either), the $0.50 is automatically refunded — visible as a negative-credit row in your usage history.
Cost
| Endpoint | Price |
|---|---|
| POST /v1/tracking/creators | $0.25 (initial cycle) |
| POST /v1/tracking/videos | $0.25 (initial cycle) |
| Each recurring tracking cycle (metrics + AI report) | $0.25 per cycle |
| POST /v1/tracking/creators/:id/posts/collect (standard) | $0.50 (up to 50 videos) |
| POST /v1/tracking/creators/:id/posts/collect (deep) | $1.00 (up to 200 videos) |
| POST /v1/tracking/creators/:id/posts/collect (full) | $2.00 (up to 500 videos) |
| POST /v1/tracking/creators/:id/audience-refresh | $0.50 per fresh snapshot (any platform; auto-refunded on data_source: 'profile_only' or INSUFFICIENT_SAMPLE) |
| GET /v1/tracking/creators/:id/audience-demographics | Free (cache read) |
| GET /v1/tracking/creators/:id/audience-geography | Free (cache read) |
| All other GET, PATCH, DELETE endpoints | Free |
Track a creator
Start tracking a creator. The system immediately queues an initial tracking cycle that collects metrics and generates an AI analysis report as one bundled operation. You can provide either a profile URL or a handle with a platform.
$0.25 (initial cycle)
Request body
- Name
platform- Type
- string
- Required
- *
- Description
Platform to track. One of:
tiktok,youtube,instagram.
- Name
url- Type
- string
- Description
Creator profile URL. Either
urlorhandleis required.
- Name
handle- Type
- string
- Description
Creator handle (without @). Either
urlorhandleis required.
- Name
scrape_cadence- Type
- string
- Description
How often to run a tracking cycle. Options:
six_hours,twelve_hours,daily,every_other_day,weekly,bi_weekly,monthly. Default:daily. Each cycle costs $0.25.
- Name
collection_depth- Type
- string
- Description
Optional initial post collection depth. One of:
standard(50 videos, +$0.50),deep(200 videos, +$1.00),full(500 videos, +$2.00). If omitted, only daily shallow collection runs. Extra credits charged on top of the $0.25 cycle cost.
Request
curl -X POST https://api.virlo.ai/v1/tracking/creators \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"platform": "tiktok",
"handle": "khaby.lame",
"scrape_cadence": "twelve_hours"
}'
Response
{
"data": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "active",
"message": "Creator tracking started. Initial metrics and AI report are being generated.",
"finalized": false,
"pending_jobs": [
{
"type": "tracking_report",
"status": "pending",
"poll_url": "/v1/tracking/creators/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"result_path": "data",
"webhook_event": "tracking.cycle.completed",
"retry_after_seconds": 15
}
]
}
}
List tracked creators
Retrieve a paginated list of all tracked creators for the authenticated team.
Free
Query parameters
- Name
page- Type
- integer
- Description
Page number (1-indexed). Default:
1.
- Name
limit- Type
- integer
- Description
Results per page (1-100). Default:
20.
- Name
platform- Type
- string
- Description
Filter by platform:
tiktok,youtube, orinstagram.
- Name
search- Type
- string
- Description
Search by handle or display name (case-insensitive partial match). E.g.
?search=gordon.
Request
curl -G https://api.virlo.ai/v1/tracking/creators \
-H "Authorization: Bearer {token}" \
-d limit=20 \
-d page=1
Response
{
"data": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"platform": "tiktok",
"platform_handle": "khaby.lame",
"display_name": "Khabane lame",
"status": "active",
"scrape_cadence": "twelve_hours",
"latest_followers": 160400000,
"latest_total_likes": 2400000000,
"latest_total_videos": 1313,
"growth_rate": 1.0,
"followers_gained": 100000,
"enrichment_status": "ready",
"last_scraped_at": "2026-03-23T14:00:00.000Z",
"next_scrape_at": "2026-03-24T02:00:00.000Z",
"created_at": "2026-03-20T10:30:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 5,
"total_pages": 1,
"has_next_page": false,
"has_prev_page": false
}
}
Get tracked creator
Get full details for a specific tracked creator including current metrics, tracking configuration, and enrichment status.
Free
Path parameters
- Name
id- Type
- string
- Required
- *
- Description
The tracked creator ID returned when tracking was started.
Request
curl https://api.virlo.ai/v1/tracking/creators/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
-H "Authorization: Bearer {token}"
Response
{
"data": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"platform": "tiktok",
"platform_handle": "khaby.lame",
"display_name": "Khabane lame",
"avatar_url": "https://p16-sign-sg.tiktokcdn.com/...",
"profile_url": "https://www.tiktok.com/@khaby.lame",
"bio": "If u wanna laugh u r in the right place",
"is_verified": true,
"status": "active",
"scrape_cadence": "twelve_hours",
"enrichment_status": "completed",
"latest_followers": 160400000,
"latest_following": 86,
"latest_total_videos": 1313,
"latest_total_likes": 2400000000,
"latest_total_views": 8455553979,
"growth_rate": 1.0,
"followers_gained": 100000,
"last_scraped_at": "2026-03-23T14:00:00.000Z",
"next_scrape_at": "2026-03-24T02:00:00.000Z",
"category": "comedy",
"content_tags": ["silent-comedy", "life-hacks", "reactions"],
"profile_metadata": {
"country": "IT",
"language": "en",
"external_links": []
},
"created_at": "2026-03-20T10:30:00.000Z",
"updated_at": "2026-03-23T14:00:00.000Z"
}
}
Get creator report
Get the latest AI analysis report for a tracked creator. Reports are generated automatically on every tracking cycle. The analysis is a structured JSON object with content strategy insights, audience sentiment, growth recommendations, content themes, and outlier videos.
Free
Request
curl https://api.virlo.ai/v1/tracking/creators/a1b2c3d4-e5f6-7890-abcd-ef1234567890/report \
-H "Authorization: Bearer {token}"
Response
{
"data": {
"account": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"platform": "tiktok",
"platform_handle": "khaby.lame",
"display_name": "Khabane lame",
"latest_followers": 160400000
},
"report": {
"id": "r1s2t3u4-v5w6-x7y8-z9a0-b1c2d3e4f5g6",
"tracking_account_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"analysis": {
"overview": {
"headline": "160M-follower TikTok comedy creator...",
"recent_focus": "Shifted toward event-driven content...",
"content_focus": "Universal, language-agnostic comedy...",
"growth_insight": "Sustained but plateauing engagement..."
},
"what_works": [
{
"insight": "Silent, non-verbal storytelling...",
"evidence": "Top 5 videos contain zero spoken words...",
"evidence_video_ids": ["6979606181463526661"]
}
],
"content_themes": [
{
"name": "Life Hack Reactions",
"avg_views": 89400000,
"description": "Watches overcomplicated solutions...",
"video_count": 8
}
],
"posting_patterns": {
"frequency": "1-2 videos per week...",
"best_formats": ["Silent reaction-to-hack (13-18 sec)"],
"optimal_duration": "13-18 seconds"
},
"audience_sentiment": {
"overall_summary": "Overwhelmingly positive, global...",
"sentiment_labels": ["highly_positive", "appreciative"],
"notable_comments": [
{
"likes": 190974,
"content": "Learn from Khaby",
"insight": "Audience views Khaby as an educator"
}
]
}
},
"model_used": "anthropic/claude-haiku-4.5",
"created_at": "2026-03-23T14:00:00.000Z"
}
}
}
Get creator snapshots
Get historical metric snapshots for a tracked creator. Each snapshot captures the creator's metrics at a point in time, plus computed delta_* fields showing the change from the previous snapshot. Use snapshots to build growth charts and track performance trends.
About total_views: For YouTube, this is the real profile-level view count from the platform. For TikTok and Instagram, the platform APIs do not expose a profile-level metric, so total_views is computed as the sum of views across collected posts — collected_post_count tells you how many posts are included. This refreshes each tracking cycle. For broader coverage, trigger a post collection after you start tracking.
Free
Query parameters
- Name
start_date- Type
- string
- Description
ISO 8601 date. Only return snapshots on or after this date. E.g.
?start_date=2026-01-01T00:00:00Z.
- Name
end_date- Type
- string
- Description
ISO 8601 date. Only return snapshots on or before this date.
- Name
limit- Type
- integer
- Description
Max snapshots to return (1-365). Default:
30.
Request
curl https://api.virlo.ai/v1/tracking/creators/a1b2c3d4-e5f6-7890-abcd-ef1234567890/snapshots \
-H "Authorization: Bearer {token}"
Response
{
"data": [
{
"id": "snap-001",
"tracking_account_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"followers": 160300000,
"following": 86,
"total_videos": 1311,
"total_views": 8450000000,
"total_likes": 2398000000,
"collected_post_count": 35,
"subscribers": null,
"snapshot_at": "2026-03-22T14:00:00.000Z",
"delta_followers": null,
"delta_following": null,
"delta_total_videos": null,
"delta_total_views": null,
"delta_total_likes": null
},
{
"id": "snap-002",
"tracking_account_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"followers": 160400000,
"following": 86,
"total_videos": 1313,
"total_views": 8455553979,
"total_likes": 2400000000,
"collected_post_count": 35,
"subscribers": null,
"snapshot_at": "2026-03-23T02:00:00.000Z",
"delta_followers": 100000,
"delta_following": 0,
"delta_total_videos": 2,
"delta_total_views": 5553979,
"delta_total_likes": 2000000
}
]
}
Update tracked creator
Update tracking configuration for a creator. You can change the status or scrape cadence. Changing the cadence recalculates the next_scrape_at timestamp.
Free
Request body
- Name
status- Type
- string
- Description
Set to
activeorpaused.
- Name
scrape_cadence- Type
- string
- Description
New scrape cadence:
six_hours,twelve_hours,daily,every_other_day,weekly,bi_weekly,monthly. Each cycle costs $0.25.
Request
curl -X PATCH https://api.virlo.ai/v1/tracking/creators/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{ "scrape_cadence": "six_hours" }'
Response
{
"data": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"platform": "tiktok",
"platform_handle": "khaby.lame",
"status": "active",
"scrape_cadence": "six_hours",
"next_scrape_at": "2026-03-24T08:00:00.000Z"
}
}
Stop tracking creator
Stop tracking a creator. This performs a soft delete — historical data (snapshots, reports) is retained but no further cycles will run. The creator will no longer appear in list results.
Free
Request
curl -X DELETE https://api.virlo.ai/v1/tracking/creators/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
-H "Authorization: Bearer {token}"
Response
(empty response body)
List creator posts
List a tracked creator's posts with per-post metrics (views, likes, comments, shares, bookmarks) and content type flags (is_duet, is_stitch for TikTok). Posts are populated by daily tracking cycles and on-demand collection. Paginated with date filtering and sorting.
Free
Query parameters
- Name
page- Type
- integer
- Description
Page number (1-indexed). Default:
1.
- Name
limit- Type
- integer
- Description
Results per page (1-200). Default:
50.
- Name
start_date- Type
- string
- Description
ISO 8601 date. Filter posts published on or after this date.
- Name
end_date- Type
- string
- Description
ISO 8601 date. Filter posts published on or before this date.
- Name
sort- Type
- string
- Description
Sort order:
publish_date_desc(default),publish_date_asc,views_desc.
Request
curl -G "https://api.virlo.ai/v1/tracking/creators/a1b2c3d4-e5f6-7890-abcd-ef1234567890/posts" \
-H "Authorization: Bearer {token}" \
-d limit=20 \
-d sort=views_desc
Response
{
"data": [
{
"id": "post-uuid-001",
"tracking_account_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"platform": "tiktok",
"platform_video_id": "7234567890123456789",
"url": "https://www.tiktok.com/@khaby.lame/video/7234567890123456789",
"title": "Let's just use regular belt...",
"views": 85000000,
"likes": 6200000,
"comments": 31000,
"shares": 450000,
"bookmarks": 120000,
"is_duet": false,
"is_stitch": false,
"publish_date": "2026-03-15T12:00:00.000Z",
"hashtags": ["fyp", "comedy"],
"collected_at": "2026-03-23T14:00:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 150,
"total_pages": 8,
"has_next_page": true,
"has_prev_page": false
}
}
Get creator post
Get full details for a single creator post including all available metrics.
Free
Request
curl "https://api.virlo.ai/v1/tracking/creators/a1b2c3d4.../posts/post-uuid-001" \
-H "Authorization: Bearer {token}"
Response
{
"data": {
"id": "post-uuid-001",
"tracking_account_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"platform": "tiktok",
"platform_video_id": "7234567890123456789",
"url": "https://www.tiktok.com/@khaby.lame/video/7234567890123456789",
"title": "Let's just use regular belt...",
"description": "Full video description...",
"views": 85000000,
"likes": 6200000,
"comments": 31000,
"shares": 450000,
"bookmarks": 120000,
"is_duet": false,
"is_stitch": false,
"duration_seconds": 15,
"publish_date": "2026-03-15T12:00:00.000Z",
"hashtags": ["fyp", "comedy"],
"collected_at": "2026-03-23T14:00:00.000Z"
}
}
Collect creator posts
Trigger on-demand deep post collection for a tracked creator. This starts an async scraping job that paginates through the creator's videos. Choose a depth tier based on how many videos you need.
$0.50 – $2.00 (varies by depth)
Depth Tiers
| Tier | Max Videos | Cost |
|---|---|---|
standard | 50 | $0.50 |
deep | 200 | $1.00 |
full | 500 | $2.00 |
Request body
- Name
depth- Type
- string
- Description
Collection depth tier:
standard(default),deep, orfull.
Request
curl -X POST "https://api.virlo.ai/v1/tracking/creators/a1b2c3d4.../posts/collect" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{ "depth": "deep" }'
Response
{
"data": {
"collection_id": "col-uuid-001",
"status": "processing",
"depth": "deep",
"max_videos": 200,
"credits_reserved": 100
}
}
Get collection status
Poll the status of a post collection job. Status will be processing, completed, or failed.
Free
Request
curl "https://api.virlo.ai/v1/tracking/creators/a1b2c3d4.../posts/collect/col-uuid-001" \
-H "Authorization: Bearer {token}"
Response
{
"data": {
"collection_id": "col-uuid-001",
"status": "completed",
"depth": "deep",
"videos_collected": 187,
"max_videos": 200,
"started_at": "2026-04-14T10:00:00Z",
"completed_at": "2026-04-14T10:02:30Z"
}
}
Get posting cadence
Get posting frequency analytics derived from collected posts. Includes average gaps between posts, posts per week/month, and day-of-week distribution. Requires posts to be collected first (via daily cycles or on-demand collection).
Free
Request
curl "https://api.virlo.ai/v1/tracking/creators/a1b2c3d4.../posting-cadence" \
-H "Authorization: Bearer {token}"
Response
{
"data": {
"total_posts": 150,
"avg_days_between_posts": 2.3,
"posts_per_week": 3.04,
"posts_per_month": 13.04,
"day_of_week_distribution": {
"0": 15, "1": 22, "2": 28, "3": 25,
"4": 20, "5": 22, "6": 18
},
"earliest_post_date": "2025-10-01T12:00:00.000Z",
"latest_post_date": "2026-04-13T18:00:00.000Z"
}
}
Get audience demographics
Return the latest cached engaged-audience demographics snapshot (age bands, gender split, language mix) for a tracked creator. Always free — this endpoint never triggers a fresh collection. If no snapshot exists yet, call POST /v1/tracking/creators/:id/audience-refresh first.
Free
Query parameters
- Name
freshness_days- Type
- integer
- Description
Max age of an acceptable cached snapshot, in days. Default is
30. Snapshots older than this are treated as not-found and the response returnsnulldata.
Request
curl "https://api.virlo.ai/v1/tracking/creators/a1b2c3d4.../audience-demographics?freshness_days=30" \
-H "Authorization: Bearer {token}"
Response
{
"data": {
"platform": "tiktok",
"handle": "khaby.lame",
"snapshot": {
"snapshot_id": "f5a3b2c1-...",
"snapshot_at": "2026-05-01T12:00:00Z",
"sample_size": 712,
"age_distribution": { "18-24": 0.46, "25-34": 0.32, "13-17": 0.14, "35-44": 0.06, "45+": 0.02 },
"gender_distribution": { "female": 0.55, "male": 0.45 },
"language_distribution": { "en": 0.62, "it": 0.18, "pt": 0.09, "es": 0.07, "fr": 0.04 },
"country_distribution": null,
"city_distribution": null,
"confidence_per_signal": { "age": 0.72, "gender": 0.84, "country": 0.79, "city": 0.69, "language": 0.81 },
"confidence_level": "high",
"data_source": "comments",
"signal_breakdown": { "comments": 712, "followers": 0 },
"evidence_summary": "Sample of 712 commenters drawn from 10 recent posts shows...",
"model_version": "v1.3"
},
"is_stale": false,
"finalized": true,
"pending_jobs": []
}
}
Get audience geography
Return the latest cached engaged-audience geography snapshot (top countries and cities) for a tracked creator. Always free — never triggers a fresh collection. If no snapshot exists yet, call POST /v1/tracking/creators/:id/audience-refresh first.
Free
Query parameters
- Name
freshness_days- Type
- integer
- Description
Max age of an acceptable cached snapshot, in days. Default
30.
Request
curl "https://api.virlo.ai/v1/tracking/creators/a1b2c3d4.../audience-geography" \
-H "Authorization: Bearer {token}"
Response
{
"data": {
"platform": "tiktok",
"handle": "khaby.lame",
"snapshot": {
"snapshot_id": "f5a3b2c1-...",
"snapshot_at": "2026-05-01T12:00:00Z",
"sample_size": 712,
"age_distribution": null,
"gender_distribution": null,
"language_distribution": null,
"country_distribution": [
{ "code": "IT", "name": "Italy", "pct": 0.31, "confidence": 0.84 },
{ "code": "US", "name": "United States", "pct": 0.22, "confidence": 0.81 },
{ "code": "BR", "name": "Brazil", "pct": 0.11, "confidence": 0.78 },
{ "name": "Other (12 countries)", "pct": 0.08 }
],
"city_distribution": [
{ "code": "IT", "name": "Milan", "pct": 0.08, "confidence": 0.71 },
{ "code": "IT", "name": "Rome", "pct": 0.06, "confidence": 0.68 },
{ "name": "Other (4 cities)", "pct": 0.04 }
],
"confidence_per_signal": { "age": 0.72, "gender": 0.84, "country": 0.79, "city": 0.69, "language": 0.81 },
"confidence_level": "high",
"data_source": "comments",
"signal_breakdown": { "comments": 712, "followers": 0 },
"evidence_summary": "Sample of 712 commenters drawn from 10 recent posts shows...",
"model_version": "v1.3"
},
"is_stale": false,
"finalized": true,
"pending_jobs": []
}
}
Refresh audience snapshot
Trigger a fresh engaged-audience snapshot for a tracked creator. The endpoint is cache-first: if a snapshot already exists that's younger than freshness_days, it's returned immediately with no credit charge. Otherwise the request queues a new collection job, returns a job_id, and the audience.snapshot.completed webhook fires when ready.
Fresh snapshots cost a flat $0.50 on any platform. Credits are deducted only when a new job is queued — cached returns are always free. When the snapshot lands on the profile_only fallback (no real audience signal could be harvested — see the data_source taxonomy below) OR fails INSUFFICIENT_SAMPLE, the $0.50 is automatically refunded; the refund appears as a negative-credit row in your usage history.
$0.50 on cache miss (auto-refunded on data_source: 'profile_only' or INSUFFICIENT_SAMPLE)
Request body
- Name
freshness_days- Type
- integer
- Description
Reuse a cached snapshot if it's younger than this many days. Default
30. Use0to force a fresh snapshot every time.
- Name
force- Type
- boolean
- Description
Bypass the freshness check entirely. When
true, a new snapshot is generated even if a recent one exists. Charges credits. Use sparingly.
Request
curl -X POST "https://api.virlo.ai/v1/tracking/creators/a1b2c3d4.../audience-refresh" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{ "freshness_days": 30 }'
Response
{
"data": {
"source": "cache",
"snapshot": {
"snapshot_id": "f5a3b2c1-...",
"snapshot_at": "2026-05-01T12:00:00Z",
"sample_size": 712,
"age_distribution": { "18-24": 0.46, "25-34": 0.32, "13-17": 0.14 },
"gender_distribution": { "female": 0.55, "male": 0.45 },
"language_distribution": { "en": 0.62, "it": 0.18, "pt": 0.09 },
"country_distribution": [{ "code": "IT", "name": "Italy", "pct": 0.31, "confidence": 0.84 }],
"city_distribution": [{ "code": "IT", "name": "Milan", "pct": 0.08, "confidence": 0.71 }],
"confidence_per_signal": { "age": 0.72, "gender": 0.84, "country": 0.79, "city": 0.69, "language": 0.81 },
"confidence_level": "high",
"data_source": "comments",
"signal_breakdown": { "comments": 712, "followers": 0 },
"evidence_summary": "Sample of 712 commenters drawn from 10 recent posts shows...",
"model_version": "v1.3"
},
"job_id": null,
"status": null,
"credits_used": 0,
"creator_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"credit_unit": "cent",
"finalized": true,
"pending_jobs": []
}
}
Check audience refresh status
Poll a running audience snapshot job by job_id. Returns { status: "processing" | "completed" | "failed", snapshot, error }. Always free — no credit cost. The status endpoint is the deterministic alternative to the audience.snapshot.completed webhook (job state is cached in Redis for 24 hours after completion; older job IDs return 404).
When a job fails with error: "INSUFFICIENT_SAMPLE", the $0.50 already charged at queue time has already been auto-refunded — no action needed on your side. The pipeline only fails with this code when even the profile_only synthesis has zero signal to work with (creator profile is empty too); in practice you'll see a data_source: 'profile_only' low-confidence snapshot far more often than this hard failure. Other failure modes (e.g. upstream platform errors) are not refunded; check the error string for the failure category.
Free
Request
curl "https://api.virlo.ai/v1/tracking/creators/a1b2c3d4.../audience-refresh/9f8e7d6c..." \
-H "Authorization: Bearer {token}"
Response
{
"data": {
"job_id": "9f8e7d6c-...",
"status": "completed",
"error": null,
"snapshot": {
"snapshot_id": "f5a3b2c1-...",
"snapshot_at": "2026-05-01T12:00:00Z",
"sample_size": 712,
"age_distribution": { "18-24": 0.46, "25-34": 0.32, "13-17": 0.14 },
"gender_distribution": { "female": 0.55, "male": 0.45 },
"language_distribution": { "en": 0.62, "it": 0.18 },
"country_distribution": [{ "code": "IT", "name": "Italy", "pct": 0.31, "confidence": 0.84 }],
"city_distribution": [{ "code": "IT", "name": "Milan", "pct": 0.08, "confidence": 0.71 }],
"confidence_per_signal": { "age": 0.72, "gender": 0.84, "country": 0.79, "city": 0.69, "language": 0.81 },
"confidence_level": "high",
"data_source": "comments",
"signal_breakdown": { "comments": 712, "followers": 0 },
"evidence_summary": "Sample of 712 commenters drawn from 10 recent posts shows...",
"model_version": "v1.3"
}
}
}
Track a video
Start tracking a video. The system immediately queues an initial tracking cycle that collects metrics and generates an AI analysis report as one bundled operation.
$0.25 (initial cycle)
Request body
- Name
url- Type
- string
- Required
- *
- Description
Full URL of the video to track.
- Name
platform- Type
- string
- Required
- *
- Description
Platform:
tiktok,youtube, orinstagram.
- Name
tracking_account_id- Type
- string
- Description
Optional. Associate this video with a tracked creator.
- Name
scrape_cadence- Type
- string
- Description
How often to run a tracking cycle. Options:
six_hours,twelve_hours,daily,every_other_day,weekly,bi_weekly,monthly. Default:daily. Each cycle costs $0.25.
Request
curl -X POST https://api.virlo.ai/v1/tracking/videos \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"url": "https://www.tiktok.com/@khaby.lame/video/7234567890123456789",
"platform": "tiktok",
"scrape_cadence": "daily"
}'
Response
{
"data": {
"id": "v1d2e3o4-f5g6-h7i8-j9k0-l1m2n3o4p5q6",
"status": "active",
"message": "Video tracking started. Initial metrics and AI report are being generated."
}
}
List tracked videos
Retrieve a paginated list of all tracked videos for the authenticated team.
Free
Query parameters
- Name
page- Type
- integer
- Description
Page number (1-indexed). Default:
1.
- Name
limit- Type
- integer
- Description
Results per page (1-100). Default:
20.
- Name
platform- Type
- string
- Description
Filter by platform:
tiktok,youtube, orinstagram.
- Name
search- Type
- string
- Description
Search by video title or URL (case-insensitive partial match). E.g.
?search=pancake.
Request
curl -G https://api.virlo.ai/v1/tracking/videos \
-H "Authorization: Bearer {token}" \
-d limit=20 \
-d page=1
Response
{
"data": [
{
"id": "v1d2e3o4-f5g6-h7i8-j9k0-l1m2n3o4p5q6",
"platform": "tiktok",
"url": "https://www.tiktok.com/@khaby.lame/video/7234567890123456789",
"title": "Let's just use regular belt...",
"status": "active",
"scrape_cadence": "daily",
"latest_views": 85000000,
"latest_likes": 6200000,
"latest_comments": 31000,
"latest_shares": 450000,
"growth_rate": 0.05,
"enrichment_status": "ready",
"last_scraped_at": "2026-03-23T14:00:00.000Z",
"created_at": "2026-03-20T10:30:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 3,
"total_pages": 1,
"has_next_page": false,
"has_prev_page": false
}
}
Get tracked video
Get full details for a specific tracked video including current metrics and tracking configuration.
Free
Request
curl https://api.virlo.ai/v1/tracking/videos/v1d2e3o4-f5g6-h7i8-j9k0-l1m2n3o4p5q6 \
-H "Authorization: Bearer {token}"
Response
{
"data": {
"id": "v1d2e3o4-f5g6-h7i8-j9k0-l1m2n3o4p5q6",
"platform": "tiktok",
"url": "https://www.tiktok.com/@khaby.lame/video/7234567890123456789",
"title": "Let's just use regular belt from now on",
"author_handle": "khaby.lame",
"author_name": "Khabane lame",
"status": "active",
"scrape_cadence": "daily",
"latest_views": 85000000,
"latest_likes": 6200000,
"latest_comments": 31000,
"latest_shares": 450000,
"latest_bookmarks": 120000,
"growth_rate": 0.05,
"enrichment_status": "ready",
"last_scraped_at": "2026-03-23T14:00:00.000Z",
"next_scrape_at": "2026-03-24T14:00:00.000Z",
"created_at": "2026-03-20T10:30:00.000Z"
}
}
Get video report
Get the latest AI analysis for a tracked video. The analysis field contains a structured JSON object with engagement insights, audience sentiment, and performance breakdown. Returns null if no analysis has been generated yet (check enrichment_status on the video).
Free
Request
curl https://api.virlo.ai/v1/tracking/videos/v1d2e3o4-f5g6-h7i8-j9k0-l1m2n3o4p5q6/report \
-H "Authorization: Bearer {token}"
Response
{
"data": {
"video": {
"id": "v1d2e3o4-f5g6-h7i8-j9k0-l1m2n3o4p5q6",
"platform": "tiktok",
"url": "https://www.tiktok.com/@khaby.lame/video/7234567890123456789",
"title": "Let's just use regular belt from now on",
"latest_views": 85000000,
"latest_likes": 6200000
},
"analysis": {
"performance": "Exceptional engagement rate...",
"sentiment": "Overwhelmingly positive...",
"recommendations": ["Leverage this format..."]
},
"analysis_updated_at": "2026-03-23T14:00:00.000Z"
}
}
Get video snapshots
Get historical metric snapshots for a tracked video. Each snapshot captures views, likes, comments, shares, and bookmarks at a point in time, plus computed delta_* fields showing the change from the previous snapshot.
Free
Query parameters
- Name
start_date- Type
- string
- Description
ISO 8601 date. Only return snapshots on or after this date.
- Name
end_date- Type
- string
- Description
ISO 8601 date. Only return snapshots on or before this date.
- Name
limit- Type
- integer
- Description
Max snapshots to return (1-365). Default:
30.
Request
curl https://api.virlo.ai/v1/tracking/videos/v1d2e3o4-f5g6-h7i8-j9k0-l1m2n3o4p5q6/snapshots \
-H "Authorization: Bearer {token}"
Response
{
"data": [
{
"id": "snap-v01",
"tracking_video_id": "v1d2e3o4-f5g6-h7i8-j9k0-l1m2n3o4p5q6",
"views": 84500000,
"likes": 6180000,
"comments": 30800,
"shares": 448000,
"bookmarks": 119000,
"snapshot_at": "2026-03-22T14:00:00.000Z",
"delta_views": null,
"delta_likes": null,
"delta_comments": null,
"delta_shares": null,
"delta_bookmarks": null
},
{
"id": "snap-v02",
"tracking_video_id": "v1d2e3o4-f5g6-h7i8-j9k0-l1m2n3o4p5q6",
"views": 85000000,
"likes": 6200000,
"comments": 31000,
"shares": 450000,
"bookmarks": 120000,
"snapshot_at": "2026-03-23T14:00:00.000Z",
"delta_views": 500000,
"delta_likes": 20000,
"delta_comments": 200,
"delta_shares": 2000,
"delta_bookmarks": 1000
}
]
}
Update tracked video
Update tracking configuration for a video. Changing the cadence recalculates the next_scrape_at timestamp.
Free
Request body
- Name
status- Type
- string
- Description
Set to
activeorpaused.
- Name
scrape_cadence- Type
- string
- Description
New scrape cadence. Each cycle costs $0.25.
Request
curl -X PATCH https://api.virlo.ai/v1/tracking/videos/v1d2e3o4-f5g6-h7i8-j9k0-l1m2n3o4p5q6 \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{ "status": "paused" }'
Response
{
"data": {
"id": "v1d2e3o4-f5g6-h7i8-j9k0-l1m2n3o4p5q6",
"status": "paused",
"scrape_cadence": "daily"
}
}
Stop tracking video
Stop tracking a video. Historical data (snapshots) is retained. The video will no longer appear in list results.
Free
Request
curl -X DELETE https://api.virlo.ai/v1/tracking/videos/v1d2e3o4-f5g6-h7i8-j9k0-l1m2n3o4p5q6 \
-H "Authorization: Bearer {token}"
Response
(empty response body)
Webhook notifications
Tracking events fire webhooks so you can react in real time — no polling needed. Subscribe to these events via the Webhooks API or your dashboard Integrations page.
| Event | When it fires |
|---|---|
tracking.cycle.completed | A creator or video tracking cycle finishes — new snapshot captured and AI report ready |
tracking.outlier_video.detected | A tracked creator publishes a video that significantly outperforms their median views (3x+ threshold) |
tracking.paused | Tracking is auto-paused after 3 consecutive scrape failures |
Cycle completed payloads include the latest snapshot metrics with deltas from the previous cycle, post count, and a direct dashboard link. For creators, outlier detection runs automatically — any video exceeding 3x the creator's median views triggers a separate tracking.outlier_video.detected event with the video URL, view count, outlier ratio, and weighted score.
Tracking webhooks fire through the same delivery infrastructure as other Virlo webhooks — same retry ladder, same custom headers, same delivery log. See Webhooks for full details.
Workflow Recipes
Creator Growth Monitoring
Track a creator and build a growth dashboard:
POST /v1/tracking/creatorswithscrape_cadence: "twelve_hours"— $0.25 (initial cycle starts immediately, collecting metrics + generating AI report)- Wait for initial cycle to complete (check
enrichment_status— will bereadywhen done) GET /v1/tracking/creators/:id/snapshotsperiodically to build growth charts — FreeGET /v1/tracking/creators/:id/reportto read the latest AI analysis — Free
Video Performance Tracking
Monitor how a video performs over its lifecycle:
POST /v1/tracking/videoswithscrape_cadence: "six_hours"— $0.25 (initial cycle starts immediately)GET /v1/tracking/videos/:id/snapshotsto track view velocity and engagement — FreeGET /v1/tracking/videos/:id/reportto read the latest AI analysis — FreePATCH /v1/tracking/videos/:idto reduce cadence once growth stabilizes — Free
Competitive Intelligence
Monitor multiple creators in your niche:
import requests
creators = ['creator1', 'creator2', 'creator3']
API_KEY = 'YOUR_API_KEY'
headers = {'Authorization': f'Bearer {API_KEY}'}
tracked_ids = []
for creator in creators:
response = requests.post(
'https://api.virlo.ai/v1/tracking/creators',
headers=headers,
json={
'platform': 'tiktok',
'handle': creator,
'scrape_cadence': 'daily'
}
)
tracked_ids.append(response.json()['data']['id'])
# Later, compare snapshots across creators
for tid in tracked_ids:
snapshots = requests.get(
f'https://api.virlo.ai/v1/tracking/creators/{tid}/snapshots',
headers=headers
).json()['data']
print(f"Creator {tid}: {len(snapshots)} snapshots")
Error Responses
- Name
400 Bad Request- Description
Invalid parameters. Common causes: missing required fields, invalid platform, invalid cadence value.
- Name
401 Unauthorized- Description
- Missing or invalid API key.
- Name
402 Payment Required- Description
Insufficient prepaid balance to perform this operation. Add funds at dev.virlo.ai/dashboard/billing. See Billing & Pricing.
- Name
404 Not Found- Description
Tracked creator or video not found, or does not belong to your team.
- Name
429 Too Many Requests- Description
Rate limit exceeded. Check
X-RateLimit-Resetheader for when to retry.
