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.


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

EndpointPrice
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-demographicsFree (cache read)
GET /v1/tracking/creators/:id/audience-geographyFree (cache read)
All other GET, PATCH, DELETE endpointsFree

POST/v1/tracking/creators

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.

Cost:

$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 url or handle is required.

  • Name
    handle
    Type
    string
    Description

    Creator handle (without @). Either url or handle is 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

POST
/v1/tracking/creators
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
      }
    ]
  }
}

GET/v1/tracking/creators

List tracked creators

Retrieve a paginated list of all tracked creators for the authenticated team.

Cost:

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, or instagram.

  • Name
    search
    Type
    string
    Description

    Search by handle or display name (case-insensitive partial match). E.g. ?search=gordon.

Request

GET
/v1/tracking/creators
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/v1/tracking/creators/:id

Get tracked creator

Get full details for a specific tracked creator including current metrics, tracking configuration, and enrichment status.

Cost:

Free

Path parameters

  • Name
    id
    Type
    string
    Required
    *
    Description

    The tracked creator ID returned when tracking was started.

Request

GET
/v1/tracking/creators/:id
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/v1/tracking/creators/:id/report

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.

Cost:

Free

Request

GET
/v1/tracking/creators/:id/report
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/v1/tracking/creators/:id/snapshots

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.

Cost:

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

GET
/v1/tracking/creators/:id/snapshots
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
    }
  ]
}

PATCH/v1/tracking/creators/:id

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.

Cost:

Free

Request body

  • Name
    status
    Type
    string
    Description

    Set to active or paused.

  • 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

PATCH
/v1/tracking/creators/:id
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"
  }
}

DELETE/v1/tracking/creators/:id

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.

Cost:

Free

Request

DELETE
/v1/tracking/creators/:id
curl -X DELETE https://api.virlo.ai/v1/tracking/creators/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer {token}"

Response

(empty response body)

GET/v1/tracking/creators/:id/posts

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.

Cost:

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

GET
/v1/tracking/creators/:id/posts
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/v1/tracking/creators/:id/posts/:post_id

Get creator post

Get full details for a single creator post including all available metrics.

Cost:

Free

Request

GET
/v1/tracking/creators/:id/posts/:post_id
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"
  }
}

POST/v1/tracking/creators/:id/posts/collect

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.

Cost:

$0.50 – $2.00 (varies by depth)

Depth Tiers

TierMax VideosCost
standard50$0.50
deep200$1.00
full500$2.00

Request body

  • Name
    depth
    Type
    string
    Description

    Collection depth tier: standard (default), deep, or full.

Request

POST
/v1/tracking/creators/:id/posts/collect
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/v1/tracking/creators/:id/posts/collect/:collection_id

Get collection status

Poll the status of a post collection job. Status will be processing, completed, or failed.

Cost:

Free

Request

GET
/v1/tracking/creators/:id/posts/collect/:collection_id
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/v1/tracking/creators/:id/posting-cadence

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).

Cost:

Free

Request

GET
/v1/tracking/creators/:id/posting-cadence
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/v1/tracking/creators/:id/audience-demographics

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.

Cost:

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 returns null data.

Request

GET
/v1/tracking/creators/:id/audience-demographics
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/v1/tracking/creators/:id/audience-geography

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.

Cost:

Free

Query parameters

  • Name
    freshness_days
    Type
    integer
    Description

    Max age of an acceptable cached snapshot, in days. Default 30.

Request

GET
/v1/tracking/creators/:id/audience-geography
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": []
  }
}

POST/v1/tracking/creators/:id/audience-refresh

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.

Cost:

$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. Use 0 to 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

POST
/v1/tracking/creators/:id/audience-refresh
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": []
  }
}

GET/v1/tracking/creators/:id/audience-refresh/:jobId

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.

Cost:

Free

Request

GET
/v1/tracking/creators/:id/audience-refresh/:jobId
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"
    }
  }
}

POST/v1/tracking/videos

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.

Cost:

$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, or instagram.

  • 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

POST
/v1/tracking/videos
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."
  }
}

GET/v1/tracking/videos

List tracked videos

Retrieve a paginated list of all tracked videos for the authenticated team.

Cost:

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, or instagram.

  • Name
    search
    Type
    string
    Description

    Search by video title or URL (case-insensitive partial match). E.g. ?search=pancake.

Request

GET
/v1/tracking/videos
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/v1/tracking/videos/:id

Get tracked video

Get full details for a specific tracked video including current metrics and tracking configuration.

Cost:

Free

Request

GET
/v1/tracking/videos/:id
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/v1/tracking/videos/:id/report

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).

Cost:

Free

Request

GET
/v1/tracking/videos/:id/report
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/v1/tracking/videos/:id/snapshots

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.

Cost:

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

GET
/v1/tracking/videos/:id/snapshots
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
    }
  ]
}

PATCH/v1/tracking/videos/:id

Update tracked video

Update tracking configuration for a video. Changing the cadence recalculates the next_scrape_at timestamp.

Cost:

Free

Request body

  • Name
    status
    Type
    string
    Description

    Set to active or paused.

  • Name
    scrape_cadence
    Type
    string
    Description

    New scrape cadence. Each cycle costs $0.25.

Request

PATCH
/v1/tracking/videos/:id
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"
  }
}

DELETE/v1/tracking/videos/:id

Stop tracking video

Stop tracking a video. Historical data (snapshots) is retained. The video will no longer appear in list results.

Cost:

Free

Request

DELETE
/v1/tracking/videos/:id
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.

EventWhen it fires
tracking.cycle.completedA creator or video tracking cycle finishes — new snapshot captured and AI report ready
tracking.outlier_video.detectedA tracked creator publishes a video that significantly outperforms their median views (3x+ threshold)
tracking.pausedTracking 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.


Workflow Recipes

Creator Growth Monitoring

Track a creator and build a growth dashboard:

  1. POST /v1/tracking/creators with scrape_cadence: "twelve_hours" — $0.25 (initial cycle starts immediately, collecting metrics + generating AI report)
  2. Wait for initial cycle to complete (check enrichment_status — will be ready when done)
  3. GET /v1/tracking/creators/:id/snapshots periodically to build growth charts — Free
  4. GET /v1/tracking/creators/:id/report to read the latest AI analysis — Free

Video Performance Tracking

Monitor how a video performs over its lifecycle:

  1. POST /v1/tracking/videos with scrape_cadence: "six_hours" — $0.25 (initial cycle starts immediately)
  2. GET /v1/tracking/videos/:id/snapshots to track view velocity and engagement — Free
  3. GET /v1/tracking/videos/:id/report to read the latest AI analysis — Free
  4. PATCH /v1/tracking/videos/:id to 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-Reset header for when to retry.

Was this page helpful?