Workflow recipes

Code for five research questions, with the cost and time of each. Replace YOUR_API_KEY with your key.

At a glance
What it does
Answers one research question per recipe, call by call.
You send
A topic, a creator's handle, or a hashtag.
You get back
An AI report, top videos, ads, standout creators, trends, or hashtag stats.
Cost
$0.15 to $1.25 per recipe as written, before add-ons. A recurring agent then costs $0.50 per run until you pause or delete it. Reading an agent's videos, ads, creators, and report is free; hashtag and trend lists charge every time. A successful response's X-Cost header shows its cost.

An agent (Content Research Agent) collects matching videos and writes an AI report, once or on a schedule. A lookup checks one creator, video, sound, or hashtag.


Full niche analysis

A one-time agent searches TikTok, YouTube, Instagram, and Meta ads, then reports what is working.

At a glance
Cost
$0.50, charged when you create the agent, even if the run fails. $1.50 with Data Intelligence: AI notes on hook and format for many, not all, videos.
How long
Half of all runs are done in under 8 minutes, and 9 in 10 in under 20. Broad runs like this take longer.

1. Create a one-time agent ($0.50)

Describe what you want (intent) and add keywords, or get them free from Suggest keywords.

Create agent

POST
/v1/agents
curl -X POST https://api.virlo.ai/v1/agents \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "is_recurring": false,
    "intent": "Find what is working in Jeep Wrangler mods content right now",
    "name": "Jeep Wrangler Mods Research",
    "keywords": ["jeep wrangler mods", "jeep wrangler accessories", "jeep upgrades"],
    "platforms": ["youtube", "tiktok", "instagram"],
    "meta_ads_enabled": true
  }'

2. Wait until it's done (free)

Check again every 30 seconds until finalized is true (report written) and last_run_at is set (creators scored). A partial_failure run (one keyword or platform failed) is still usable; a failed run is not.

Check status

GET
/v1/agents/:id
deadline = time.time() + 60 * 60  # stop waiting after an hour (rare)
while True:
    agent = requests.get(
        f'https://api.virlo.ai/v1/agents/{agent_id}',
        headers={'Authorization': 'Bearer YOUR_API_KEY'}
    ).json()['data']

    if agent['latest_run']['status'] == 'failed':
        raise Exception('The run failed.')
    # finalized: videos collected and the AI report written
    #   (latest_run.status "completed" alone only means videos are collected).
    # last_run_at: set about a minute later, when creator scoring is done.
    if agent['finalized'] and agent['last_run_at']:
        break
    if time.time() > deadline:
        # Check again later. Creating a new agent would charge you again.
        raise TimeoutError('Still running after an hour.')

    print(f"{agent['stage']}: {agent['progress_pct']}%")  # e.g. "collecting: 40%"
    time.sleep(30)

# analysis is only the headline. The full report (themes, tactics, posting times,
# top 10 videos) is in analysis_data, also at GET /v1/agents/:id/analysis/latest.
report = agent['analysis_data'] or {}
print(agent['analysis'])  # the main takeaway, in one or two sentences
for theme in report.get('themes', []):
    print(f"- {theme['name']}: {theme['why_it_works']}")

# Example output, from a latte art agent:
# The most impactful insight for creators is the overwhelming success of 'progress journey' content, ...
# - Progress Journey Latte Art: Documenting daily or incremental improvements creates a relatable narrative, ...

Or use the content_research_agent.run.completed webhook. It can arrive up to a minute before creator scoring ends, so check last_run_at first.

3. Read the results (free)

Standout creators get far more views than their follower count predicts.

Read results

# Free, including the filters (min_views, start_date, end_date, platforms, region).

# The 50 most-viewed videos
videos = requests.get(
    f'https://api.virlo.ai/v1/agents/{agent_id}/videos',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
    params={'limit': 50, 'order_by': 'views', 'sort': 'desc'}
).json()['data']['videos']

# Meta ads (needs meta_ads_enabled at create time)
ads = requests.get(
    f'https://api.virlo.ai/v1/agents/{agent_id}/ads',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
    params={'limit': 50}
).json()['data']['ads']

# Standout creators ("creator outliers"), best Virality Score first.
# weighted_score = ln(avg_views / followers) x ln(followers)
# 35+ exceptional, 25-35 very strong, 18-25 strong, 10-18 promising
outliers = requests.get(
    f'https://api.virlo.ai/v1/agents/{agent_id}/creators/outliers',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
    params={'limit': 20, 'order_by': 'weighted_score', 'sort': 'desc'}
).json()['data']['outliers']

for creator in outliers[:5]:
    print(f"{creator['platform']}: {creator['follower_count']:,} followers, "
          f"{creator['avg_views']:,.0f} avg views, score {creator['weighted_score']}")
    print(f"  {creator['creator_url']}")

# Example output:
# instagram: 1,791 followers, 475,807 avg views, score 41.81
#   https://www.instagram.com/...

