Search videos
/v1/videos/searchKeyword search across TikTok, Instagram and YouTube, one page per call, plus Facebook when platforms names it (opt-in: the default stays the three). coverage reports each platform as complete, partial or failed; Instagram and Facebook results are best-effort and carry coverage: "partial", and Facebook results carry a view count only where Facebook shows one, and no other counts. A platform whose Source is unavailable is reported failed: source_unavailable, is not charged, and leaves the Run partial. intelligence: true analyses Facebook results like the others, at the same price. With intelligence: true the search runs in the request and the enrichment passes run as a workflow, so each enriched video becomes a RunItem with its own status and charge at GET /v1/runs/{id}/items. An enriched search that finds no videos completes with the empty page and is charged the search fee, like a plain search. A video longer than 10 minutes is not analysed or charged: its item fails with video_too_long, decided before the pass when the search reported its length, else when the pass reads the video. A TikTok photo carousel is analysed from its images, at the same price. A video that cannot be analysed comes back on the page with intelligence: null and intelligence_error saying why.
Open in Playground(no API Key needed)
Price
3 credits per platform searched, per page (9 credits for the default three). intelligence: true adds 20 credits for each of the top 20 results enriched, whether analysed now or already.
Supports "estimate": true in the body: the reply is the price in Credits and whether it would be cached, with no Run created and nothing charged.
A cached result costs the same as a fresh one; cached says which you got.
Parameters
| Name | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
Idempotency-Key | header | string | Optional | — | 1-255 printable ASCII characters. Replaying this key with the same payload returns the original Run (202 while it is still running); a different payload, or a different operation, is a 409 idempotency_conflict. |
Request body
application/json
object
querystringrequiredlength 1 to 200At most 200 characters.platformsarray of stringitems at least 1Omit for TikTok, Instagram and YouTube.facebookis opt-in: name it to search Facebook videos and Reels.regionstringlength 2 to 5windowstringone ofday,week,month,quarter,half_year,allsortstringone ofrelevance,likes,datelimitintegervalue 1 to 30cursorstringlength at least 1intelligencebooleanAnalyse the top 20 results.waitnumbervalue 0 to 120estimatebooleanWhen a source the call would read is unavailable and the answer is not served from cache, the estimate addsunavailable, the{ platform, capability }parts it cannot reach, or answers 503source_unavailablewhen it can reach none.
Responses
200 OK
The Run finished inside the wait budget: { run, result }. With estimate=true, { estimate_credits, cached } instead.
any of 2 shapes
Option 1object
runobjectrequiredEvery charged operation creates a Run. The envelope is identical whether the result came back inline or was polled.idstringrequiredkindstringrequiredWhat was run, e.g.video_lookup.statusstringrequiredone ofrunning,completed,partial,failedpartialkeeps the completed items and charges for them, up to what the Balance covers;failedcharges nothing.created_atstringrequiredRFC 3339.completed_atstringrequirednullableNull while the Run is still running.charge_creditsintegerrequiredWhat this Run actually cost, in Credits. A stored answer costs the same as a fresh one.list_price_creditsintegerrequiredThe full price of the work asked for, in Credits. Equal tocharge_creditsunless the Run charged for only part of it.cachedbooleanrequiredTrue when a stored result answered without paying the vendor.progressobjectWhat a running Research has done so far, refreshed as it works:stage(keywords,searching,filtering,analysing,writing_digest) and the counts known by then —keywords,found,kept,dropped_off_topic, andanalysedofshortlisted. A count is absent until its stage produced it. Absent once the Run settles, and on every other kind.stagestringrequiredone ofkeywords,searching,filtering,analysing,writing_digestkeywordsintegervalue at least 0searchesintegervalue at least 0foundintegervalue at least 0judgedintegervalue at least 0keptintegervalue at least 0dropped_off_topicintegervalue at least 0dropped_unsureintegervalue at least 0shortlistedintegervalue at least 0analysedintegervalue at least 0updated_atstringrequired
resultobjectrequireditemsarray of objectrequiredWithintelligence: true, the enriched videos carryintelligence, orintelligence: nullandintelligence_errorwhen they could not be analysed.platformstringrequiredidstringrequiredurlstringrequirednullabledescriptionstringrequiredposted_atstringrequirednullableduration_secondsnumberrequirednullablethumbnail_urlstringrequirednullablesoundobjectrequirednullableidstringrequiredtitlestringrequirednullable
creatorobjectrequirednullableidstringrequiredhandlestringrequirednullablenamestringrequiredfollower_countnumberrequirednullable
snapshotobjectrequirednullableatstringrequiredviewsnumberrequiredlikesnumberrequiredcommentsnumberrequiredsavesnumberrequired
scoresobjectrequirednullableNull when the creator has no baseline yet.outliernumberrequirednullableViews over the creator's median views.outlier_p90numberrequirednullablepercentilenumberrequirednullableWhere this video sits in the creator's own sample, 0-100.velocityobjectrequirednullableviews_per_hournumberrequiredwindowstringrequired
reasonstringrequirednullablealwaysaged_outaged_outwhen the video is over 30 days old and Scores are null.baselineobjectrequiredThe yardstick every Score on this creator is measured against.median_viewsnumberrequiredp90_viewsnumberrequiredengagement_ratenumberrequirednullableposts_per_weeknumberrequirednullablesampleintegerrequiredconfidencestringrequiredone ofhigh,lowsourcestringrequiredone ofvideos,follower_tiercomputed_atstringrequirednullablestalebooleanrequiredTrue past 7 days; the next lookup refreshes it.
coveragestringalwayspartialPresent only where the platform's index is best-effort.intelligenceobjectnullableThe analysis. Null when this video could not be analysed (uncharged); absent past the cap.versionintegerrequiredmodelstringrequiredcomputed_atstringrequiredsourcestringrequiredcontentobjectrequiredsummarystringrequirednichestringrequiredlanguagesarray of stringrequiredcontent_stylesarray of stringrequiredkeywordsarray of objectrequiredkeywordstringrequiredcategorystringrequiredsentimentnumberrequired
transcriptstringrequirednullable
hookobjectrequiredopening_linestringrequirednullabletypestringrequiredvisual_hookstringrequirednullablerationalestringrequirednullable
persuasionobjectrequiredcall_to_actionobjectrequiredtypestringrequiredtextstringrequirednullable
sponsoredbooleanrequiredsponsorship_signalsarray of stringrequiredbrands_and_productsarray of objectrequirednamestringrequiredkindstringrequiredprominencestringrequired
trend_referencesarray of objectrequirednamestringrequiredkindstringrequired
toneobjectrequiredsentiment_labelstringrequiredsentiment_scorenumberrequiredprimary_emotionstringrequiredemotion_intensitynumberrequirednullableemotion_rationalestringrequirednullablespeaking_stylestringrequiredspeaking_style_notesstringrequirednullable
visualobjectrequiredformatstringrequiredsettingstringrequiredface_visibilitystringrequiredon_screen_textarray of stringrequiredhas_on_screen_captionsbooleanrequiredcamera_notesstringrequirednullablelighting_notesstringrequirednullableelementsany
safetyobjectrequiredbrand_safety_tierstringrequiredreasonsarray of stringrequirednotesstringrequirednullable
intelligence_errorobjectWhyintelligenceis null.typestringrequiredtitlestringrequiredstatusintegerrequiredcodestringrequiredone ofmissing_authorization,invalid_key,key_revoked,invalid_token,organization_not_selected,organization_access_revoked,connection_revoked,forbidden,invalid_request,unsupported_platform,unsupported_kind,kind_deprecated,not_found,video_too_long,idempotency_conflict,run_not_ready,advertiser_ambiguous,insufficient_balance,rate_limit_exceeded,concurrency_limit_exceeded,tracker_limit_exceeded,webhook_limit_exceeded,webhook_rotation_in_progress,collection_limit_exceeded,collection_name_taken,collection_kind_mismatch,media_unavailable,vendor_error,source_unavailable,service_unavailable,internal_errorStable machine-readable code.detailstring
next_cursorstringrequirednullablecoveragemap of stringrequiredPer platform:complete,partial, orfailed: <code>.intelligenceobjectPresent only withintelligence: true. Per-video outcomes page atGET /v1/runs/{id}/items.requestedintegerrequiredcompletedintegerrequiredfailedintegerrequiredcapintegerrequired
Option 2objectReturned instead of a Run when
estimate=true. Nothing is charged. Operations with more to say about a quote add members; the two above are always present.estimate_creditsintegerrequiredWhat the call would be charged, in Credits.cachedbooleanrequiredWhether a stored result can already answer. It does not change the price.
200 · The Run finished inside the wait budget: `{ run, result }`. With `estimate=true`, `{ estimate_credits, cached }` instead.
{
"run": {
"id": "run_8f2c1ad04b",
"kind": "video_search",
"status": "completed",
"created_at": "2026-09-08T09:14:02.418Z",
"completed_at": "2026-09-08T09:14:04.930Z",
"charge_credits": 3,
"list_price_credits": 3,
"cached": false
},
"result": {
"items": [
{
"platform": "tiktok",
"id": "7300000000000000000",
"url": "https://www.tiktok.com/@someone/video/7300000000000000000",
"description": "3 minutes at 4°C every morning for 30 days. Here is what actually changed. #coldplunge #recovery",
"posted_at": "2026-09-05T06:32:11.000Z",
"duration_seconds": 41,
"thumbnail_url": "https://p16-sign.tiktokcdn.com/obj/tos-cover-7300000000000000000.jpeg",
"hashtags": [
"coldplunge",
"recovery",
"morningroutine"
],
"sound": {
"id": "7180000000000000000",
"title": "original sound - someone"
},
"creator": {
"id": "cre_9d4b2a7f1c",
"handle": "someone",
"name": "Someone",
"follower_count": 184300
},
"snapshot": {
"at": "2026-09-08T09:14:04.219Z",
"views": 1284000,
"likes": 143200,
"comments": 2810,
"shares": 9040,
"saves": 21600
},
"scores": null
},
{
"platform": "tiktok",
"id": "7300000000000000042",
"url": "https://www.tiktok.com/@anotherone/video/7300000000000000042",
"description": "I tried cold plunging before every workout for a week. #coldplunge",
"posted_at": "2026-09-06T13:04:52.000Z",
"duration_seconds": 28,
"thumbnail_url": "https://p16-sign.tiktokcdn.com/obj/tos-cover-7300000000000000042.jpeg",
"hashtags": [
"coldplunge",
"gym"
],
"sound": {
"id": "7180000000000000099",
"title": "Winter Air"
},
"creator": {
"id": "cre_1a77c0b3de",
"handle": "anotherone",
"name": "Another One",
"follower_count": 21400
},
"snapshot": {
"at": "2026-09-08T09:14:04.219Z",
"views": 96200,
"likes": 8140,
"comments": 212,
"shares": 401,
"saves": 1180
},
"scores": null
}
],
"next_cursor": "eyJ0aWt0b2siOiIzMCJ9",
"coverage": {
"tiktok": "complete"
}
}
}200 · With `estimate=true`: the price, no Run, no charge.
{
"estimate_credits": 3,
"cached": false
}202 Accepted
Still running: { run }. Poll GET /v1/runs/{id}.
object
Still running. Poll GET /v1/runs/{id}.
runobjectrequiredEvery charged operation creates a Run. The envelope is identical whether the result came back inline or was polled.idstringrequiredkindstringrequiredWhat was run, e.g.video_lookup.statusstringrequiredone ofrunning,completed,partial,failedpartialkeeps the completed items and charges for them, up to what the Balance covers;failedcharges nothing.created_atstringrequiredRFC 3339.completed_atstringrequirednullableNull while the Run is still running.charge_creditsintegerrequiredWhat this Run actually cost, in Credits. A stored answer costs the same as a fresh one.list_price_creditsintegerrequiredThe full price of the work asked for, in Credits. Equal tocharge_creditsunless the Run charged for only part of it.cachedbooleanrequiredTrue when a stored result answered without paying the vendor.progressobjectWhat a running Research has done so far, refreshed as it works:stage(keywords,searching,filtering,analysing,writing_digest) and the counts known by then —keywords,found,kept,dropped_off_topic, andanalysedofshortlisted. A count is absent until its stage produced it. Absent once the Run settles, and on every other kind.stagestringrequiredone ofkeywords,searching,filtering,analysing,writing_digestkeywordsintegervalue at least 0searchesintegervalue at least 0foundintegervalue at least 0judgedintegervalue at least 0keptintegervalue at least 0dropped_off_topicintegervalue at least 0dropped_unsureintegervalue at least 0shortlistedintegervalue at least 0analysedintegervalue at least 0updated_atstringrequired
202 · Example
{
"run": {
"id": "run_8f2c1ad04b",
"kind": "video_search",
"status": "running",
"created_at": "2026-09-08T09:14:02.418Z",
"completed_at": null,
"charge_credits": 0,
"list_price_credits": 0,
"cached": false
}
}400 Bad Request
invalid_request (a malformed id, wait, estimate or Idempotency-Key) or unsupported_platform, refused before any Run opens. Nothing is charged.
object
RFC 9457 problem document, served as application/problem+json. Branch on code, never on the prose.
typestringrequiredtitlestringrequiredstatusintegerrequiredcodestringrequiredone ofmissing_authorization,invalid_key,key_revoked,invalid_token,organization_not_selected,organization_access_revoked,connection_revoked,forbidden,invalid_request,unsupported_platform,unsupported_kind,kind_deprecated,not_found,video_too_long,idempotency_conflict,run_not_ready,advertiser_ambiguous,insufficient_balance,rate_limit_exceeded,concurrency_limit_exceeded,tracker_limit_exceeded,webhook_limit_exceeded,webhook_rotation_in_progress,collection_limit_exceeded,collection_name_taken,collection_kind_mismatch,media_unavailable,vendor_error,source_unavailable,service_unavailable,internal_errorStable machine-readable code.detailstring
400 · Example
{
"type": "https://www.shortsintel.com/docs/reference/errors/invalid_request",
"title": "Invalid request",
"status": 400,
"code": "invalid_request",
"detail": "`estimate` must be `true` or `false`."
}401 Unauthorized
missing_authorization, invalid_key, key_revoked or invalid_token.
object
RFC 9457 problem document, served as application/problem+json. Branch on code, never on the prose.
typestringrequiredtitlestringrequiredstatusintegerrequiredcodestringrequiredone ofmissing_authorization,invalid_key,key_revoked,invalid_token,organization_not_selected,organization_access_revoked,connection_revoked,forbidden,invalid_request,unsupported_platform,unsupported_kind,kind_deprecated,not_found,video_too_long,idempotency_conflict,run_not_ready,advertiser_ambiguous,insufficient_balance,rate_limit_exceeded,concurrency_limit_exceeded,tracker_limit_exceeded,webhook_limit_exceeded,webhook_rotation_in_progress,collection_limit_exceeded,collection_name_taken,collection_kind_mismatch,media_unavailable,vendor_error,source_unavailable,service_unavailable,internal_errorStable machine-readable code.detailstring
401 · Example
{
"type": "https://www.shortsintel.com/docs/reference/errors/invalid_key",
"title": "Invalid key",
"status": 401,
"code": "invalid_key",
"detail": "That API key does not exist. Keys look like `sk_live_...` and are created in the console."
}402 Payment Required
insufficient_balance — the Balance cannot cover the quoted price (the worst case for Research and enriched search). No Run is created and nothing is charged. A multi-item Run whose Balance runs short later charges its completed items up to the Balance and ends partial.
object
RFC 9457 problem document, served as application/problem+json. Branch on code, never on the prose.
typestringrequiredtitlestringrequiredstatusintegerrequiredcodestringrequiredone ofmissing_authorization,invalid_key,key_revoked,invalid_token,organization_not_selected,organization_access_revoked,connection_revoked,forbidden,invalid_request,unsupported_platform,unsupported_kind,kind_deprecated,not_found,video_too_long,idempotency_conflict,run_not_ready,advertiser_ambiguous,insufficient_balance,rate_limit_exceeded,concurrency_limit_exceeded,tracker_limit_exceeded,webhook_limit_exceeded,webhook_rotation_in_progress,collection_limit_exceeded,collection_name_taken,collection_kind_mismatch,media_unavailable,vendor_error,source_unavailable,service_unavailable,internal_errorStable machine-readable code.detailstring
402 · Example
{
"type": "https://www.shortsintel.com/docs/reference/errors/insufficient_balance",
"title": "Insufficient balance",
"status": 402,
"code": "insufficient_balance",
"detail": "Your balance does not cover this operation. Top up in the console.",
"balance_credits": 0,
"required_credits": 3
}409 Conflict
idempotency_conflict — the same Idempotency-Key with a different payload.
object
RFC 9457 problem document, served as application/problem+json. Branch on code, never on the prose.
typestringrequiredtitlestringrequiredstatusintegerrequiredcodestringrequiredone ofmissing_authorization,invalid_key,key_revoked,invalid_token,organization_not_selected,organization_access_revoked,connection_revoked,forbidden,invalid_request,unsupported_platform,unsupported_kind,kind_deprecated,not_found,video_too_long,idempotency_conflict,run_not_ready,advertiser_ambiguous,insufficient_balance,rate_limit_exceeded,concurrency_limit_exceeded,tracker_limit_exceeded,webhook_limit_exceeded,webhook_rotation_in_progress,collection_limit_exceeded,collection_name_taken,collection_kind_mismatch,media_unavailable,vendor_error,source_unavailable,service_unavailable,internal_errorStable machine-readable code.detailstring
409 · Example
{
"type": "https://www.shortsintel.com/docs/reference/errors/idempotency_conflict",
"title": "Idempotency conflict",
"status": 409,
"code": "idempotency_conflict",
"detail": "This Idempotency-Key was used with a different payload.",
"run_id": "run_8f2c1ad04b"
}429 Too Many Requests
rate_limit_exceeded or concurrency_limit_exceeded, with Retry-After.
object
RFC 9457 problem document, served as application/problem+json. Branch on code, never on the prose.
typestringrequiredtitlestringrequiredstatusintegerrequiredcodestringrequiredone ofmissing_authorization,invalid_key,key_revoked,invalid_token,organization_not_selected,organization_access_revoked,connection_revoked,forbidden,invalid_request,unsupported_platform,unsupported_kind,kind_deprecated,not_found,video_too_long,idempotency_conflict,run_not_ready,advertiser_ambiguous,insufficient_balance,rate_limit_exceeded,concurrency_limit_exceeded,tracker_limit_exceeded,webhook_limit_exceeded,webhook_rotation_in_progress,collection_limit_exceeded,collection_name_taken,collection_kind_mismatch,media_unavailable,vendor_error,source_unavailable,service_unavailable,internal_errorStable machine-readable code.detailstring
429 · Example
{
"type": "https://www.shortsintel.com/docs/reference/errors/rate_limit_exceeded",
"title": "Rate limit exceeded",
"status": 429,
"code": "rate_limit_exceeded",
"detail": "60 requests per minute per key. Retry after the number of seconds in `Retry-After`.",
"limit": 60
}502 Bad Gateway
A Run that opened and then failed is answered as application/problem+json with its problem's status — vendor_error here, not_found as 404 — and the Run envelope alongside, so the Run id is kept. A failed Run is never charged.
object
RFC 9457 problem document, served as application/problem+json. Branch on code, never on the prose.
typestringrequiredtitlestringrequiredstatusintegerrequiredcodestringrequiredone ofmissing_authorization,invalid_key,key_revoked,invalid_token,organization_not_selected,organization_access_revoked,connection_revoked,forbidden,invalid_request,unsupported_platform,unsupported_kind,kind_deprecated,not_found,video_too_long,idempotency_conflict,run_not_ready,advertiser_ambiguous,insufficient_balance,rate_limit_exceeded,concurrency_limit_exceeded,tracker_limit_exceeded,webhook_limit_exceeded,webhook_rotation_in_progress,collection_limit_exceeded,collection_name_taken,collection_kind_mismatch,media_unavailable,vendor_error,source_unavailable,service_unavailable,internal_errorStable machine-readable code.detailstring
502 · Example
{
"type": "https://www.shortsintel.com/docs/reference/errors/vendor_error",
"title": "Vendor error",
"status": 502,
"code": "vendor_error",
"detail": "The upstream data provider could not be reached.",
"run": {
"id": "run_8f2c1ad04b",
"kind": "video_search",
"status": "failed",
"created_at": "2026-09-08T09:14:02.418Z",
"completed_at": "2026-09-08T09:14:04.930Z",
"charge_credits": 0,
"list_price_credits": 0,
"cached": false
}
}503 Service Unavailable
source_unavailable: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; endpoints names the source. Retry later rather than treating it as empty.
object
RFC 9457 problem document, served as application/problem+json. Branch on code, never on the prose.
typestringrequiredtitlestringrequiredstatusintegerrequiredcodestringrequiredone ofmissing_authorization,invalid_key,key_revoked,invalid_token,organization_not_selected,organization_access_revoked,connection_revoked,forbidden,invalid_request,unsupported_platform,unsupported_kind,kind_deprecated,not_found,video_too_long,idempotency_conflict,run_not_ready,advertiser_ambiguous,insufficient_balance,rate_limit_exceeded,concurrency_limit_exceeded,tracker_limit_exceeded,webhook_limit_exceeded,webhook_rotation_in_progress,collection_limit_exceeded,collection_name_taken,collection_kind_mismatch,media_unavailable,vendor_error,source_unavailable,service_unavailable,internal_errorStable machine-readable code.detailstring
503 · Example
{
"type": "https://www.shortsintel.com/docs/reference/errors/source_unavailable",
"title": "Source unavailable",
"status": 503,
"code": "source_unavailable",
"detail": "The tiktok/video source is unavailable right now.",
"endpoints": [
"tiktok/video"
],
"run": {
"id": "run_8f2c1ad04b",
"kind": "video_search",
"status": "failed",
"created_at": "2026-09-08T09:14:02.418Z",
"completed_at": "2026-09-08T09:14:04.930Z",
"charge_credits": 0,
"list_price_credits": 0,
"cached": false
}
}Request samples
curl -X POST "https://www.shortsintel.com/v1/videos/search" \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"query":"cold plunge","platforms":["tiktok"],"limit":30,"sort":"likes"}'const response = await fetch(
"https://www.shortsintel.com/v1/videos/search",
{
method: "POST",
headers: {
"Authorization": "Bearer sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
"query": "cold plunge",
"platforms": [
"tiktok"
],
"limit": 30,
"sort": "likes"
}),
},
);
if (!response.ok) {
throw new Error(`ShortsIntel ${response.status}`);
}
const data = await response.json();import requests
response = requests.post(
"https://www.shortsintel.com/v1/videos/search",
headers={
"Authorization": "Bearer sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
json={
"query": "cold plunge",
"platforms": [
"tiktok",
],
"limit": 30,
"sort": "likes",
},
)
response.raise_for_status()
data = response.json()Related guides
This call creates a Run. With wait it holds the response open until the Run finishes or the wait runs out, then answers with the finished result or 202 and the running Run. Poll GET /v1/runs/{id} until it settles; re-reading a Run is free.
- Runs: How a call becomes a Run, waiting inline, polling and free re-reads.
- Pricing and estimates: Credits, estimates and why a cached result costs the same as a fresh one.
- Analysis: What we derive from a video, why it is computed once and reused, and when asking for a refresh is charged as new work.
- Scores: Outlier and velocity, how a creator baseline is built, what confidence means, and when a score stops being reported.