curl --request GET \
--url 'https://www.genviral.io/api/partner/v1/viral-library?q=cooking%20app&category=Food%20%26%20Cooking&limit=12' \
--header 'Authorization: Bearer <token>'
{
"ok": true,
"code": 200,
"message": "Viral library posts retrieved",
"data": {
"posts": [
{
"id": "viral-post-1",
"platform": "tiktok",
"content_type": "slideshow",
"link": "https://www.tiktok.com/@chefdesk/video/1",
"category": "Food & Cooking",
"business_type": "app",
"product_name": "Chef Desk",
"product_website": "https://chefdesk.example",
"account": "chefdesk",
"caption": "The 3 meals I batch on Sunday",
"hashtags": ["mealprep", "cookingapp"],
"date_published": "2026-07-14",
"metrics": {
"views": 412000,
"likes": 38000,
"comments": 900,
"shares": 1200,
"bookmarks": 5400
},
"slide_count": 6,
"preview_image_url": "https://cdn.example.com/viral/preview-1.jpg",
"image_urls": ["https://cdn.example.com/viral/slide-1.jpg"],
"video_url": null,
"hook_text": "I stopped cooking every night",
"hook_analysis": {
"content_class": "listicle",
"format_template": "problem-solution",
"psychology_tags": ["relief", "time-saving"]
},
"search_summary": "A batch-cooking app walkthrough told as a Sunday routine",
"niche": "meal planning",
"topics": ["batch cooking"],
"search_keywords": ["meal prep app"],
"ad_signal": null,
"creator_sponsored": false,
"language": "en",
"slide_texts": null,
"relevance": null
}
],
"total": 137,
"has_more": true,
"next_offset": 12
}
}
Viral Library
Search Viral Library
Search Genviral’s curated corpus of organic viral posts by idea, category, platform, account, or publish date
GET
/
api
/
partner
/
v1
/
viral-library
curl --request GET \
--url 'https://www.genviral.io/api/partner/v1/viral-library?q=cooking%20app&category=Food%20%26%20Cooking&limit=12' \
--header 'Authorization: Bearer <token>'
{
"ok": true,
"code": 200,
"message": "Viral library posts retrieved",
"data": {
"posts": [
{
"id": "viral-post-1",
"platform": "tiktok",
"content_type": "slideshow",
"link": "https://www.tiktok.com/@chefdesk/video/1",
"category": "Food & Cooking",
"business_type": "app",
"product_name": "Chef Desk",
"product_website": "https://chefdesk.example",
"account": "chefdesk",
"caption": "The 3 meals I batch on Sunday",
"hashtags": ["mealprep", "cookingapp"],
"date_published": "2026-07-14",
"metrics": {
"views": 412000,
"likes": 38000,
"comments": 900,
"shares": 1200,
"bookmarks": 5400
},
"slide_count": 6,
"preview_image_url": "https://cdn.example.com/viral/preview-1.jpg",
"image_urls": ["https://cdn.example.com/viral/slide-1.jpg"],
"video_url": null,
"hook_text": "I stopped cooking every night",
"hook_analysis": {
"content_class": "listicle",
"format_template": "problem-solution",
"psychology_tags": ["relief", "time-saving"]
},
"search_summary": "A batch-cooking app walkthrough told as a Sunday routine",
"niche": "meal planning",
"topics": ["batch cooking"],
"search_keywords": ["meal prep app"],
"ad_signal": null,
"creator_sponsored": false,
"language": "en",
"slide_texts": null,
"relevance": null
}
],
"total": 137,
"has_more": true,
"next_offset": 12
}
}
Search the viral library: Genviral’s curated corpus of organic TikTok, Instagram,
Threads, and YouTube Shorts posts that passed 10,000 views, kept with their
metrics, slide images, hook, and hook analysis.
Every post in the corpus is organic content from a real account, selected and
classified by Genviral. Nothing in it is generated, sponsored, or paid.
Search results do not contain spoken transcripts. Once a result is worth deeper
analysis, read that one script with
Get Viral Library Transcript.
The results budget is the one to plan around. A search is charged its requested
Searching by idea, not by keyword
q is a natural-language idea, not a keyword match. The corpus is indexed by
what a post is about, so cooking app finds meal-planning walkthroughs whose
captions never use either word, and skincare founder story finds a founder
talking about her product without saying “founder”.
Ordering follows from that: results are ordered by relevance whenever q is
present, and by newest otherwise. Set sort explicitly to override either
default.
Filters compose with q rather than replacing it. Narrowing by category,
business_type, platform, account, or the publish dates is almost always a
better way to find a specific post than paging deep into a broad query.
Query Parameters
string
A natural-language idea to search for, 1-200 characters — for example
cooking app, productivity app onboarding, skincare founder story. When set, results are ordered by relevance.string
One content category, for example
Food & Cooking, Technology, or Health & Wellness. See the
enum in the OpenAPI schema for the full list.string
What the post is selling:
app, ecommerce, saas, service, affiliate, creator, game,
book, other, or unclassified.string
tiktok, instagram, threads, or youtube (YouTube Shorts).string
slideshow, video, or mixed.string
Match posts whose account handle contains this text.
string
Match posts whose product name contains this text.
string
Comma-separated numeric App Store ids, up to 100. Returns only posts tied to any of these apps
through their App Store link, website or product name — the same association each post’s
product_app reports.number
Return only posts with at most this many slides. Range:
1-100.string
TikTok paid reach.
ads: posts TikTok served as ads. likely_or_ads: also posts whose creator
authorized Spark Ads or whose engagement looks like paid reach. not_ads: neither. Posts never
checked (every Instagram, Threads, and YouTube post) count as not ads.boolean
true returns only posts a brand paid a creator to make (a paid-partnership label, a disclosure
hashtag such as #ad, or a promo code); false hides them. Posts never checked count as not
sponsored.string
Content language: one or more ISO 639-1 codes, comma-separated (
en,es), up to 20. mul matches
bilingual posts, zxx posts with no spoken or written words, and und posts whose language could
not be determined. A post matches when its language is any of the codes.string
Earliest publish date, as a calendar date
YYYY-MM-DD. This is the day the post went out, not the
day Genviral captured it.string
Latest publish date, as a calendar date
YYYY-MM-DD. Must be at or after published_since.string
relevance, newest, latest_posted, most_views, most_likes, most_comments, or
most_slides. Defaults to relevance when q is set and newest otherwise.number
default:"12"
Posts per page. Range:
1-40.number
default:"0"
Posts to skip. Range:
0-960.Response
array
Matching posts, ordered by
sort.Show Viral Library Post Object
Show Viral Library Post Object
string
string
string
string | null
string
string | null
string | null
string | null
string | null
string | null
string[]
string | null
Calendar date,
YYYY-MM-DD.object
views, likes, comments, shares, and bookmarks, each a number or null where the
platform did not report it.number | null
string | null
string[]
Slide images, in order.
string | null
Present only when the clip is available for playback. Always
null for a YouTube Short: no
copy of a Short is stored, so play it from its link (or YouTube’s embedded player) and use
preview_image_url for its cover.string | null
The opening line the post leads with.
object | null
content_class, format_template, and psychology_tags.string | null
string | null
string[]
string[]
object | null
TikTok only.
status is ad (TikTok served the post as an ad) or likely_ad (evidence of paid
reach), with the reason. null when nothing points to paid reach or the post was never
checked.boolean | null
Whether a brand paid a creator to make the post.
null when the post was never checked.string | null
ISO 639-1 code,
mul (bilingual), zxx (no words) or und (undetermined). null when the
post was never checked.null
Always
null here. Read one post with Get Viral Library
Post for its slide texts.null
Reserved. The ranking score is not exposed.
number
Total posts matching the query, not the size of this page.
boolean
number | null
The
offset for the next page, or null on the last page and once the reachable window is
exhausted. At the reach cap a response can carry has_more: true alongside next_offset: null:
more posts match, but none of them are reachable on this query — narrow it with filters instead.Reach and rate limits
One query reaches at most 1,000 results:offset is capped at 960 and
limit at 40. total still reports the full match count, so a query whose
total runs into the thousands is a query to narrow, not a query to page
through. Add a category, a business_type, a platform, an account, or a
published_since/published_until window and search again.
Reads are rate limited per authenticated customer:
| Operation | Per minute | Per day | Results per day |
|---|---|---|---|
| Search | 20 | 200 | 2,000 |
| Get one post | 60 | 300 | — |
| Get one transcript | 30 | 100 | — |
limit before it runs — asking for 40 spends 40 whether or not 40 come back —
so the 2,000 rows a day are yours to spend on wide pages or on many narrow ones.
Request an honest limit rather than the maximum, and the budget lasts.
A ceiling also applies across all callers together — 300 searches, 900
single-post reads, and 300 transcript reads per minute — so a burst can be
throttled even while your own budget is intact. Every limit answers 429 with
error_code: "rate_limited" and a retry_after_seconds value. Wait that long
before retrying; retrying sooner consumes budget without returning results.
A 503 provider_unavailable means the limiter itself could not be reached.
The daily budget is counted centrally, so a request that cannot be counted is
refused rather than served. It is transient, and carries its own
retry_after_seconds.
curl --request GET \
--url 'https://www.genviral.io/api/partner/v1/viral-library?q=cooking%20app&category=Food%20%26%20Cooking&limit=12' \
--header 'Authorization: Bearer <token>'
{
"ok": true,
"code": 200,
"message": "Viral library posts retrieved",
"data": {
"posts": [
{
"id": "viral-post-1",
"platform": "tiktok",
"content_type": "slideshow",
"link": "https://www.tiktok.com/@chefdesk/video/1",
"category": "Food & Cooking",
"business_type": "app",
"product_name": "Chef Desk",
"product_website": "https://chefdesk.example",
"account": "chefdesk",
"caption": "The 3 meals I batch on Sunday",
"hashtags": ["mealprep", "cookingapp"],
"date_published": "2026-07-14",
"metrics": {
"views": 412000,
"likes": 38000,
"comments": 900,
"shares": 1200,
"bookmarks": 5400
},
"slide_count": 6,
"preview_image_url": "https://cdn.example.com/viral/preview-1.jpg",
"image_urls": ["https://cdn.example.com/viral/slide-1.jpg"],
"video_url": null,
"hook_text": "I stopped cooking every night",
"hook_analysis": {
"content_class": "listicle",
"format_template": "problem-solution",
"psychology_tags": ["relief", "time-saving"]
},
"search_summary": "A batch-cooking app walkthrough told as a Sunday routine",
"niche": "meal planning",
"topics": ["batch cooking"],
"search_keywords": ["meal prep app"],
"ad_signal": null,
"creator_sponsored": false,
"language": "en",
"slide_texts": null,
"relevance": null
}
],
"total": 137,
"has_more": true,
"next_offset": 12
}
}
Error Responses
401- authentication failed (missing, invalid, or revoked token)402 subscription_required- an active eligible subscription is required403 tier_not_allowed- the Scheduler tier cannot use the Partner API422- invalid query parameters, for example an unknowncategory, anoffsetabove960, or apublished_untilbeforepublished_since429 rate_limited- the per-customer request limit, the daily results budget, or the shared ceiling was reached; waitretry_after_secondsand retry503 provider_unavailable- the rate limiter was unreachable, so the request was refused rather than served uncounted; waitretry_after_secondsand retry