4. Optional: profile a creator ($0.50 to $1.00)

Run the Creator deep dive on their handle ($0.50, or $1.00 with its step 2). TikTok and Instagram creator_urls end with the handle; on YouTube, open the link and copy the @handle.

for creator in outliers[:3]:
    handle = creator['creator_url'].rstrip('/').split('/')[-1].lstrip('@')
    # On YouTube this is often a channel ID (/channel/UC...), not a handle.
    print(creator['platform'], handle)  # tiktok outside.kev

Creator deep dive

Size up a creator, then see if their top recent video is a real breakout.

At a glance
Cost
$1.00: $0.50 per lookup, charged when it starts. A failed creator lookup, such as for a handle that doesn't exist, is refunded; a failed video check isn't.
How long
About a minute. Each lookup usually takes 20 to 40 seconds.

1. Look up the creator ($0.50)

Creator lookup

GET
/v1/satellite/creator/:platform/:username
curl "https://api.virlo.ai/v1/satellite/creator/tiktok/khaby.lame?include=videos,outliers&max_videos=20" \
  -H "Authorization: Bearer YOUR_API_KEY"

2. Check their top recent video ($0.50)

This checks the most-viewed of the 20 recent videos the lookup read, not necessarily their all-time top.

Video outlier check

POST
/v1/satellite/video-outlier
# The most-viewed of the recent videos the lookup read
top_video = max(creator['videos'], key=lambda v: v['views'])

response = requests.post(
    'https://api.virlo.ai/v1/satellite/video-outlier',
    headers={'Authorization': 'Bearer YOUR_API_KEY'},
    json={'url': top_video['url'], 'platform': 'tiktok'}
)
video_job_id = response.json()['data']['job_id']

while True:
    result = requests.get(
        f'https://api.virlo.ai/v1/satellite/video-outlier/status/{video_job_id}',
        headers={'Authorization': 'Bearer YOUR_API_KEY'}
    ).json()['data']

    if result['status'] == 'completed':
        break
    if result['status'] == 'failed':
        raise Exception(result['error'])
    time.sleep(10)

analysis = result['result']['analysis']
print(f"Outlier score: {analysis['outlier_score']}")    # views / the creator's median views
print(f"Percentile: {analysis['percentile']}")          # % of their recent videos it beat
print(f"Label: {analysis['performance_label']}")        # average | above_average | viral | mega_viral

# Both results are saved. Reopen either for free with GET /v1/satellite/runs/{job_id},
# so keep both IDs. A new paid lookup of the same creator gets its own ID; old runs stay.

outlier_score is views divided by the creator's median views (up to 100 recent videos): mega_viral is 10x or more, viral 3 to 10x, above_average 1.5 to 3x, average under 1.5x.


Trend monitoring setup

Find today's trends, research one, then keep watching it with a recurring agent.

At a glance
Cost
$1.25 to start ($0.25 trends, $0.50 one-time agent, $0.50 first recurring run), or $0.75 without the one-time agent. Then $0.50 per run.
How long
Seconds, plus one agent run (up to about 20 minutes).

1. Get today's trends ($0.25)

Worldwide trends, unless you add region=us (or gb, au, sg).

Get trends

GET
/v1/trends/digest
import requests

API = 'https://api.virlo.ai/v1'
headers = {'Authorization': 'Bearer YOUR_API_KEY'}

digest = requests.get(f'{API}/trends/digest', headers=headers).json()['data']

for group in digest:
    print(group['local_date'])  # the list's date. Don't use 'title', which can be a day off.
    for item in group['trends']:
        print(f"  #{item['ranking']}: {item['trend']['name']}")

2. Research one trend ($0.50)

Get free keyword ideas and start a one-time agent, then read results as in the Full niche analysis.

Research a Trend

POST
/v1/agents
trend_name = digest[0]['trends'][0]['trend']['name']  # or pick one from the list
intent = f'Find what is working in short videos about {trend_name}'

# Keyword ideas (free)
suggestion = requests.post(
    f'{API}/agents/suggest-keywords',
    headers=headers,
    json={'intent': intent}
).json()['data']
# Before you pay for a run, check that suggestion['quality']['passes'] is True.

# One-time agent ($0.50). Optional: skip it to start at $0.75, but keep the keyword ideas.
agent = requests.post(
    f'{API}/agents',
    headers=headers,
    json={
        'is_recurring': False,
        'intent': intent,
        'keywords': suggestion['keywords'],
        'exclude_keywords': suggestion['exclude_keywords'],  # words that point to other topics
    }
).json()['data']
agent_id = agent['id']

3. Keep watching it ($0.50 per run)

Create a new agent with is_recurring: true and a cadence: daily, weekly, monthly, or a custom schedule (cron format), at most once a day.

Creating it is free, but its first run starts at once. Each run costs $0.50 when it finishes. A partial_failure run is charged; a failed run isn't. These charges aren't in any header, so check your balance. To stop them, pause (Update agent, active: false) or delete the agent.

Create recurring agent

POST
/v1/agents
# Your balance must cover the first run ($0.50), or this returns a 402 error.
monitor = requests.post(
    f'{API}/agents',
    headers=headers,
    json={
        'is_recurring': True,
        'cadence': 'weekly',  # runs early each Sunday, UTC
        'name': f'Weekly watch: {trend_name}',
        'intent': intent,
        'keywords': suggestion['keywords'],
        'exclude_keywords': suggestion['exclude_keywords'],
    }
).json()['data']

print(f"Agent ID: {monitor['id']}")
print(f"Next scheduled run: {monitor['next_run_at']}")  # the first run has already started

Hashtag research

See which hashtags had the most-viewed videos posted in the last 30 days.

At a glance
Cost
$0.05 per call: $0.15 for steps 1 to 3, or $0.25 adding YouTube and Instagram. Empty lists are billed; a hashtag with no videos (404) is free.
How long
A few seconds per call.

Numbers count only videos Virlo has collected, so compare hashtags with each other, not with platform totals.

1. Top hashtags ($0.05)

Top lists need both dates (YYYY-MM-DD, at most 90 days apart). Views are the current totals of videos posted in that range.

Top hashtags

GET
/v1/hashtags
import requests
from datetime import date, timedelta

headers = {'Authorization': 'Bearer YOUR_API_KEY'}
end = date.today().isoformat()
start = (date.today() - timedelta(days=30)).isoformat()

hashtags = requests.get(
    'https://api.virlo.ai/v1/hashtags',
    headers=headers,
    params={'start_date': start, 'end_date': end, 'limit': 20, 'order_by': 'views', 'sort': 'desc'}
).json()['data']

# Generic tags like #fyp lead. Hashtags come back lowercase, without the #.
for tag in hashtags[:5]:
    print(f"#{tag['hashtag']}: {tag['count']:,} videos, {tag['total_views']:,} views")

2. One hashtag's numbers ($0.05)

Skip the dates for all-time numbers.

Hashtag performance

GET
/v1/hashtags/:hashtag/performance
perf = requests.get(
    'https://api.virlo.ai/v1/hashtags/fyp/performance',  # no # in the path
    headers=headers,
    params={'start_date': start, 'end_date': end}
).json()['data']

print(f"#fyp: {perf['video_count']:,} videos, {perf['total_views']:,} views, avg {perf['avg_views']:,.0f} views/video")

3. Top hashtags on one platform ($0.05)

Top TikTok hashtags

GET
/v1/tiktok/hashtags
# YouTube and Instagram: /v1/youtube/hashtags and /v1/instagram/hashtags
tiktok = requests.get(
    'https://api.virlo.ai/v1/tiktok/hashtags',
    headers=headers,
    params={'start_date': start, 'end_date': end, 'limit': 10, 'order_by': 'views', 'sort': 'desc'}
).json()['data']

for tag in tiktok[:3]:
    print(f"#{tag['hashtag']}: {tag['count']:,} videos, {tag['total_views']:,} views")

# Example output (videos posted Aug 25 to Sep 23, 2026):
# #fyp: 31,049 videos, 5,162,705,739 views
# #viral: 9,971 videos, 1,693,054,907 views
# #funny: 4,276 videos, 1,242,478,023 views

For a hashtag's videos, use a hashtag lookup ($0.50 to $2.50).


Research in another language or country

Research a niche in any language, then narrow results to one country.

At a glance
Cost
$0.50, charged when you create the agent ($1.50 with Data Intelligence). Country filters are free.
How long
The same as a Full niche analysis.
  1. Set english_only: false when you create the agent, or it keeps only English. Write the name, intent, and keywords in your language; Virlo builds its search terms in that language. English may still appear (there's no language filter).
  2. region when you read results: a two-letter code like MX, any case. Mexico returns no results, not an error.

1. Create an all-languages agent ($0.50)

Create agent

POST
/v1/agents
curl -X POST https://api.virlo.ai/v1/agents \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "is_recurring": false,
    "intent": "Investigar el contenido viral de fútbol en Latinoamérica",
    "name": "Fútbol LATAM",
    "keywords": ["goles de fútbol", "jugadas de fútbol", "resumen de partido"],
    "platforms": ["tiktok", "instagram"],
    "english_only": false
  }'

2. Wait, then filter by country (free)

Videos carry the country as upload_region, slideshows as region; both are null when unknown.

Filter by region

GET
/v1/agents/:id/videos
# Videos uploaded from Mexico
curl -G https://api.virlo.ai/v1/agents/{agent_id}/videos \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d region=MX \
  -d order_by=views \
  -d sort=desc \
  -d limit=50

# Slideshows uploaded from Argentina
curl -G https://api.virlo.ai/v1/agents/{agent_id}/slideshows \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d region=AR \
  -d limit=50

Was this page helpful?