{"openapi":"3.1.0","info":{"title":"ShortsIntel Intelligence API","version":"1.0.0","summary":"Short-form video intelligence for agents: search, enrich, score and track TikTok, Instagram Reels and YouTube Shorts.","description":"Every charged operation creates a **Run**; free reads and edits (a balance, a rename, a deletion) answer directly and create none. A call holds the response open for `wait` seconds (default 30, max 120); if the work finishes in time you get `{ run, result }`, and if it does not you get `{ run }` with status `running` to poll at `GET /v1/runs/{id}`. The envelope is the same either way, and re-reading a Run is always free.\n\nPricing is per operation and prepaid. `estimate=true` on any paid operation returns the price without creating a Run or charging anything. Before any work starts, the Balance is checked against the operation's quoted price (for Research and enriched searches, the worst-case quote). If it cannot cover that, the call is a `402 insufficient_balance` and no Run is created or charged. A multi-item Run (Research, enriched search) settles per item when it finishes. If the Balance no longer covers every completed item, the completed items are charged in order up to the Balance, the rest fail with `insufficient_balance`, and the Run ends `partial`. A Run that cannot afford any of its work ends `failed` and is not charged.\n\nEvery operation carries `x-price: { credits, unit, max_credits }`: `credits` per `unit` (`call`, `page`, `platform_page`, `video`, `ad` or `cycle`), 0 when the operation is free; `max_credits` is the most one call can charge with every opt-in at its limit, or null when that depends on what the call finds. The **Price** line in each description has the details.\n\nWebhooks are signed: see the `webhooks` section and the `X-ShortsIntel-Signature` header.\n\nErrors are `application/problem+json` with a stable `code`. Branch on the code.\n\nLimits are 60 requests per minute per key and 10 concurrent running Runs per Customer.\n\nQuestions: support@shortsintel.com.","contact":{"name":"ShortsIntel","email":"support@shortsintel.com"},"termsOfService":"https://www.shortsintel.com/terms"},"servers":[{"url":"https://www.shortsintel.com/v1","description":"Production"}],"tags":[{"name":"Research","description":"One intent in plain language, a Digest back: themes, hooks that work verbatim, sentiment, recommended angles, and the ranked videos, creators, hashtags and sounds behind them."},{"name":"Breakdowns","x-displayName":"Creator Breakdown","description":"What works for a set of Creators: a Research seeded with Creators, each Video scored against its own Creator's median. Reads answer as their Research counterparts."},{"name":"Videos","description":"Search, look up, enrich, score and read the comments of short-form videos across TikTok, Instagram Reels and YouTube Shorts."},{"name":"Creators","description":"Creator profiles, their stored videos, their baseline metrics and their follower history."},{"name":"Hashtags","description":"Hashtag stats, trend direction and the videos carrying a tag."},{"name":"Sounds","description":"Sound and music metadata, usage counts and the videos using a track."},{"name":"Keywords","description":"What a platform's search shows for a phrase: sample stats, trend direction and the top videos."},{"name":"Ads","description":"Keyword and advertiser search over the Meta and TikTok ad libraries."},{"name":"Trackers","description":"Daily watches on a creator, a hashtag, a sound, a keyword (a search phrase on one Platform) or a Meta or TikTok Advertiser, with Snapshots kept forever and a Change Report only when something notable moves. Creator, hashtag, sound, keyword and advertiser Trackers are the kinds available today."},{"name":"Collections","description":"Named sets of Trackers of one kind, such as Competitors or Our accounts. A Tracker can sit in several and is still charged once per cycle; a Collection holds no state of its own."},{"name":"Runs","description":"Every charged operation creates a Run; free reads and edits do not. Re-read one to poll a long operation or to fetch a result you already paid for; re-reads are always free."},{"name":"Account","description":"Prepaid balance and the spend log."},{"name":"Webhooks","description":"Signed HTTP callbacks for `run.completed` and `tracker.changed`, with a delivery log and replay. The signature header, event types and payload are described under 'Webhook delivery and verification' in llms-full.txt and in the OpenAPI `webhooks` section."}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from the console, sent as `Authorization: Bearer sk_live_…`. Keys are shown once, are revocable, and may carry an expiry. A read-only key makes free reads and `estimate=true` quotes only; anything else is 403 `key_scope_insufficient`. The MCP endpoint additionally accepts OAuth 2.1."}},"headers":{"XRequestId":{"description":"The id of this request, to quote to support. Echoes your `X-Request-Id` when it is 1-128 characters of `[A-Za-z0-9._:-]`; otherwise a generated `req_` id. Problem bodies carry it as `request_id`.","schema":{"type":"string"}},"CacheControl":{"description":"Never cache or replay a response: calls can charge.","schema":{"type":"string","const":"no-store"}},"RateLimit":{"description":"Where this request leaves you against the request limit: `limit=60, remaining=<requests left>, reset=<seconds until the window resets>`. Absent when the request never reached the limit check (a 401) or the limiter was unavailable.","schema":{"type":"string"}},"RateLimitPolicy":{"description":"The request limit: `60;w=60`, 60 requests per 60-second window per key (per user for OAuth). Sent alongside `RateLimit`.","schema":{"type":"string"}},"RetryAfter":{"description":"Seconds to wait before retrying. The body carries the same number as `retry_after_seconds`, so a caller that sees only the body (MCP) backs off the same way.","schema":{"type":"integer","minimum":0}},"PollLocation":{"description":"Where to poll the Run: `/v1/runs/{id}`.","schema":{"type":"string"}},"PollRetryAfter":{"description":"Seconds to wait before the next poll; 5 today.","schema":{"type":"integer","minimum":0}}},"schemas":{"Run":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","description":"What was run, e.g. `video_lookup`."},"status":{"type":"string","enum":["running","completed","partial","failed"],"description":"`partial` keeps the completed items and charges for them, up to what the Balance covers; `failed` charges nothing."},"created_at":{"type":"string","description":"RFC 3339."},"completed_at":{"type":["string","null"],"description":"Null while the Run is still running."},"charge_credits":{"type":"integer","description":"What this Run actually cost, in Credits. A stored answer costs the same as a fresh one."},"list_price_credits":{"type":"integer","description":"The full price of the work asked for, in Credits. Equal to `charge_credits` unless the Run charged for only part of it."},"cached":{"type":"boolean","description":"True when a stored result answered without a fresh fetch."},"progress":{"type":"object","properties":{"stage":{"type":"string","enum":["keywords","searching","reading_creators","filtering","analysing","writing_digest"]},"keywords":{"type":"integer","minimum":0},"creators":{"type":"integer","minimum":0},"creators_read":{"type":"integer","minimum":0},"searches":{"type":"integer","minimum":0},"found":{"type":"integer","minimum":0},"judged":{"type":"integer","minimum":0},"kept":{"type":"integer","minimum":0},"dropped_off_topic":{"type":"integer","minimum":0},"dropped_unsure":{"type":"integer","minimum":0},"shortlisted":{"type":"integer","minimum":0},"analysed":{"type":"integer","minimum":0},"updated_at":{"type":"string"}},"required":["stage","updated_at"],"description":"What a running Research has done so far, refreshed as it works: its `stage` and the counts known by then, such as `analysed` of `shortlisted`. A count is absent until its stage produced it. Absent once the Run settles, and on every other kind."}},"required":["id","kind","status","created_at","completed_at","charge_credits","list_price_credits","cached"],"description":"Every charged operation creates a Run. The envelope is identical whether the result came back inline or was polled."},"RunEnvelope":{"type":"object","properties":{"run":{"$ref":"#/components/schemas/Run"}},"required":["run"],"description":"The envelope every charged operation answers with: `{ run }` while the Run is running (plus `poll_url` on the 202), joined by `result` once it completes or `error` once it fails."},"RunningEnvelope":{"description":"Still running. Poll `poll_url` (`GET /v1/runs/{id}`), waiting the 202's `Retry-After` seconds between polls.","allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"poll_url":{"type":"string","format":"uri","description":"Absolute URL of `GET /v1/runs/{id}` for this Run, the body's copy of the 202's `Location` header for callers that never see headers (MCP). Present only while the Run is `running`."}},"required":["poll_url"]}]},"Estimate":{"type":"object","properties":{"estimate_credits":{"type":"integer","description":"What the call would be charged, in Credits."},"cached":{"type":"boolean","description":"Whether a stored result can already answer. It does not change the price."}},"required":["estimate_credits","cached"],"additionalProperties":true,"description":"Returned 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."},"Problem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string","enum":["missing_authorization","invalid_key","key_revoked","key_expired","invalid_token","organization_not_selected","organization_access_revoked","connection_revoked","forbidden","key_scope_insufficient","invalid_request","unsupported_platform","unsupported_kind","kind_deprecated","focus_unsupported_kind","not_found","comment_not_found","video_too_long","idempotency_conflict","run_not_ready","advertiser_ambiguous","insufficient_balance","max_credits_exceeded","key_spend_cap_exceeded","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_error"],"description":"Stable machine-readable code."},"detail":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string","description":"Dotted path of the field to fix, e.g. `collection_ids.1` or `cursor`. Empty for an issue with the request body as a whole."},"message":{"type":"string","description":"What is wrong with that field."}},"required":["path","message"]},"description":"On `invalid_request` from a field that failed validation: one entry per problem, so you can find the field without parsing `detail`. Absent when no single field is at fault, e.g. a body that is not JSON."},"request_id":{"type":"string","description":"The request this problem answers, the same as its `X-Request-Id` header. Quote it to support."},"retryable":{"type":"boolean","description":"Whether sending the same request again, after any wait named here, can succeed: `true` for a rate or concurrency limit, an upstream outage, an internal error or a Run not yet settled; `false` when the request must change or a person must act. Fixed per `code`."},"action":{"type":"string","description":"The next step, in one sentence."},"remedy":{"type":"string","description":"What to do next, as the code's error reference page says it; fuller than `action`. On every problem a request answers with; a per-item `error` inside a result may omit it."},"retry_after_seconds":{"type":"integer","minimum":0,"description":"Seconds to wait before retrying; the same as the `Retry-After` header. On `rate_limit_exceeded`, `concurrency_limit_exceeded`, `source_unavailable` and `service_unavailable`."},"expired_at":{"type":"string","description":"When the key expired. On `key_expired`."},"resets_at":{"type":"string","description":"When the request window (`rate_limit_exceeded`) or the key's month (`key_spend_cap_exceeded`) resets."},"limit":{"type":"integer","description":"The limit that was hit, on the `*_limit_exceeded` codes."},"running":{"type":"integer","description":"Runs in flight. On `concurrency_limit_exceeded`."},"active":{"type":"integer","description":"Active Trackers or webhook endpoints. On `tracker_limit_exceeded` and `webhook_limit_exceeded`."},"requested":{"type":"integer","description":"Trackers the request would resume. On `tracker_limit_exceeded` from a Collection action."},"count":{"type":"integer","description":"Collections held. On `collection_limit_exceeded`."},"balance_credits":{"type":"integer","description":"The Balance, in Credits. On `insufficient_balance`."},"required_credits":{"type":"integer","description":"What the call needs, in Credits (the worst case where quoted). On `insufficient_balance`."},"max_credits":{"type":"integer","description":"The cap the call sent. On `max_credits_exceeded`."},"estimate_credits":{"type":"integer","description":"The call's worst-case quote, in Credits. On `max_credits_exceeded` and `key_spend_cap_exceeded`."},"cap_credits":{"type":"integer","description":"The key's monthly cap. On `key_spend_cap_exceeded`."},"spent_credits":{"type":"integer","description":"The key's Charges this UTC month. On `key_spend_cap_exceeded`."},"reserved_credits":{"type":"integer","description":"What the key's Runs in flight hold. On `key_spend_cap_exceeded`."},"endpoints":{"type":"array","items":{"type":"string"},"description":"The sources that could not answer. On `source_unavailable`."},"endpoint":{"type":"string","description":"The source that could not answer. On `source_unavailable`."},"candidates":{"type":"array","items":{"type":"object","properties":{},"additionalProperties":true},"description":"The advertisers that carry the name, to ask again with. On `advertiser_ambiguous`."},"supported_kinds":{"type":"array","items":{"type":"string"},"description":"The kinds that are accepted. On `kind_deprecated` and `focus_unsupported_kind`."},"duration_seconds":{"type":"number","description":"The video's length. On `video_too_long`."},"max_duration_seconds":{"type":"number","description":"The longest video accepted. On `video_too_long`."},"overlap_expires_at":{"type":"string","description":"When the previous secret stops working. On `webhook_rotation_in_progress`."},"scope":{"type":"string","enum":["read_only"],"description":"The key's scope. On `key_scope_insufficient`."},"required":{"type":"string","enum":["full"],"description":"The scope the call needs. On `key_scope_insufficient`."},"collection_id":{"type":"string","description":"The Collection that already has the name. On `collection_name_taken`."},"collection_kind":{"type":"string","description":"The Collection's kind. On `collection_kind_mismatch`."},"kind":{"type":"string","description":"The kind that was offered. On `collection_kind_mismatch`."},"run_id":{"type":"string","description":"The Run the Idempotency-Key already belongs to. On `idempotency_conflict`."},"reason":{"type":"string","description":"A short machine-readable reason, where a code has several."},"reference_id":{"type":"string","description":"Our reference for an unexpected failure, the same as `request_id`; quote it when reporting it."},"run":{"$ref":"#/components/schemas/Run","description":"The Run, on a failed Run's body, so its id is kept."},"error":{"type":"object","properties":{},"additionalProperties":true,"description":"The same problem, nested, on a failed Run's body."}},"required":["type","title","status","code","retryable","action"],"additionalProperties":true,"description":"RFC 9457 problem document, served as `application/problem+json`. Branch on `code`, never on the prose. `retryable` and `action` say whether to retry and what to do next."},"Video":{"type":"object","properties":{"platform":{"type":"string"},"id":{"type":"string"},"url":{"type":["string","null"]},"description":{"type":"string"},"posted_at":{"type":["string","null"]},"duration_seconds":{"type":["number","null"]},"thumbnail_url":{"type":["string","null"]},"hashtags":{"type":"array","items":{"type":"string"}},"sound":{"type":["object","null"],"properties":{"id":{"type":"string"},"title":{"type":["string","null"]},"author":{"type":["string","null"],"description":"Who made the sound, as the platform names them. Null when the platform did not say (Facebook never does)."},"is_original":{"type":["boolean","null"],"description":"True for the creator's own audio (a voiceover or original sound), false for a catalogue or library track. Null when the platform did not say, never false for unknown."}},"required":["id","title","author","is_original"]},"creator":{"type":["object","null"],"properties":{"id":{"type":"string"},"handle":{"type":["string","null"]},"name":{"type":"string"},"follower_count":{"type":["number","null"]},"avatar_url":{"type":["string","null"],"description":"Our archived copy when there is one, else the platform's URL, which may be signed and expire. Download it rather than storing the link."},"verified":{"type":["boolean","null"],"description":"The creator's verified badge, from their latest profile read, else from this video's read. Null when neither reported it."}},"required":["id","handle","name","follower_count","avatar_url","verified"]},"region":{"type":["string","null"],"description":"Where the video was posted, as the platform reports it (a country code on TikTok). Null when not reported."},"language":{"type":["string","null"],"description":"Platform-declared caption language, e.g. `en` (TikTok). Null when not reported."},"title":{"type":["string","null"],"description":"The video's own title (YouTube, Facebook). `description` still starts with it on YouTube, as before. Null when the platform shows none or did not report it."},"commerce":{"type":["object","null"],"properties":{"is_ad":{"type":["boolean","null"],"description":"The Platform marks the video as an ad (TikTok, Instagram)."},"paid_partnership":{"type":["boolean","null"],"description":"The Platform marks a paid partnership (TikTok, Instagram; on YouTube, its \"Includes paid promotion\" label)."},"affiliate":{"type":["boolean","null"],"description":"The Platform marks affiliate content (Instagram)."},"shop_url":{"type":["string","null"],"description":"The product link the video carries (TikTok Shop)."},"anchors":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","description":"The Platform's own anchor type id, e.g. `54`."},"label":{"type":"string","description":"What the anchor shows, e.g. `CapCut · Editing made easy`."}},"required":["kind","label"]},"description":"The links the video carries under its caption (an editing template, a product, a place). Empty when none were reported."}},"required":["is_ad","paid_partnership","affiliate","shop_url","anchors"],"description":"Platform-declared commerce: what the Platform itself says, never inferred from the content. Each flag is null when not reported, never false. The object is null when nothing in it was reported."},"people":{"type":["object","null"],"properties":{"mentions":{"type":"array","items":{"type":"string"},"description":"Handles the caption mentions (lowercased)."},"collaborators":{"type":"array","items":{"type":"object","properties":{"handle":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["handle","name"]},"description":"Co-authors the Platform names on the Video (an Instagram collab, a Facebook collaborator)."}},"required":["mentions","collaborators"],"description":"Platform-declared people: accounts the Video itself mentions or names. On TikTok `mentions` are the caption's mentions; on Instagram they are the users the Video tags, then the accounts its caption names. Null when it named none."},"location":{"type":["object","null"],"properties":{"id":{"type":["string","null"],"description":"The Platform's own place id. Null when not sent."},"name":{"type":"string","description":"The place, e.g. `Central Park, New York`."}},"required":["id","name"],"description":"The place the Video names (Instagram). Null when it named none or the read did not say."},"topics":{"type":["object","null"],"properties":{"keywords":{"type":"array","items":{"type":"string"},"description":"The creator's own tags (YouTube)."},"genre":{"type":["string","null"],"description":"The Platform's category, e.g. `Education` (YouTube)."},"labels":{"type":"array","items":{"type":"string"},"description":"The Platform's own category labels (TikTok)."}},"required":["keywords","genre","labels"],"description":"Platform-declared topics. Null when the Platform reported none."},"chapters":{"type":["array","null"],"items":{"type":"object","properties":{"title":{"type":"string"},"start_seconds":{"type":"number","description":"Where the chapter starts, in seconds from the start."}},"required":["title","start_seconds"]},"description":"The description's chapters, in order (YouTube). Null when the video has none or they were not reported."},"ai_generated":{"type":["boolean","null"],"description":"The Platform labels the video AI-generated (TikTok). Null when not reported."},"snapshot":{"type":["object","null"],"properties":{"at":{"type":"string"},"views":{"type":"number"},"likes":{"type":"number"},"comments":{"type":"number"},"shares":{"type":"number"},"saves":{"type":"number"}},"required":["at","views","likes","comments","shares","saves"]},"scores":{"type":["object","null"],"properties":{"outlier":{"type":["number","null"],"description":"Views over the creator's median views."},"outlier_p90":{"type":["number","null"]},"percentile":{"type":["number","null"],"description":"Where this video sits in the creator's own sample, 0-100."},"velocity":{"type":["object","null"],"properties":{"views_per_hour":{"type":"number"},"window":{"type":"string"}},"required":["views_per_hour","window"]},"reason":{"type":["string","null"],"enum":["aged_out",null],"description":"`aged_out` when the video is over 30 days old and Scores are null."},"baseline":{"type":"object","properties":{"median_views":{"type":"number"},"p90_views":{"type":"number"},"engagement_rate":{"type":["number","null"]},"posts_per_week":{"type":["number","null"]},"sample":{"type":"integer"},"confidence":{"type":"string","enum":["high","low"]},"source":{"type":"string","enum":["videos","follower_tier"]},"computed_at":{"type":["string","null"]},"stale":{"type":"boolean","description":"True past 7 days; the next lookup refreshes it."}},"required":["median_views","p90_views","engagement_rate","posts_per_week","sample","confidence","source","computed_at","stale"],"description":"The yardstick every Score on this creator is measured against."}},"required":["outlier","outlier_p90","percentile","velocity","reason","baseline"],"description":"Null when the creator has no baseline yet."},"coverage":{"type":"string","enum":["partial"],"description":"Present only where the platform's index is best-effort."}},"required":["platform","id","url","description","posted_at","duration_seconds","thumbnail_url","hashtags","sound","creator","region","language","title","commerce","people","location","topics","chapters","ai_generated","snapshot","scores"],"description":"One normalised video, the same shape on every platform."},"Creator":{"type":"object","properties":{"platform":{"type":"string"},"id":{"type":"string"},"handle":{"type":["string","null"]},"name":{"type":"string"},"avatar_url":{"type":["string","null"]},"follower_count":{"type":["number","null"]},"bio":{"type":["string","null"]},"verified":{"type":"boolean","description":"The verified badge, where the platform reports it (TikTok, Instagram, YouTube)."},"video_count":{"type":["number","null"],"description":"Videos the platform says the creator has (TikTok, YouTube)."},"total_likes":{"type":["number","null"],"description":"Likes the creator's videos have received, lifetime (TikTok). TikTok reports no lifetime views."},"following_count":{"type":["number","null"],"description":"Accounts the creator follows (TikTok, Instagram). Null when unreported."},"links":{"type":["array","null"],"items":{"type":"object","properties":{"title":{"type":["string","null"],"description":"The link's label, null where the platform gives none."},"url":{"type":"string"}},"required":["title","url"]},"description":"Bio or channel links, in the platform's order (TikTok and Instagram bio links, YouTube channel links, a Facebook Page's website). Null when none."},"joined_at":{"type":["string","null"],"description":"When the account was created, RFC 3339 (TikTok; YouTube and Facebook give a date, so the time is midnight UTC). Null when unreported."},"country":{"type":["string","null"],"description":"The account's country or region as the platform reports it: a code on TikTok (`US`), a name on YouTube (`United States`). Null when unreported."},"business":{"type":["object","null"],"properties":{"is_business":{"type":["boolean","null"],"description":"A business or organisation account (TikTok, Instagram, Facebook); null when the platform did not say, or on an Instagram professional account whose logged-out flag is unreliable (use `category`)."},"category":{"type":["string","null"],"description":"The account's category, e.g. `Artist`."}},"required":["is_business","category"],"description":"Whether the account is a business or organisation, and its category. Null when unreported."},"total_views":{"type":["number","null"],"description":"Lifetime views across the channel (YouTube). Null when unreported."},"contact":{"type":["object","null"],"properties":{"email":{"type":["string","null"]},"phone":{"type":["string","null"]},"address":{"type":["string","null"],"description":"The address as one line of text."},"website":{"type":["string","null"]},"source":{"type":"string","enum":["profile","bio"],"description":"`profile`: the contact details a Facebook Page shows publicly. `bio`: the first email address written in the creator's bio (every platform); phone numbers are never read from a bio."}},"required":["email","phone","address","website","source"],"description":"Contact details the account publishes itself, never inferred or enriched from elsewhere. Null when it publishes none; at least one detail is set otherwise. You are responsible for using them lawfully: follow the anti-spam and data-protection rules that apply to you (e.g. CAN-SPAM, GDPR, PECR) before contacting anyone. Stored only with the creator and deleted with it, under our data retention terms."},"snapshot":{"type":["object","null"],"properties":{"at":{"type":"string"},"followers":{"type":["number","null"]}},"required":["at","followers"]},"baseline":{"type":["object","null"],"properties":{"median_views":{"type":"number"},"p90_views":{"type":"number"},"engagement_rate":{"type":["number","null"]},"posts_per_week":{"type":["number","null"]},"sample":{"type":"integer"},"confidence":{"type":"string","enum":["high","low"]},"source":{"type":"string","enum":["videos","follower_tier"]},"computed_at":{"type":["string","null"]},"stale":{"type":"boolean","description":"True past 7 days; the next lookup refreshes it."}},"required":["median_views","p90_views","engagement_rate","posts_per_week","sample","confidence","source","computed_at","stale"],"description":"The yardstick every Score on this creator is measured against."},"videos":{"type":"array","items":{"$ref":"#/components/schemas/Video"},"description":"With `include=videos`."},"next_cursor":{"type":["string","null"],"description":"With `include=videos` on a platform that pages the feed (every one but TikTok): pass it back as `cursor`, with the same creator, for the next page; null on the last page."},"like_count":{"type":["number","null"],"description":"Page likes (Facebook)."},"category":{"type":["string","null"],"description":"The Page's category, e.g. `Artist` (Facebook)."},"advertiser":{"type":"object","properties":{"page_id":{"type":"string"},"name":{"type":["string","null"]},"page_url":{"type":"string"}},"required":["page_id","name","page_url"],"description":"Facebook: the Meta Advertiser with this Page's id, when we already hold it (`GET /advertisers/{page_id}`). Absent otherwise."}},"required":["platform","id","handle","name","avatar_url","follower_count","bio","following_count","links","joined_at","country","business","total_views","contact","snapshot","baseline"]},"Ad":{"type":"object","properties":{"library":{"type":"string","enum":["meta","tiktok"]},"id":{"type":"string"},"url":{"type":["string","null"]},"advertiser":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","name"]},"is_active":{"type":["boolean","null"]},"first_shown":{"type":["string","null"]},"last_shown":{"type":["string","null"]},"placements":{"type":"array","items":{"type":"string"}},"creative":{"type":"object","properties":{"title":{"type":["string","null"]},"body":{"type":["string","null"]},"cta":{"type":["string","null"]},"link_url":{"type":["string","null"]},"format":{"type":["string","null"]},"image_urls":{"type":"array","items":{"type":"string"}},"video_urls":{"type":"array","items":{"type":"string"}},"thumbnail_urls":{"type":"array","items":{"type":"string"}}},"required":["title","body","cta","link_url","format","image_urls","video_urls","thumbnail_urls"]},"reach":{"type":"object","properties":{"impressions":{"type":["string","null"]},"spend":{"type":["string","null"]},"currency":{"type":["string","null"]},"audience":{"type":["string","null"]}},"required":["impressions","spend","currency","audience"],"description":"Ranges as the library reports them, never coerced. Meta discloses spend and impressions for political and issue Ads, and reach (`audience`) for some EU Ads; otherwise null. TikTok reports `audience` (a bucket such as `10K-100K`); `spend` is null, and `impressions` is null except on a single-Ad lookup."},"kind":{"type":["string","null"],"enum":["commercial","political","issue",null],"description":"Meta only."},"media_type":{"type":["string","null"],"enum":["video","image","carousel",null],"description":"Meta only."},"countries":{"type":["array","null"],"items":{"type":"string"},"description":"Countries reached, when the library discloses them: Meta search and lookup, and the TikTok single-Ad lookup."},"variant_count":{"type":["number","null"],"description":"Meta only. How many Ads share this Ad's media; null for a single Ad."},"days_running":{"type":["number","null"],"description":"Meta only. Whole days from start to stop, or to now while running."},"archived":{"type":"boolean","description":"True when every media URL is our permanent archived copy; false while any is still the library's expiring URL (retried on the next sighting)."},"winner_score":{"type":["object","null"],"properties":{"score":{"type":["number","null"]},"confidence":{"type":"string","enum":["high","low"]},"inputs":{"type":"object","properties":{"days_running":{"type":["number","null"]},"variants_added":{"type":"number"},"snapshots":{"type":"number"},"advertiser_ads":{"type":"number","description":"Dated Ads of this Advertiser stored so far, this one included."}},"required":["days_running","variants_added","snapshots","advertiser_ads"]},"reason":{"type":["string","null"],"enum":["single_snapshot","few_advertiser_ads","no_start_date",null]}},"required":["score","confidence","inputs","reason"],"description":"Meta only. How strongly the Ad looks like a winner. 0 to 100, computed from the stored history of the Ad, never fetched. score = round(100 x (0.7 x rank(days_running) + 0.3 x rank(variants_added))), where rank is the share of the Advertiser's other Ads below this one (ties count half) and variants_added is the variant count at the latest Snapshot minus at the first. With one Snapshot the score is round(100 x rank(days_running)), confidence low, reason single_snapshot. With no other dated Ad of the Advertiser, rank falls back to min(days, 90)/90 and min(variants, 5)/5; under 5 dated Ads of the Advertiser the score is low confidence, reason few_advertiser_ads. No start date: score null, reason no_start_date."},"intelligence":{"anyOf":[{"type":"object","properties":{"version":{"type":"integer"},"model":{"type":"string"},"computed_at":{"type":"string"},"source":{"type":"string"},"content":{"type":"object","properties":{"summary":{"type":"string"},"niche":{"type":"string"},"languages":{"type":"array","items":{"type":"string"}},"content_styles":{"type":"array","items":{"type":"string"}},"keywords":{"type":"array","items":{"type":"object","properties":{"keyword":{"type":"string"},"category":{"type":"string"},"sentiment":{"type":"number"}},"required":["keyword","category","sentiment"]}},"transcript":{"type":["string","null"]},"transcript_segments":{"type":["array","null"],"items":{"type":"object","properties":{"start_ms":{"type":"integer"},"end_ms":{"type":"integer"},"text":{"type":"string"}},"required":["start_ms","end_ms","text"]},"description":"Timed transcript lines (ms from the start), to see when the hook lands. From YouTube captions or TikTok's caption track; null on Instagram, Facebook, with no timed captions, and on older analyses."}},"required":["summary","niche","languages","content_styles","keywords","transcript","transcript_segments"]},"hook":{"type":"object","properties":{"opening_line":{"type":["string","null"]},"type":{"type":"string"},"visual_hook":{"type":["string","null"]},"rationale":{"type":["string","null"]}},"required":["opening_line","type","visual_hook","rationale"]},"persuasion":{"type":"object","properties":{"call_to_action":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":["string","null"]}},"required":["type","text"]},"sponsored":{"type":"boolean","description":"Whether the video is plausibly a paid promotion. Always true when the Platform labels it an ad or a paid partnership."},"sponsorship_signals":{"type":"array","items":{"type":"string"}},"brands_and_products":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"kind":{"type":"string"},"prominence":{"type":"string"}},"required":["name","kind","prominence"]}},"trend_references":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"kind":{"type":"string"}},"required":["name","kind"]}}},"required":["call_to_action","sponsored","sponsorship_signals","brands_and_products","trend_references"]},"tone":{"type":"object","properties":{"sentiment_label":{"type":"string"},"sentiment_score":{"type":"number"},"primary_emotion":{"type":"string"},"emotion_intensity":{"type":["number","null"]},"emotion_rationale":{"type":["string","null"]},"speaking_style":{"type":"string"},"speaking_style_notes":{"type":["string","null"]}},"required":["sentiment_label","sentiment_score","primary_emotion","emotion_intensity","emotion_rationale","speaking_style","speaking_style_notes"]},"visual":{"type":"object","properties":{"format":{"type":"string"},"setting":{"type":"string"},"face_visibility":{"type":"string"},"on_screen_text":{"type":"array","items":{"type":"string"}},"has_on_screen_captions":{"type":"boolean"},"camera_notes":{"type":["string","null"]},"lighting_notes":{"type":["string","null"]},"elements":{}},"required":["format","setting","face_visibility","on_screen_text","has_on_screen_captions","camera_notes","lighting_notes"]},"safety":{"type":"object","properties":{"brand_safety_tier":{"type":"string"},"reasons":{"type":"array","items":{"type":"string"}},"notes":{"type":["string","null"]}},"required":["brand_safety_tier","reasons","notes"]},"pipeline":{"type":"string","enum":["video"]}},"required":["version","model","computed_at","source","content","hook","persuasion","tone","visual","safety","pipeline"],"description":"Video Ads: the full video analysis, read from the archived video with the ad copy as context."},{"type":"object","properties":{"pipeline":{"type":"string","enum":["image"]},"version":{"type":"integer"},"model":{"type":"string"},"computed_at":{"type":"string"},"images_analyzed":{"type":"integer"},"summary":{"type":"string"},"copy":{"type":"object","properties":{"angle":{"type":"string"},"rationale":{"type":["string","null"]},"headline":{"type":["string","null"]}},"required":["angle","rationale","headline"]},"offer":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":["string","null"]}},"required":["type","text"]},"call_to_action":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":["string","null"]}},"required":["type","text"]},"visual":{"type":"object","properties":{"format":{"type":"string"},"on_image_text":{"type":"array","items":{"type":"string"}}},"required":["format","on_image_text"]},"topics":{"type":"array","items":{"type":"string"}},"tone":{"type":"object","properties":{"sentiment_label":{"type":"string"},"sentiment_score":{"type":"number"}},"required":["sentiment_label","sentiment_score"]}},"required":["pipeline","version","model","computed_at","images_analyzed","summary","copy","offer","call_to_action","visual","topics","tone"],"description":"Image and carousel Ads: the analysis an image can carry, read from the archived images with the ad copy as context."},{"type":"null"}],"description":"Present when already computed for this Ad (on TikTok, by a Tracker with `intelligence`), or asked for with `analyze` (Meta); null under `analyze` when it could not be computed."},"advertiser_account":{"type":["object","null"],"properties":{"username":{"type":"string"},"display_name":{"type":["string","null"]},"followers":{"type":["string","null"],"description":"As TikTok shows it (`9.3M`), not a number."},"verified":{"type":["boolean","null"]},"url":{"type":["string","null"]}},"required":["username","display_name","followers","verified","url"],"description":"TikTok lookup only. The TikTok account the Ad ran from."},"targeting":{"type":["object","null"],"properties":{"countries":{"type":"array","items":{"type":"string"}},"impressions":{"type":["string","null"]},"audience_size":{"type":["string","null"]},"ages":{"type":"array","items":{"type":"string"},"description":"Age ranges targeted (`18-24`)."},"genders":{"type":"array","items":{"type":"string"},"description":"Genders targeted (`female`, `male`, `unknown`)."},"by_country":{"type":"array","items":{"type":"object","properties":{"country":{"type":"string"},"impressions":{"type":["string","null"]},"breakdown":{"type":"array","items":{"type":"object","properties":{"age":{"type":"string"},"gender":{"type":"string"},"impressions":{"type":["string","null"]}},"required":["age","gender","impressions"]}}},"required":["country","impressions","breakdown"]}}},"required":["countries","impressions","audience_size","ages","genders","by_country"],"description":"TikTok lookup only. Where and to whom the ad library says the Ad was delivered, impressions as ranges per country by age and gender. Null when the Ad came from Creative Center."},"performance":{"type":["object","null"],"properties":{"ctr":{"type":["number","null"],"description":"Click-through rate as a fraction (0.46 is 46%)."},"likes":{"type":["number","null"]},"comments":{"type":["number","null"]},"shares":{"type":["number","null"]}},"required":["ctr","likes","comments","shares"],"description":"TikTok lookup only. Creative Center's engagement figures, when the Ad is a Creative Center Top Ad; null for an Ad only the ad library holds."},"objective":{"type":["string","null"],"description":"TikTok lookup only. The Ad's objective (`Traffic`)."}},"required":["library","id","url","advertiser","is_active","first_shown","last_shown","placements","creative","reach"]},"Advertiser":{"type":"object","properties":{"page_id":{"type":"string","description":"The Facebook Page id: the advertiser's identity."},"name":{"type":["string","null"]},"page_url":{"type":["string","null"]},"instagram":{"type":["object","null"],"properties":{"handle":{"type":"string"},"url":{"type":"string"}},"required":["handle","url"],"description":"The Page's linked Instagram account, only when Meta shows one."},"creator":{"type":["object","null"],"properties":{"id":{"type":"string"},"platform":{"type":"string","enum":["instagram"]},"handle":{"type":["string","null"]},"name":{"type":"string"}},"required":["id","platform","handle","name"],"description":"The Creator behind that Instagram account, when we hold one. Never guessed from the name."},"running_ad_count":{"type":["integer","null"],"description":"Running Ads as last observed; null until a complete observation."},"total_ad_count":{"type":["integer","null"],"description":"Every Ad the Page has in the library, running or stopped, as last observed."},"last_observed_at":{"type":["string","null"],"description":"When every Ad of the advertiser was last read in one go."},"first_seen_at":{"type":"string"},"cached":{"type":"boolean","description":"True when served from a complete observation under 6 hours old."},"as_of":{"type":"string","description":"When this profile was observed."}},"required":["page_id","name","page_url","instagram","creator","running_ad_count","total_ad_count","last_observed_at","first_seen_at","cached","as_of"]},"Tracker":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["creator","hashtag","sound","advertiser","keyword","video"],"description":"`video` is deprecated (ADR 0024): existing Video Trackers keep working, new ones are refused with 400 `kind_deprecated`."},"platform":{"type":"string","description":"`meta` or `tiktok` for an advertiser Tracker."},"target":{"type":"string"},"intelligence":{"type":"boolean","description":"Whether each new video (or Ad) the cycle finds is analysed."},"state":{"type":"string","enum":["active","paused","deleted"]},"last_cycle_at":{"type":["string","null"]},"last_run_id":{"type":["string","null"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"coverage":{"type":"string","enum":["library_regions_only","partial"],"description":"`GET /v1/trackers/{id}`. TikTok advertiser: `library_regions_only` when its latest observation found no Ads in the TikTok ad library, which holds only Ads delivered in the EU/EEA, Switzerland, the UK and Turkey. Keyword on Instagram or Facebook: `partial`, their search being a best-effort index. Absent otherwise."},"coverage_note":{"type":"string","description":"The regions the TikTok ad library covers, beside `coverage`."},"focus":{"type":"object","properties":{"text":{"type":"string"},"must_mention":{"type":"array","items":{"type":"string"}}},"required":["text","must_mention"],"description":"The Tracker's Focus: which Videos are relevant to you. Terms are stored lowercased. Absent when it has none."}},"required":["id","kind","platform","target","intelligence","state","last_cycle_at","last_run_id","created_at","updated_at"]},"Page":{"type":"object","properties":{"next_cursor":{"type":["string","null"],"description":"Pass back as `cursor`. Null on the last page."}},"required":["next_cursor"],"description":"A page of a list. `items` holds the page; pass `next_cursor` back as `cursor` for the next one."},"Research":{"type":"object","properties":{"digest_version":{"type":"integer"},"mode":{"type":"string","enum":["keywords","creators"],"description":"What the research was seeded with: `keywords` (an intent) or `creators` (a breakdown). Absent means `keywords`."},"intent":{"type":"string"},"keywords":{"type":"array","items":{"type":"string"}},"keyword_rationale":{"type":"string"},"coverage":{"type":"object","additionalProperties":{"type":"string"}},"digest":{"$ref":"#/components/schemas/Digest"},"lift_tables":{"$ref":"#/components/schemas/LiftTables"},"breakdown":{"type":"object","properties":{"videos_per_creator":{"type":"integer","description":"Recent Videos asked for per Creator."},"creators":{"type":"array","items":{"type":"object","properties":{"platform":{"type":"string"},"handle":{"type":"string"},"id":{"type":"string"},"videos_read":{"type":"integer","description":"Videos read; fewer than `videos_per_creator` when `ended`."},"ended":{"type":"boolean","description":"True when the Creator's feed ran out before `videos_per_creator`."}},"required":["platform","handle","id","videos_read","ended"]},"description":"Every Creator read, in request order, each charged its fee."},"failed":{"type":"array","items":{"type":"object","properties":{"platform":{"type":"string"},"handle":{"type":"string"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["platform","handle","code","detail"]},"description":"Creators that could not be read, charged 0, each with its problem `code` and `detail`. The Run is then partial."},"lift_videos":{"type":"integer","description":"Analysed Videos with a view count, of `analysed_videos`: the ranking and lift basis. The rest are unscored."},"analysed_videos":{"type":"integer","description":"Videos analysed, of all the Creators read."}},"required":["videos_per_creator","creators"],"description":"Breakdown only: the Creators read and how many Videos each returned, and those that could not be read."},"videos":{"type":"array","items":{"$ref":"#/components/schemas/Video"},"description":"The top 25 videos of the ranked shortlist, in rank order. Every video the research delivered pages, with filters and sorting, at `GET /v1/research/{id}/videos`."},"creators":{"type":"array","items":{"type":"object","properties":{"platform":{"type":"string"},"id":{"type":"string"},"handle":{"type":["string","null"]},"name":{"type":"string"},"follower_count":{"type":["number","null"]},"avatar_url":{"type":["string","null"],"description":"The creator's avatar as their video carried it at collection time; may be a signed URL that expires. Null when not recorded."},"video_count":{"type":"integer"},"best_outlier":{"type":["number","null"]},"median_views":{"type":["number","null"],"description":"The Creator baseline median views `best_outlier` was measured against, frozen at collection time. Null, never zero, when no video of theirs carried Scores."},"total_views":{"type":"number"},"video_ids":{"type":"array","items":{"type":"string"}},"top_video_id":{"type":["string","null"],"description":"Breakdown only: this Creator's top Video against their own median (`platform:id`). Null when none was analysed."},"posts_per_week":{"type":["number","null"],"description":"Breakdown only: posts per week over the Videos read. Null when their dates are unknown."},"videos_read":{"type":"integer","description":"Breakdown only: Videos read for this Creator."},"videos_analysed":{"type":"integer","description":"Breakdown only: Videos analysed of those read; 0 when the intent dropped all of them or every analysis failed."}},"required":["platform","id","handle","name","follower_count","avatar_url","video_count","best_outlier","median_views","total_views","video_ids"]},"description":"The top 25 creators, by best outlier multiple, then views. Every creator the research recorded pages, with filters and sorting, at `GET /v1/research/{id}/creators`."},"hashtags":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"title":{"type":["string","null"]},"platforms":{"type":"array","items":{"type":"string"},"description":"Every platform this tag was observed on in the shortlist. One rollup spans platforms; `video_ids` are `platform:id` if you want the split."},"video_count":{"type":"integer"},"total_views":{"type":"number"},"video_ids":{"type":"array","items":{"type":"string"}}},"required":["value","platforms","video_count","total_views","video_ids"]},"description":"The top 25 hashtags, by video count, then views. Every hashtag the research recorded pages, with filters and sorting, at `GET /v1/research/{id}/hashtags`."},"sounds":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"title":{"type":["string","null"]},"platforms":{"type":"array","items":{"type":"string"},"description":"Every platform this tag was observed on in the shortlist. One rollup spans platforms; `video_ids` are `platform:id` if you want the split."},"video_count":{"type":"integer"},"total_views":{"type":"number"},"video_ids":{"type":"array","items":{"type":"string"}},"author":{"type":["string","null"],"description":"Who made the sound, from the first video that named them. Null when none did; absent on research recorded before it existed."},"is_original":{"type":["boolean","null"],"description":"True for original audio, false for a catalogue track, so a trend sound can be told from a voiceover. Null when no video said; absent on research recorded before it existed."}},"required":["value","platforms","video_count","total_views","video_ids"]},"description":"The top 25 sounds, by video count, then views. Every sound the research recorded pages, with filters and sorting, at `GET /v1/research/{id}/sounds`."},"research":{"type":"object","properties":{"requested":{"type":"integer"},"completed":{"type":"integer"},"failed":{"type":"integer"},"cached":{"type":"integer"},"fresh":{"type":"integer"},"max_videos":{"type":"integer"},"included_videos":{"type":"integer"},"shortlisted":{"type":"object","additionalProperties":{"type":"integer"},"description":"Shortlist places per requested platform: a guaranteed part each, then the rest by how many on-topic candidates each had."},"dropped_off_topic":{"type":"integer","description":"Candidates judged off-topic and dropped before the shortlist; never charged."},"dropped_unsure":{"type":"integer","description":"Candidates whose relevance was unsure and that ranked too low to keep; never charged."},"dropped_sample":{"type":"array","items":{"type":"object","properties":{"video_id":{"type":"string","description":"`platform:id` of the dropped video."},"verdict":{"type":"string","enum":["off_topic","unsure"]},"reason":{"type":"string","description":"The relevance check's reason, short."}},"required":["video_id","verdict","reason"]},"description":"Up to 10 dropped candidates, best-ranked first, with why each was dropped. Absent on research recorded before it existed."}},"required":["requested","completed","failed","cached","fresh","max_videos","included_videos"]}},"required":["digest_version","coverage","digest","videos","creators","hashtags","sounds","research"]},"ResearchSummary":{"type":"object","properties":{"digest_version":{"type":"integer"},"mode":{"type":"string","enum":["keywords","creators"],"description":"What the research was seeded with: `keywords` (an intent) or `creators` (a breakdown). Absent means `keywords`."},"intent":{"type":"string"},"keywords":{"type":"array","items":{"type":"string"}},"keyword_rationale":{"type":"string"},"coverage":{"type":"object","additionalProperties":{"type":"string"}},"digest":{"$ref":"#/components/schemas/Digest"},"lift_tables":{"$ref":"#/components/schemas/LiftTables"},"breakdown":{"type":"object","properties":{"videos_per_creator":{"type":"integer","description":"Recent Videos asked for per Creator."},"creators":{"type":"array","items":{"type":"object","properties":{"platform":{"type":"string"},"handle":{"type":"string"},"id":{"type":"string"},"videos_read":{"type":"integer","description":"Videos read; fewer than `videos_per_creator` when `ended`."},"ended":{"type":"boolean","description":"True when the Creator's feed ran out before `videos_per_creator`."}},"required":["platform","handle","id","videos_read","ended"]},"description":"Every Creator read, in request order, each charged its fee."},"failed":{"type":"array","items":{"type":"object","properties":{"platform":{"type":"string"},"handle":{"type":"string"},"code":{"type":"string"},"detail":{"type":"string"}},"required":["platform","handle","code","detail"]},"description":"Creators that could not be read, charged 0, each with its problem `code` and `detail`. The Run is then partial."},"lift_videos":{"type":"integer","description":"Analysed Videos with a view count, of `analysed_videos`: the ranking and lift basis. The rest are unscored."},"analysed_videos":{"type":"integer","description":"Videos analysed, of all the Creators read."}},"required":["videos_per_creator","creators"],"description":"Breakdown only: the Creators read and how many Videos each returned, and those that could not be read."},"research":{"type":"object","properties":{"requested":{"type":"integer"},"completed":{"type":"integer"},"failed":{"type":"integer"},"cached":{"type":"integer"},"fresh":{"type":"integer"},"max_videos":{"type":"integer"},"included_videos":{"type":"integer"},"shortlisted":{"type":"object","additionalProperties":{"type":"integer"},"description":"Shortlist places per requested platform: a guaranteed part each, then the rest by how many on-topic candidates each had."},"dropped_off_topic":{"type":"integer","description":"Candidates judged off-topic and dropped before the shortlist; never charged."},"dropped_unsure":{"type":"integer","description":"Candidates whose relevance was unsure and that ranked too low to keep; never charged."},"dropped_sample":{"type":"array","items":{"type":"object","properties":{"video_id":{"type":"string","description":"`platform:id` of the dropped video."},"verdict":{"type":"string","enum":["off_topic","unsure"]},"reason":{"type":"string","description":"The relevance check's reason, short."}},"required":["video_id","verdict","reason"]},"description":"Up to 10 dropped candidates, best-ranked first, with why each was dropped. Absent on research recorded before it existed."}},"required":["requested","completed","failed","cached","fresh","max_videos","included_videos"]}},"required":["digest_version","coverage","digest","research"],"description":"What a research recorded about itself: the intent, the keywords derived from it, coverage per platform, the counts, and the digest. The videos, creators, hashtags and sounds behind it page separately."},"ResearchHashtags":{"allOf":[{"$ref":"#/components/schemas/ResearchPage"},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"title":{"type":["string","null"]},"platforms":{"type":"array","items":{"type":"string"},"description":"Every platform this tag was observed on in the shortlist. One rollup spans platforms; `video_ids` are `platform:id` if you want the split."},"video_count":{"type":"integer"},"total_views":{"type":"number"},"video_ids":{"type":"array","items":{"type":"string"}}},"required":["value","platforms","video_count","total_views","video_ids"]}}},"required":["items"]}]},"ResearchSounds":{"allOf":[{"$ref":"#/components/schemas/ResearchPage"},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"title":{"type":["string","null"]},"platforms":{"type":"array","items":{"type":"string"},"description":"Every platform this tag was observed on in the shortlist. One rollup spans platforms; `video_ids` are `platform:id` if you want the split."},"video_count":{"type":"integer"},"total_views":{"type":"number"},"video_ids":{"type":"array","items":{"type":"string"}},"author":{"type":["string","null"],"description":"Who made the sound, from the first video that named them. Null when none did; absent on research recorded before it existed."},"is_original":{"type":["boolean","null"],"description":"True for original audio, false for a catalogue track, so a trend sound can be told from a voiceover. Null when no video said; absent on research recorded before it existed."}},"required":["value","platforms","video_count","total_views","video_ids"]}}},"required":["items"]}]},"ResearchVideos":{"allOf":[{"$ref":"#/components/schemas/ResearchPage"},{"type":"object","properties":{"items":{"type":"array","items":{"description":"One video of a research, with the numbers frozen as the research saw them.","allOf":[{"$ref":"#/components/schemas/Video"},{"type":"object","properties":{"rank":{"type":"integer","description":"Position in the research's own ranking, best first from 0 — outlier, then views."},"item_id":{"type":["string","null"],"description":"The run item this video was delivered by, if still present."},"cached":{"type":"boolean","description":"Whether the analysis was already stored rather than paid for."}},"required":["rank","item_id","cached"]}]}}},"required":["items"]}]},"ResearchCreators":{"allOf":[{"$ref":"#/components/schemas/ResearchPage"},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"platform":{"type":"string"},"id":{"type":"string"},"handle":{"type":["string","null"]},"name":{"type":"string"},"follower_count":{"type":["number","null"]},"avatar_url":{"type":["string","null"],"description":"The creator's avatar as their video carried it at collection time; may be a signed URL that expires. Null when not recorded."},"video_count":{"type":"integer"},"best_outlier":{"type":["number","null"]},"median_views":{"type":["number","null"],"description":"The Creator baseline median views `best_outlier` was measured against, frozen at collection time. Null, never zero, when no video of theirs carried Scores."},"total_views":{"type":"number"},"video_ids":{"type":"array","items":{"type":"string"}},"top_video_id":{"type":["string","null"],"description":"Breakdown only: this Creator's top Video against their own median (`platform:id`). Null when none was analysed."},"posts_per_week":{"type":["number","null"],"description":"Breakdown only: posts per week over the Videos read. Null when their dates are unknown."},"videos_read":{"type":"integer","description":"Breakdown only: Videos read for this Creator."},"videos_analysed":{"type":"integer","description":"Breakdown only: Videos analysed of those read; 0 when the intent dropped all of them or every analysis failed."}},"required":["platform","id","handle","name","follower_count","avatar_url","video_count","best_outlier","median_views","total_views","video_ids"]}}},"required":["items"]}]},"Digest":{"type":"object","properties":{"summary":{"type":"string","description":"Two or three sentences answering the intent directly, across the videos analysed. Describe what the videos and their audiences say and do; never state a real-world event or outcome as fact."},"answers":{"type":"array","items":{"type":"object","properties":{"question":{"type":"string","description":"One question the intent asks, in a few words, e.g. \"How do Republicans react?\"."},"answer":{"type":"string","description":"One or two sentences answering it from the evidence. When the evidence does not cover it, say so plainly."},"video_ids":{"type":"array","items":{"type":"string"},"description":"`video_id` keys (platform:id) of the analysed videos the answer rests on, exactly as given in the evidence. Empty when the evidence does not cover the question."}},"required":["question","answer","video_ids"]}},"themes":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Short label, three or four words."},"share":{"type":"number","minimum":0,"maximum":1,"description":"Fraction of the analysed videos that belong to this theme, 0-1."},"description":{"type":"string","description":"What the videos in this theme have in common."},"video_ids":{"type":"array","items":{"type":"string"},"description":"`video_id` keys (platform:id) of the analysed videos that belong to this theme, exactly as given in the evidence."},"lift":{"type":"object","properties":{"views_lift":{"type":["number","null"]},"video_count":{"type":"integer"},"low_confidence":{"type":"boolean"}},"required":["views_lift","video_count","low_confidence"],"description":"The theme's lift over the videos it cites: their median views against the set's median, or on a Breakdown against each Creator's median. Absent before version 7."}},"required":["name","share","description","video_ids"]},"minItems":1,"maxItems":8},"hooks":{"type":"array","items":{"type":"object","properties":{"text":{"type":"string","description":"The opening line, quoted VERBATIM from the evidence. Never paraphrase, never invent."},"video_id":{"type":"string","description":"`video_id` key (platform:id) of the video this hook is quoted from, exactly as given in the evidence."},"hook_type":{"type":"string","description":"The kind of hook, e.g. question, claim, negation, stat."},"why_it_works":{"type":"string","description":"One sentence."},"template":{"type":"string","minLength":1,"description":"The verbatim hook with its specifics (product, number, mistake, outcome, audience) replaced by short bracketed slots, every other word kept as spoken, e.g. \"Stop [mistake] if you want [outcome]\"."},"lift":{"type":["object","null"],"properties":{"value":{"type":"string","description":"The analysed hook type, or format + hook type, the row is keyed by."},"video_count":{"type":"integer"},"median_views":{"type":["number","null"]},"median_engagement_rate":{"type":["number","null"]},"views_lift":{"type":["number","null"]},"engagement_lift":{"type":["number","null"]},"low_confidence":{"type":"boolean"}},"required":["value","video_count","median_views","median_engagement_rate","views_lift","engagement_lift","low_confidence"],"description":"The `lift_tables.hook_type` row for the quoted video's analysed hook type, attached in code (never written by the model). Null when that video has no analysed hook type."}},"required":["text","video_id","hook_type","why_it_works"]},"maxItems":12},"sentiment":{"type":"object","properties":{"positive":{"type":"number","minimum":0,"maximum":1},"neutral":{"type":"number","minimum":0,"maximum":1,"description":"Neutral or mixed."},"negative":{"type":"number","minimum":0,"maximum":1},"note":{"type":"string","description":"One sentence on what drives the distribution."}},"required":["positive","neutral","negative","note"]},"angles":{"type":"array","items":{"type":"object","properties":{"angle":{"type":"string","description":"A content angle worth trying."},"rationale":{"type":"string","description":"Why the evidence supports it, referencing what was seen."},"video_ids":{"type":"array","items":{"type":"string"},"description":"Videos the rationale cites."}},"required":["angle","rationale"]},"minItems":1,"maxItems":8},"formulas":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Short label, three to five words."},"recipe":{"type":"string","description":"One line saying how to make it: the format, how it opens, and the order of its beats."},"visual_format":{"type":"string","description":"The visual format, copied exactly as it appears in `lift_tables.visual_format`."},"hook_type":{"type":"string","description":"The hook type, copied exactly as it appears in `lift_tables.hook_type`."},"structure":{"type":"string","description":"The beat structure the example videos share, as short beats joined by arrows, e.g. \"problem → demo → result → CTA\"."},"video_ids":{"type":"array","items":{"type":"string"},"description":"Up to 3 `video_id` keys (platform:id) of analysed videos that follow this formula, best performing first, exactly as given in the evidence."},"lift":{"type":["object","null"],"properties":{"value":{"type":"string","description":"The analysed hook type, or format + hook type, the row is keyed by."},"video_count":{"type":"integer"},"median_views":{"type":["number","null"]},"median_engagement_rate":{"type":["number","null"]},"views_lift":{"type":["number","null"]},"engagement_lift":{"type":["number","null"]},"low_confidence":{"type":"boolean"}},"required":["value","video_count","median_views","median_engagement_rate","views_lift","engagement_lift","low_confidence"],"description":"The `lift_tables.format_hook` row for this formula's visual format and hook type, attached in code (never written by the model): its `video_count` and lifts. The lift is for the format + hook type pair only; the structure is not bucketed. Null when no analysed video has that pair."}},"required":["name","recipe","visual_format","hook_type","structure","video_ids","lift"]},"maxItems":5},"gaps":{"type":"array","items":{"type":"object","properties":{"ask":{"type":"string","description":"What the audience asks for or complains about, in one sentence, in your own words."},"comments":{"type":"array","items":{"type":"object","properties":{"text":{"type":"string","description":"A comment quoted VERBATIM from <comments>, character for character. Never paraphrase, never invent."},"video_id":{"type":"string","description":"`video_id` key (platform:id) of the video this comment was left under, exactly as given in <comments>."}},"required":["text","video_id"]},"minItems":1,"maxItems":3},"angle":{"type":"string","description":"A video someone could make that answers this ask, in one sentence."}},"required":["ask","comments","angle"]},"maxItems":5,"description":"Up to 5 things the audience asks for in the top 10 videos' comments that no analysed video addresses, each with verbatim quoted comments (and the video they came from) and a suggested angle. Empty when no comments were available. Absent on research recorded before gaps existed."}},"required":["summary","themes","hooks","sentiment","angles"]},"LiftTables":{"type":"object","properties":{"basis":{"type":"string","enum":["set_median","creator_median"]},"set":{"type":"object","properties":{"video_count":{"type":"integer"},"median_views":{"type":["number","null"]},"median_engagement_rate":{"type":["number","null"]}},"required":["video_count","median_views","median_engagement_rate"]},"visual_format":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","description":"The visual format, hook type, length bucket, or `<format> + <hook type>`."},"video_count":{"type":"integer"},"median_views":{"type":["number","null"]},"median_engagement_rate":{"type":["number","null"],"description":"(likes + comments + shares + saves) / views."},"views_lift":{"type":["number","null"],"description":"Median views of this row over the whole set's median views. Null when the set median is 0 or unknown."},"engagement_lift":{"type":["number","null"]},"low_confidence":{"type":"boolean","description":"True when the row rests on fewer than 3 videos."}},"required":["value","video_count","median_views","median_engagement_rate","views_lift","engagement_lift","low_confidence"]}},"hook_type":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","description":"The visual format, hook type, length bucket, or `<format> + <hook type>`."},"video_count":{"type":"integer"},"median_views":{"type":["number","null"]},"median_engagement_rate":{"type":["number","null"],"description":"(likes + comments + shares + saves) / views."},"views_lift":{"type":["number","null"],"description":"Median views of this row over the whole set's median views. Null when the set median is 0 or unknown."},"engagement_lift":{"type":["number","null"]},"low_confidence":{"type":"boolean","description":"True when the row rests on fewer than 3 videos."}},"required":["value","video_count","median_views","median_engagement_rate","views_lift","engagement_lift","low_confidence"]}},"length":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","description":"The visual format, hook type, length bucket, or `<format> + <hook type>`."},"video_count":{"type":"integer"},"median_views":{"type":["number","null"]},"median_engagement_rate":{"type":["number","null"],"description":"(likes + comments + shares + saves) / views."},"views_lift":{"type":["number","null"],"description":"Median views of this row over the whole set's median views. Null when the set median is 0 or unknown."},"engagement_lift":{"type":["number","null"]},"low_confidence":{"type":"boolean","description":"True when the row rests on fewer than 3 videos."}},"required":["value","video_count","median_views","median_engagement_rate","views_lift","engagement_lift","low_confidence"]}},"format_hook":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","description":"The visual format, hook type, length bucket, or `<format> + <hook type>`."},"video_count":{"type":"integer"},"median_views":{"type":["number","null"]},"median_engagement_rate":{"type":["number","null"],"description":"(likes + comments + shares + saves) / views."},"views_lift":{"type":["number","null"],"description":"Median views of this row over the whole set's median views. Null when the set median is 0 or unknown."},"engagement_lift":{"type":["number","null"]},"low_confidence":{"type":"boolean","description":"True when the row rests on fewer than 3 videos."}},"required":["value","video_count","median_views","median_engagement_rate","views_lift","engagement_lift","low_confidence"]},"description":"Visual format and hook type together, `value` as `<format> + <hook type>`: the rows the Digest's formulas take their lift from. Absent on research recorded before it existed."}},"required":["set","visual_format","hook_type","length"],"description":"Lift tables computed in code over the analysed videos: per visual format, hook type and length bucket, the video count, median views and engagement rate, and lift versus the whole set's median. The Digest quotes lifts only from these. Absent on research recorded before they existed."},"Analysis":{"type":"object","properties":{"version":{"type":"integer"},"model":{"type":"string"},"computed_at":{"type":"string"},"source":{"type":"string"},"content":{"type":"object","properties":{"summary":{"type":"string"},"niche":{"type":"string"},"languages":{"type":"array","items":{"type":"string"}},"content_styles":{"type":"array","items":{"type":"string"}},"keywords":{"type":"array","items":{"type":"object","properties":{"keyword":{"type":"string"},"category":{"type":"string"},"sentiment":{"type":"number"}},"required":["keyword","category","sentiment"]}},"transcript":{"type":["string","null"]},"transcript_segments":{"type":["array","null"],"items":{"type":"object","properties":{"start_ms":{"type":"integer"},"end_ms":{"type":"integer"},"text":{"type":"string"}},"required":["start_ms","end_ms","text"]},"description":"Timed transcript lines (ms from the start), to see when the hook lands. From YouTube captions or TikTok's caption track; null on Instagram, Facebook, with no timed captions, and on older analyses."}},"required":["summary","niche","languages","content_styles","keywords","transcript","transcript_segments"]},"hook":{"type":"object","properties":{"opening_line":{"type":["string","null"]},"type":{"type":"string"},"visual_hook":{"type":["string","null"]},"rationale":{"type":["string","null"]}},"required":["opening_line","type","visual_hook","rationale"]},"persuasion":{"type":"object","properties":{"call_to_action":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":["string","null"]}},"required":["type","text"]},"sponsored":{"type":"boolean","description":"Whether the video is plausibly a paid promotion. Always true when the Platform labels it an ad or a paid partnership."},"sponsorship_signals":{"type":"array","items":{"type":"string"}},"brands_and_products":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"kind":{"type":"string"},"prominence":{"type":"string"}},"required":["name","kind","prominence"]}},"trend_references":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"kind":{"type":"string"}},"required":["name","kind"]}}},"required":["call_to_action","sponsored","sponsorship_signals","brands_and_products","trend_references"]},"tone":{"type":"object","properties":{"sentiment_label":{"type":"string"},"sentiment_score":{"type":"number"},"primary_emotion":{"type":"string"},"emotion_intensity":{"type":["number","null"]},"emotion_rationale":{"type":["string","null"]},"speaking_style":{"type":"string"},"speaking_style_notes":{"type":["string","null"]}},"required":["sentiment_label","sentiment_score","primary_emotion","emotion_intensity","emotion_rationale","speaking_style","speaking_style_notes"]},"visual":{"type":"object","properties":{"format":{"type":"string"},"setting":{"type":"string"},"face_visibility":{"type":"string"},"on_screen_text":{"type":"array","items":{"type":"string"}},"has_on_screen_captions":{"type":"boolean"},"camera_notes":{"type":["string","null"]},"lighting_notes":{"type":["string","null"]},"elements":{}},"required":["format","setting","face_visibility","on_screen_text","has_on_screen_captions","camera_notes","lighting_notes"]},"safety":{"type":"object","properties":{"brand_safety_tier":{"type":"string"},"reasons":{"type":"array","items":{"type":"string"}},"notes":{"type":["string","null"]}},"required":["brand_safety_tier","reasons","notes"]}},"required":["version","model","computed_at","source","content","hook","persuasion","tone","visual","safety"],"description":"The versioned analysis of one video: what it says, how it opens, what it sells, how it sounds, how it looks and whether it is brand safe."},"Collection":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","description":"Unique per Customer, regardless of case."},"kind":{"type":"string","enum":["creator","hashtag","sound","advertiser","keyword","video"],"description":"What every member is. Fixed at creation. `video` is deprecated: existing Video Collections keep working, new ones are refused with 400 `kind_deprecated`."},"member_count":{"type":"integer","description":"Live (active or paused) member Trackers."},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","kind","member_count","created_at","updated_at"],"description":"A named set of Trackers of one kind. Holds no state: pausing, analysis and cycles belong to each Tracker."},"ChangeReport":{"type":"object","properties":{"id":{"type":"string"},"tracker_id":{"type":"string"},"run_id":{"type":["string","null"]},"cycle_key":{"type":"string","description":"One report per Tracker per cycle."},"triggers":{"type":"array","items":{"type":"string"},"description":"Creator: `new_videos`, `followers`, `outlier`, `velocity`, `became_ad`, `bio_link_changed`, `verified_changed`. Hashtag and Keyword: `median_views`, `new_top_videos`. Sound: `video_count`, `new_top_video`. Advertiser: `new_ads`, `stopped_ads`, `variant_growth`, `new_countries_or_placements`."},"changes":{"description":"The before/after numbers behind the triggers."},"summary":{"type":["string","null"]},"created_at":{"type":"string"},"coverage":{"type":"string","enum":["partial"],"description":"A Keyword Tracker's on Instagram or Facebook: their search is a best-effort index, so the numbers are too. Absent otherwise."},"off_focus_count":{"type":"integer","description":"A Tracker with a Focus only: how many off-focus Videos `changes` left out, including those hidden by quiet cycles since the previous report. `changes` lists in-focus and unjudged Videos; stats stay full-Sample. Absent without a Focus."},"off_focus_videos":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":["string","null"]},"focus":{"type":"object","properties":{"verdict":{"type":"string","enum":["in_focus","off_focus","unjudged"],"description":"`unjudged`: the Video could not be judged (or is not judged yet) and is shown."},"reason":{"type":"string"}},"required":["verdict","reason"]}},"required":["id","url","focus"]},"description":"Only with `include_off_focus=true`, on a report with a Focus: the Videos `off_focus_count` counts, each with `focus: { verdict, reason }`."}},"required":["id","tracker_id","run_id","cycle_key","triggers","summary","created_at"],"description":"Written only when something notable moved. Quiet cycles produce none."},"ResearchPage":{"type":"object","properties":{"total":{"type":"integer","description":"Rows matching the filters, before `limit` and `offset`."},"limit":{"type":"integer"},"offset":{"type":"integer"},"as_of":{"type":"string","enum":["run","latest"],"description":"Which snapshots the numbers come from: `run` is what the research itself saw, frozen, so a read always agrees with the digest; `latest` is the newest snapshot this API holds for each video."}},"required":["total","limit","offset","as_of"],"description":"A page of one research read. `items` holds the page; it pages with `limit` and `offset` over a frozen set."},"WebhookEvent":{"type":"object","description":"The thin webhook payload, exactly the bytes that were signed.","properties":{"id":{"description":"Event id, `evt_...`. Stable for one fact: a replay or a re-emission carries the same id, so dedupe on it.","type":"string"},"type":{"description":"`run.completed`, `tracker.changed` or `webhook.test`.","type":"string","enum":["run.completed","tracker.changed","webhook.test"]},"created_at":{"description":"When the event was created.","type":"string","format":"date-time"},"run_id":{"description":"The Run behind the event.","type":["string","null"]},"kind":{"description":"The Run's kind, lower case, e.g. `research`.","type":["string","null"]},"status":{"description":"`completed`, `partial` or `failed`.","type":["string","null"]},"charge_credits":{"description":"What the Run cost, as `GET /v1/runs/{id}` shows it.","type":["number","null"]},"tracker_id":{"description":"On `tracker.changed`.","type":["string","null"]},"change_report_id":{"description":"On `tracker.changed`.","type":["string","null"]},"collections":{"description":"On `tracker.changed` only: the Collections the Tracker sits in as of the event, by id and name, so you can route changes without a lookup. Absent on other events.","type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The Collection's id."},"name":{"type":"string","description":"The Collection's name."}},"required":["id","name"]}},"off_focus_count":{"description":"On `tracker.changed` for a Tracker with a Focus only: how many off-focus Videos the Change Report hid. The report's Videos are at `links.changes`.","type":["number","null"]},"links":{"description":"Absolute URLs to fetch the detail with your own key: `run`, `tracker`, `changes`, and `webhook` on a test event.","type":"object","additionalProperties":{"type":"string","format":"uri"}}},"required":["id","type","created_at","run_id","kind","status","charge_credits","tracker_id","change_report_id","links"]}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"description":"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`.","schema":{"type":"string"}},"MinViews":{"name":"min_views","in":"query","required":false,"description":"Keep videos with at least this many views. A video with no view count is excluded rather than assumed to be at zero.","schema":{"type":"integer","minimum":0}},"MaxViews":{"name":"max_views","in":"query","required":false,"description":"Keep videos with at most this many views.","schema":{"type":"integer","minimum":0}},"Platforms":{"name":"platforms","in":"query","required":false,"description":"Comma-separated, or repeated, each one of `tiktok`, `instagram`, `youtube`, `facebook`; any other value is a 400. Omit for every platform the research covered. There is no per-video `region`: a research collects under one region.","schema":{"type":"string","example":"tiktok,youtube"}},"StartDate":{"name":"start_date","in":"query","required":false,"description":"Keep videos posted at or after this ISO 8601 date (`2026-01-01`, midnight UTC) or date-time with `Z` or an explicit offset (`2026-01-01T00:00:00Z`). A video with no posted date is excluded.","schema":{"type":"string","example":"2026-01-01"}},"EndDate":{"name":"end_date","in":"query","required":false,"description":"Keep videos posted at or before this ISO 8601 date or date-time (a date-time needs `Z` or an explicit offset). A date alone (`2026-01-31`) includes the whole of that UTC day; a date-time is the exact instant. A video with no posted date is excluded.","schema":{"type":"string","example":"2026-01-31"}},"Creator":{"name":"creator","in":"query","required":false,"description":"A creator id or handle, with or without the `@`, matched case-insensitively.","schema":{"type":"string"}},"Hashtag":{"name":"hashtag","in":"query","required":false,"description":"A single hashtag, with or without the leading `#`.","schema":{"type":"string"}},"Sound":{"name":"sound","in":"query","required":false,"description":"A sound id, as `sound.id` carries it.","schema":{"type":"string"}},"OrderBy":{"name":"order_by","in":"query","required":false,"description":"`rank` is the research's own ordering — outlier, then views — which is what the digest was written from. It is that frozen order under either `as_of`: `latest` does not re-rank, so use `order_by=outlier` for the order over the numbers actually served. Ties break on `platform:id`, so paging never drops or repeats a video.","schema":{"type":"string","enum":["rank","outlier","views","posted_at"],"default":"rank"}},"Sort":{"name":"sort","in":"query","required":false,"description":"Direction. `desc` is best-first for every `order_by`. Videos missing the value being sorted on come last in both directions: unknown is not the same as smallest.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},"Limit":{"name":"limit","in":"query","required":false,"description":"Videos per page. Over the maximum, or negative, is a 400 rather than a silent clamp.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},"Offset":{"name":"offset","in":"query","required":false,"description":"Videos to skip. Past the end returns an empty page with the true `total`.","schema":{"type":"integer","minimum":0,"default":0}},"AsOf":{"name":"as_of","in":"query","required":false,"description":"Which snapshots to read. `run` (the default) is what the research saw, frozen, so the list agrees with the digest. `latest` serves the newest snapshot this API holds for each video, and filters and ordering run over those numbers (a `min_` filter means \"over that many now\"); `outlier` and `outlier_p90` are recomputed against the research's baseline, `velocity` and `percentile` stay as measured. `latest` is uneven until you refresh: a video is as fresh as the last time anything looked at it, else it keeps the research numbers; `POST /research/{id}/refresh` updates its refreshable videos (TikTok today). Every response states its basis.","schema":{"type":"string","enum":["run","latest"],"default":"run"}},"MinFollowers":{"name":"min_followers","in":"query","required":false,"description":"Keep creators with at least this many followers. A creator with no follower count is excluded rather than assumed to be at zero. Follower count is the one the research recorded, under either `as_of`: `latest` does not refresh it.","schema":{"type":"integer","minimum":0}},"MaxFollowers":{"name":"max_followers","in":"query","required":false,"description":"Keep creators with at most this many followers. Follower count is the one the research recorded, under either `as_of`: `latest` does not refresh it.","schema":{"type":"integer","minimum":0}},"Platforms_2":{"name":"platforms","in":"query","required":false,"description":"Comma-separated, or repeated, each one of `tiktok`, `instagram`, `youtube`, `facebook`; any other value is a 400. Omit for every platform the research covered.","schema":{"type":"string","example":"tiktok,youtube"}},"OrderBy_2":{"name":"order_by","in":"query","required":false,"description":"`outlier` is the best multiple any one of their videos hit. `median_views` is the baseline it was measured against, `views` their total across the shortlist, `video_count` how many of the shortlist is theirs, `followers` their follower count (unknown last; as recorded by the research, under either `as_of`). Ties break on total views (most first), then creator `id`, whatever the `order_by` or `sort` — the same order as the 25 inline on the research, so under `as_of=run` (the default) the default first page is that list and `offset=25` continues it.","schema":{"type":"string","enum":["outlier","median_views","followers","video_count","views"],"default":"outlier"}},"Sort_2":{"name":"sort","in":"query","required":false,"description":"Direction. `desc` is best-first for every `order_by`. Creators missing the value being sorted on come last in both directions: unknown is not the same as smallest.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},"Limit_2":{"name":"limit","in":"query","required":false,"description":"Creators per page. Over the maximum, or negative, is a 400 rather than a silent clamp.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},"Offset_2":{"name":"offset","in":"query","required":false,"description":"Creators to skip. Past the end returns an empty page with the true `total`.","schema":{"type":"integer","minimum":0,"default":0}},"Platforms_3":{"name":"platforms","in":"query","required":false,"description":"Comma-separated, or repeated, each one of `tiktok`, `instagram`, `youtube`, `facebook`; any other value is a 400. Omit for every platform the research covered. A tag is kept if it was seen on any platform you name; its counts still cover every platform.","schema":{"type":"string","example":"tiktok,youtube"}},"OrderBy_3":{"name":"order_by","in":"query","required":false,"description":"`video_count` is how many of the shortlist carried the tag, `views` their views added up. Ties break on total views (most first), then the tag itself, whatever the `order_by` or `sort` — the same order as the 25 inline on the research, so under `as_of=run` (the default) the default first page is that list and `offset=25` continues it.","schema":{"type":"string","enum":["video_count","views"],"default":"video_count"}},"Sort_3":{"name":"sort","in":"query","required":false,"description":"Direction. `desc` is best-first for every `order_by`. Hashtags missing the value being sorted on come last in both directions: unknown is not the same as smallest.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},"Limit_3":{"name":"limit","in":"query","required":false,"description":"Hashtags per page. Over the maximum, or negative, is a 400 rather than a silent clamp.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},"Offset_3":{"name":"offset","in":"query","required":false,"description":"Hashtags to skip. Past the end returns an empty page with the true `total`.","schema":{"type":"integer","minimum":0,"default":0}},"Platforms_4":{"name":"platforms","in":"query","required":false,"description":"Comma-separated, or repeated, each one of `tiktok`, `instagram`, `youtube`, `facebook`; any other value is a 400. Omit for every platform the research covered. A sound is kept if it was seen on any platform you name; its counts still cover every platform.","schema":{"type":"string","example":"tiktok,youtube"}},"OrderBy_4":{"name":"order_by","in":"query","required":false,"description":"`video_count` is how many of the shortlist used the sound, `views` their views added up. Ties break on total views (most first), then the sound id, whatever the `order_by` or `sort` — the same order as the 25 inline on the research, so under `as_of=run` (the default) the default first page is that list and `offset=25` continues it.","schema":{"type":"string","enum":["video_count","views"],"default":"video_count"}},"Sort_4":{"name":"sort","in":"query","required":false,"description":"Direction. `desc` is best-first for every `order_by`. Sounds missing the value being sorted on come last in both directions: unknown is not the same as smallest.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},"Limit_4":{"name":"limit","in":"query","required":false,"description":"Sounds per page. Over the maximum, or negative, is a 400 rather than a silent clamp.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},"Offset_4":{"name":"offset","in":"query","required":false,"description":"Sounds to skip. Past the end returns an empty page with the true `total`.","schema":{"type":"integer","minimum":0,"default":0}},"AsOf_2":{"name":"as_of","in":"query","required":false,"description":"Accepted for symmetry with the other research reads, so one basis can be passed to all of them, and validated like theirs. A digest is always served as `run` whichever you pass: it is what a model wrote about the shortlist the research collected, and there is no fresher one to serve.","schema":{"type":"string","enum":["run","latest"],"default":"run"}},"Wait":{"name":"wait","in":"query","required":false,"description":"Seconds to hold the response open before handing back a running Run to poll. Default 30, max 120. A POST may send it in the body instead; different values in both places are a 400.","schema":{"type":"integer","minimum":0,"maximum":120,"default":30}},"MaxCredits":{"name":"max_credits","in":"query","required":false,"description":"Most Credits the call may cost. A higher quote is a 402 `max_credits_exceeded`, no Run. Where `x-price.max_credits` is null, the Run stops at it and settles `partial`.","schema":{"type":"integer","minimum":0}},"Estimate":{"name":"estimate","in":"query","required":false,"description":"`true` returns `{ estimate_credits, cached }` from what is already stored, creating no Run. Nothing is charged. Only `true` or `false`, else a 400. A POST may send it in the body instead; different values in both places are a 400.","schema":{"type":"boolean"}},"Estimate_2":{"name":"estimate","in":"query","required":false,"description":"`true` returns `{ estimate_credits, cached }` from what is already stored, creating no Run. Nothing is charged. If a source the call would read is unavailable and the cache cannot answer, the estimate adds `unavailable` (the `{ platform, capability }` parts it cannot reach), or is a 503 `source_unavailable` when it can reach none. Only `true` or `false`, else a 400. A POST may send it in the body instead; different values in both places are a 400.","schema":{"type":"boolean"}},"Limit_5":{"name":"limit","in":"query","required":false,"description":"Items per page.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},"Cursor":{"name":"cursor","in":"query","required":false,"description":"Opaque `next_cursor` from the previous page.","schema":{"type":"string"}},"Limit_6":{"name":"limit","in":"query","required":false,"description":"Items per page.","schema":{"type":"integer","minimum":1,"maximum":30,"default":25}},"Estimate_3":{"name":"estimate","in":"query","required":false,"description":"Return `{ estimate_credits, cached, already_tracking, tracker_id, per_cycle }` and change nothing: zero when the target is already tracked, else one cycle, the first. Nothing is created or charged.","schema":{"type":"boolean"}},"IncludeOffFocus":{"name":"include_off_focus","in":"query","required":false,"description":"`true`: each report with a Focus also lists the off-focus Videos it hid, as `off_focus_videos`, each with `focus: { verdict, reason }`. Default: not listed.","schema":{"type":"boolean"}}},"responses":{"CreateResearch202":{"description":"Still running: `{ run }`. Poll `GET /v1/runs/{id}`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningEnvelope"},"example":{"run":{"id":"run_8f2c1ad04b","kind":"research","status":"running","created_at":"2026-09-08T09:14:02.418Z","completed_at":null,"charge_credits":0,"list_price_credits":0,"cached":false},"poll_url":"https://www.shortsintel.com/v1/runs/run_8f2c1ad04b"}}}},"Problem400":{"description":"`invalid_request` (a malformed id, `wait`, `estimate` or Idempotency-Key) or `unsupported_platform`, refused before any Run opens. Nothing is charged.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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`.","retryable":false,"action":"Fix the field named in `detail`, then send the corrected request."}}}},"Problem401":{"description":"`missing_authorization`, `invalid_key`, `key_revoked`, `key_expired` or `invalid_token`.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":false,"action":"Check the whole key was copied, or create a new key in the console."}}},"headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"}}},"Problem409":{"description":"`idempotency_conflict` — the same Idempotency-Key with a different payload.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":false,"action":"Resend the original payload with this key, or use a new key for the new payload.","run_id":"run_8f2c1ad04b"}}}},"Problem429":{"description":"`rate_limit_exceeded` or `concurrency_limit_exceeded`, with `Retry-After`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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`.","retryable":true,"action":"Wait `retry_after_seconds`, then retry the same request.","limit":60,"retry_after_seconds":12,"resets_at":"2026-09-08T09:15:00.000Z"}}}},"Problem502":{"description":"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.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Retry with a backoff; nothing was charged.","run":{"id":"run_8f2c1ad04b","kind":"research","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}}}}},"Problem503":{"description":"`source_unavailable`: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; `endpoints` names the source. Wait `retry_after_seconds` (also sent as `Retry-After`) and retry rather than treating it as empty.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Wait `retry_after_seconds`, then retry; do not treat this as an empty result.","endpoints":["tiktok/video"],"run":{"id":"run_8f2c1ad04b","kind":"research","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},"retry_after_seconds":60}}}},"GetResearch200":{"description":"`{ run, result }` once the research has settled.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"$ref":"#/components/schemas/ResearchSummary"}},"required":["result"]}]},"example":{"run":{"id":"run_c07a41bb92","kind":"research","status":"partial","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":500,"list_price_credits":500,"cached":false},"result":{"digest_version":2,"mode":"keywords","intent":"why are cold plunge videos taking off","keywords":["cold plunge","ice bath","cold exposure","cold plunge routine"],"keyword_rationale":"The intent is about a practice rather than a product, so the keywords cover the practice and its two common synonyms.","coverage":{"tiktok":"complete","instagram":"partial"},"digest":{"summary":"Cold plunge videos are travelling on measured personal diaries rather than on science explainers. The videos that break out open on an unimpressive first number and pay it off with a later one, and keep the discomfort on camera instead of cutting around it. Sentiment is broadly positive, with the negative share concentrated on the cost of equipment.","themes":[{"name":"30-day diaries","share":0.45,"description":"One creator, one tub, a counter on screen, and the change stated as a number rather than a feeling.","video_ids":["tiktok:7300000000000000000"]},{"name":"Before-workout plunging","share":0.2,"description":"Shorter clips arguing about timing relative to training, usually with a gym setting.","video_ids":["tiktok:7300000000000000042"]}],"hooks":[{"text":"Day one I lasted eleven seconds.","video_id":"tiktok:7300000000000000000","hook_type":"stat","why_it_works":"An unimpressive concrete number sets up a payoff the viewer stays for.","template":"Day one I lasted [small number] [unit].","lift":{"value":"STORY","video_count":9,"median_views":1840000,"median_engagement_rate":0.0912,"views_lift":1.6,"engagement_lift":1.21,"low_confidence":false}}],"sentiment":{"positive":0.62,"neutral":0.23,"negative":0.15,"note":"Enthusiasm for the routine itself; the negative share is almost entirely the price of a tub."},"angles":[{"angle":"Open on the day-30 number and work backwards to day one.","rationale":"Every diary in the shortlist that led with the outcome outperformed the ones that led with the method."}],"gaps":[{"ask":"Viewers want a cold plunge setup that does not cost hundreds.","comments":[{"text":"ok but what do I do if I can't afford a 600 dollar tub","video_id":"tiktok:7300000000000000000"}],"angle":"A 30-day diary on a chest freezer or bathtub build, with the receipt on screen."}]},"research":{"requested":50,"completed":48,"failed":2,"cached":11,"fresh":37,"max_videos":50,"included_videos":50}}}}}},"GetResearch202":{"description":"`{ run }` while the research is still collecting — the same body `GET /v1/runs/{id}` returns, not an error. `run.progress` says how far it has got.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningEnvelope"},"example":{"run":{"id":"run_c07a41bb92","kind":"research","status":"running","created_at":"2026-09-08T09:14:02.418Z","completed_at":null,"charge_credits":0,"list_price_credits":0,"cached":false,"progress":{"stage":"analysing","keywords":6,"searches":12,"found":214,"judged":100,"kept":81,"dropped_off_topic":17,"dropped_unsure":2,"shortlisted":50,"analysed":32,"updated_at":"2026-09-08T09:14:41.007Z"}},"poll_url":"https://www.shortsintel.com/v1/runs/run_c07a41bb92"}}}},"Problem404":{"description":"`not_found`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/not_found","title":"Not found","status":404,"code":"not_found","detail":"No research with that id for this Customer.","retryable":false,"action":"Check the id or handle; list your resources to find the right one."}}}},"Problem502_2":{"description":"A research whose Run failed is answered as `application/problem+json` with its problem's status, the problem members beside the unchanged Run envelope — exactly as `GET /v1/runs/{id}` answers it.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Retry with a backoff; nothing was charged.","run":{"id":"run_c07a41bb92","kind":"research","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}}}}},"ListResearchVideos200":{"description":"`{ items, total, limit, offset, as_of }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResearchVideos"},"example":{"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","author":"someone","is_original":true},"creator":{"id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","verified":false},"region":"US","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[{"kind":"54","label":"CapCut · Editing made easy"}]},"people":{"mentions":["coldplungeco"],"collaborators":[]},"location":null,"topics":{"keywords":[],"genre":null,"labels":["Fitness","Health"]},"chapters":null,"ai_generated":false,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":1284000,"likes":143200,"comments":2810,"shares":9040,"saves":21600},"scores":{"outlier":4.21,"outlier_p90":1.6,"percentile":95,"velocity":{"views_per_hour":6698.6,"window":"snapshot"},"reason":null,"baseline":{"median_views":305000,"p90_views":802000,"engagement_rate":0.1342,"posts_per_week":4.1,"sample":20,"confidence":"high","source":"videos","computed_at":"2026-09-08T09:14:03.902Z","stale":false}},"rank":0,"item_id":"ri_5c30f18ab4","cached":true},{"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","author":"Northbound","is_original":false},"creator":{"id":"cre_1a77c0b3de","handle":"anotherone","name":"Another One","follower_count":21400,"avatar_url":null,"verified":null},"region":"GB","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[]},"people":null,"location":null,"topics":null,"chapters":null,"ai_generated":null,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":96200,"likes":8140,"comments":212,"shares":401,"saves":1180},"scores":null,"rank":1,"item_id":"ri_5c30f18ab5","cached":false}],"total":48,"limit":25,"offset":0,"as_of":"run"}}}},"Problem400_2":{"description":"`invalid_request` — an unknown platform, a `min_views` or `max_views` that is not a non-negative integer, an unparseable date, an unknown `order_by`, `sort` or `as_of`, a `limit` outside 1 to 100, or a negative or non-integer `offset`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/invalid_request","title":"Invalid request","status":400,"code":"invalid_request","detail":"`limit` must be an integer between 1 and 100, and `offset` a non-negative integer.","retryable":false,"action":"Fix the field named in `detail`, then send the corrected request."}}}},"Problem409_2":{"description":"`run_not_ready` — the research is still running, or failed with nothing to serve. If it is still running, poll `GET /v1/runs/{id}` and read again once it settles; a failed research never becomes readable.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/run_not_ready","title":"Run not ready","status":409,"code":"run_not_ready","detail":"Research `run_c07a41bb92` is still running. Poll GET /v1/runs/run_c07a41bb92 until it reaches a terminal status.","retryable":true,"action":"Poll the Run until it settles, then read again. If it failed, start a new Run."}}}},"ListResearchCreators200":{"description":"`{ items, total, limit, offset, as_of }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResearchCreators"},"example":{"items":[{"platform":"tiktok","id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","video_count":3,"best_outlier":4.21,"median_views":305000,"total_views":1611400,"video_ids":["tiktok:7300000000000000000"]}],"total":31,"limit":25,"offset":0,"as_of":"run"}}}},"Problem400_3":{"description":"`invalid_request` — an unknown platform, a `min_followers` or `max_followers` that is not a non-negative integer, an unknown `order_by`, `sort` or `as_of`, a `limit` outside 1 to 100, or a negative or non-integer `offset`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/invalid_request","title":"Invalid request","status":400,"code":"invalid_request","detail":"`limit` must be an integer between 1 and 100, and `offset` a non-negative integer.","retryable":false,"action":"Fix the field named in `detail`, then send the corrected request."}}}},"ListResearchHashtags200":{"description":"`{ items, total, limit, offset, as_of }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResearchHashtags"},"example":{"items":[{"value":"coldplunge","platforms":["instagram","tiktok"],"video_count":34,"total_views":18402000,"video_ids":["tiktok:7300000000000000000","instagram:C9xExampleShortcode"]}],"total":62,"limit":25,"offset":0,"as_of":"run"}}}},"Problem400_4":{"description":"`invalid_request` — an unknown platform, an unknown `order_by`, `sort` or `as_of`, a `limit` outside 1 to 100, or a negative or non-integer `offset`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/invalid_request","title":"Invalid request","status":400,"code":"invalid_request","detail":"`limit` must be an integer between 1 and 100, and `offset` a non-negative integer.","retryable":false,"action":"Fix the field named in `detail`, then send the corrected request."}}}},"ListResearchSounds200":{"description":"`{ items, total, limit, offset, as_of }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResearchSounds"},"example":{"items":[{"value":"7180000000000000000","title":"original sound - someone","author":"someone","is_original":true,"platforms":["tiktok"],"video_count":4,"total_views":2140000,"video_ids":["tiktok:7300000000000000000"]}],"total":27,"limit":25,"offset":0,"as_of":"run"}}}},"GetResearchDigest200":{"description":"The digest, with the context it was computed in. `as_of` always reads `run` here: a digest is what a model wrote about the shortlist the research collected, not a number joined to a snapshot, so there is no fresher one to serve.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"digest":{"$ref":"#/components/schemas/Digest"},"digest_version":{"type":"integer"},"lift_tables":{"$ref":"#/components/schemas/LiftTables"},"mode":{"type":"string","enum":["keywords","creators"],"description":"What the research was seeded with: `keywords` (an intent) or `creators` (a breakdown). Absent means `keywords`."},"intent":{"type":"string"},"keywords":{"type":"array","items":{"type":"string"}},"keyword_rationale":{"type":"string"},"coverage":{"type":"object","additionalProperties":{"type":"string"}},"as_of":{"type":"string","enum":["run","latest"],"description":"Which snapshots the numbers come from: `run` is what the research itself saw, frozen, so a read always agrees with the digest; `latest` is the newest snapshot this API holds for each video."}},"required":["digest","digest_version","coverage","as_of"],"description":"A research's digest with the intent, keywords and coverage it was computed in — and none of the evidence."},"example":{"digest":{"summary":"Cold plunge videos are travelling on measured personal diaries rather than on science explainers. The videos that break out open on an unimpressive first number and pay it off with a later one, and keep the discomfort on camera instead of cutting around it. Sentiment is broadly positive, with the negative share concentrated on the cost of equipment.","themes":[{"name":"30-day diaries","share":0.45,"description":"One creator, one tub, a counter on screen, and the change stated as a number rather than a feeling.","video_ids":["tiktok:7300000000000000000"]},{"name":"Before-workout plunging","share":0.2,"description":"Shorter clips arguing about timing relative to training, usually with a gym setting.","video_ids":["tiktok:7300000000000000042"]}],"hooks":[{"text":"Day one I lasted eleven seconds.","video_id":"tiktok:7300000000000000000","hook_type":"stat","why_it_works":"An unimpressive concrete number sets up a payoff the viewer stays for.","template":"Day one I lasted [small number] [unit].","lift":{"value":"STORY","video_count":9,"median_views":1840000,"median_engagement_rate":0.0912,"views_lift":1.6,"engagement_lift":1.21,"low_confidence":false}}],"sentiment":{"positive":0.62,"neutral":0.23,"negative":0.15,"note":"Enthusiasm for the routine itself; the negative share is almost entirely the price of a tub."},"angles":[{"angle":"Open on the day-30 number and work backwards to day one.","rationale":"Every diary in the shortlist that led with the outcome outperformed the ones that led with the method."}],"gaps":[{"ask":"Viewers want a cold plunge setup that does not cost hundreds.","comments":[{"text":"ok but what do I do if I can't afford a 600 dollar tub","video_id":"tiktok:7300000000000000000"}],"angle":"A 30-day diary on a chest freezer or bathtub build, with the receipt on screen."}]},"digest_version":2,"mode":"keywords","intent":"why are cold plunge videos taking off","keywords":["cold plunge","ice bath","cold exposure","cold plunge routine"],"keyword_rationale":"The intent is about a practice rather than a product, so the keywords cover the practice and its two common synonyms.","coverage":{"tiktok":"complete","instagram":"partial"},"as_of":"run"}}}},"Problem400_5":{"description":"`invalid_request` — an unknown `as_of`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/invalid_request","title":"Invalid request","status":400,"code":"invalid_request","detail":"`as_of` must be one of run, latest.","retryable":false,"action":"Fix the field named in `detail`, then send the corrected request."}}}},"RefreshResearch200":{"description":"The sweep finished inside the wait budget: `{ run, result }`. The example is a `partial` run — two of the fifty videos have been deleted since the research ran, so forty-eight were swept and charged for. With `estimate=true`, `{ estimate_credits, cached, videos, per_video_credits, max_estimate_credits, note }` instead: `videos` is how many will be swept, `max_estimate_credits` equals `estimate_credits` because a video that fails is not charged, and `note` says so — and, when some of the research's videos are on a platform that cannot be refreshed yet, how many are left out.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"type":"object","properties":{"research_id":{"type":"string","description":"The research whose videos were swept."},"requested":{"type":"integer"},"refreshed":{"type":"integer","description":"Videos we fetched fresh numbers for, and the only ones charged for."},"failed":{"type":"integer"},"per_video_credits":{"type":"integer"},"note":{"type":"string"}},"required":["research_id","requested","refreshed","failed","per_video_credits","note"],"description":"What a refresh swept. Frozen reads are unchanged by it; `as_of=latest` serves the new snapshots."}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"research_refresh","status":"partial","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":144,"list_price_credits":150,"cached":false},"result":{"research_id":"run_c07a41bb92","requested":50,"refreshed":48,"failed":2,"per_video_credits":3,"note":"Frozen reads are unchanged. `as_of=latest` now serves these snapshots."}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":150,"cached":false,"videos":50,"per_video_credits":3,"max_estimate_credits":150,"note":"A video we cannot fetch is not charged, so the final charge is at or below this quote."}}}}}},"RefreshResearch202":{"description":"Still running: `{ run }`. Poll `GET /v1/runs/{id}`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningEnvelope"},"example":{"run":{"id":"run_8f2c1ad04b","kind":"research_refresh","status":"running","created_at":"2026-09-08T09:14:02.418Z","completed_at":null,"charge_credits":0,"list_price_credits":0,"cached":false},"poll_url":"https://www.shortsintel.com/v1/runs/run_8f2c1ad04b"}}}},"Problem402":{"description":"`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`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/insufficient_balance","title":"Insufficient balance","status":402,"code":"insufficient_balance","detail":"Your balance is 0 Credits and this operation needs 150 Credits. Nothing was charged.","retryable":false,"action":"Tell the Customer to top up the Balance, then repeat the same request.","balance_credits":0,"required_credits":150}}}},"Problem409_3":{"description":"`run_not_ready` — the research is still running, or failed with nothing to serve. If it is still running, poll `GET /v1/runs/{id}` and refresh once it settles; a failed research never becomes readable. Also `idempotency_conflict` — the same Idempotency-Key sent for a different research.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/run_not_ready","title":"Run not ready","status":409,"code":"run_not_ready","detail":"Research `run_c07a41bb92` is still running. Poll GET /v1/runs/run_c07a41bb92 until it reaches a terminal status.","retryable":true,"action":"Poll the Run until it settles, then read again. If it failed, start a new Run."}}}},"Problem502_3":{"description":"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.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Retry with a backoff; nothing was charged.","run":{"id":"run_8f2c1ad04b","kind":"research_refresh","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}}}}},"Problem503_2":{"description":"`source_unavailable`: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; `endpoints` names the source. Wait `retry_after_seconds` (also sent as `Retry-After`) and retry rather than treating it as empty.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Wait `retry_after_seconds`, then retry; do not treat this as an empty result.","endpoints":["tiktok/video"],"run":{"id":"run_8f2c1ad04b","kind":"research_refresh","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},"retry_after_seconds":60}}}},"Problem402_2":{"description":"`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`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/insufficient_balance","title":"Insufficient balance","status":402,"code":"insufficient_balance","detail":"Your balance is 0 Credits and this operation needs 3 Credits. Nothing was charged.","retryable":false,"action":"Tell the Customer to top up the Balance, then repeat the same request.","balance_credits":0,"required_credits":3}}}},"LookupVideo202":{"description":"Still running: `{ run }`. Poll `GET /v1/runs/{id}`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningEnvelope"},"example":{"run":{"id":"run_8f2c1ad04b","kind":"video_lookup","status":"running","created_at":"2026-09-08T09:14:02.418Z","completed_at":null,"charge_credits":0,"list_price_credits":0,"cached":false},"poll_url":"https://www.shortsintel.com/v1/runs/run_8f2c1ad04b"}}}},"Problem502_4":{"description":"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.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Retry with a backoff; nothing was charged.","run":{"id":"run_8f2c1ad04b","kind":"video_lookup","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}}}}},"Problem503_3":{"description":"`source_unavailable`: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; `endpoints` names the source. Wait `retry_after_seconds` (also sent as `Retry-After`) and retry rather than treating it as empty.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Wait `retry_after_seconds`, then retry; do not treat this as an empty result.","endpoints":["tiktok/video"],"run":{"id":"run_8f2c1ad04b","kind":"video_lookup","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},"retry_after_seconds":60}}}},"Problem400_6":{"description":"`invalid_request` for a `cursor` that is not a `next_cursor` this API issued. Nothing is charged.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/invalid_request","title":"Invalid request","status":400,"code":"invalid_request","detail":"`cursor` is not a cursor this API issued. Pass back the `next_cursor` from the previous page.","retryable":false,"action":"Fix the field named in `detail`, then send the corrected request."}}}},"Problem404_2":{"description":"`not_found` — including anything belonging to another Customer.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/not_found","title":"Not found","status":404,"code":"not_found","detail":"No such resource for this Customer.","retryable":false,"action":"Check the id or handle; list your resources to find the right one."}}}},"Problem402_3":{"description":"`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`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/insufficient_balance","title":"Insufficient balance","status":402,"code":"insufficient_balance","detail":"Your balance is 0 Credits and this operation needs 6 Credits. Nothing was charged.","retryable":false,"action":"Tell the Customer to top up the Balance, then repeat the same request.","balance_credits":0,"required_credits":6}}}},"GetHashtag202":{"description":"Still running: `{ run }`. Poll `GET /v1/runs/{id}`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningEnvelope"},"example":{"run":{"id":"run_8f2c1ad04b","kind":"hashtag_lookup","status":"running","created_at":"2026-09-08T09:14:02.418Z","completed_at":null,"charge_credits":0,"list_price_credits":0,"cached":false},"poll_url":"https://www.shortsintel.com/v1/runs/run_8f2c1ad04b"}}}},"Problem502_5":{"description":"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.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Retry with a backoff; nothing was charged.","run":{"id":"run_8f2c1ad04b","kind":"hashtag_lookup","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}}}}},"Problem503_4":{"description":"`source_unavailable`: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; `endpoints` names the source. Wait `retry_after_seconds` (also sent as `Retry-After`) and retry rather than treating it as empty.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Wait `retry_after_seconds`, then retry; do not treat this as an empty result.","endpoints":["tiktok/video"],"run":{"id":"run_8f2c1ad04b","kind":"hashtag_lookup","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},"retry_after_seconds":60}}}},"GetSound202":{"description":"Still running: `{ run }`. Poll `GET /v1/runs/{id}`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningEnvelope"},"example":{"run":{"id":"run_8f2c1ad04b","kind":"sound_lookup","status":"running","created_at":"2026-09-08T09:14:02.418Z","completed_at":null,"charge_credits":0,"list_price_credits":0,"cached":false},"poll_url":"https://www.shortsintel.com/v1/runs/run_8f2c1ad04b"}}}},"Problem502_6":{"description":"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.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Retry with a backoff; nothing was charged.","run":{"id":"run_8f2c1ad04b","kind":"sound_lookup","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}}}}},"Problem503_5":{"description":"`source_unavailable`: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; `endpoints` names the source. Wait `retry_after_seconds` (also sent as `Retry-After`) and retry rather than treating it as empty.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Wait `retry_after_seconds`, then retry; do not treat this as an empty result.","endpoints":["tiktok/video"],"run":{"id":"run_8f2c1ad04b","kind":"sound_lookup","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},"retry_after_seconds":60}}}},"GetMetaAd202":{"description":"Still running: `{ run }`. Poll `GET /v1/runs/{id}`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningEnvelope"},"example":{"run":{"id":"run_8f2c1ad04b","kind":"ad_lookup","status":"running","created_at":"2026-09-08T09:14:02.418Z","completed_at":null,"charge_credits":0,"list_price_credits":0,"cached":false},"poll_url":"https://www.shortsintel.com/v1/runs/run_8f2c1ad04b"}}}},"Problem502_7":{"description":"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.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Retry with a backoff; nothing was charged.","run":{"id":"run_8f2c1ad04b","kind":"ad_lookup","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}}}}},"Problem503_6":{"description":"`source_unavailable`: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; `endpoints` names the source. Wait `retry_after_seconds` (also sent as `Retry-After`) and retry rather than treating it as empty.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Wait `retry_after_seconds`, then retry; do not treat this as an empty result.","endpoints":["tiktok/video"],"run":{"id":"run_8f2c1ad04b","kind":"ad_lookup","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},"retry_after_seconds":60}}}},"Problem429_2":{"description":"`rate_limit_exceeded`, with `Retry-After`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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`.","retryable":true,"action":"Wait `retry_after_seconds`, then retry the same request.","limit":60,"retry_after_seconds":12,"resets_at":"2026-09-08T09:15:00.000Z"}}}},"Problem404_3":{"description":"`not_found`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/not_found","title":"Not found","status":404,"code":"not_found","detail":"No Tracker with that id for this Customer.","retryable":false,"action":"Check the id or handle; list your resources to find the right one."}}}},"Problem404_4":{"description":"`not_found`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/not_found","title":"Not found","status":404,"code":"not_found","detail":"No Collection with that id for this Customer.","retryable":false,"action":"Check the id or handle; list your resources to find the right one."}}}},"Problem403":{"description":"`forbidden` — the key's or connection's user is a MEMBER; only an owner or admin manages webhooks.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/forbidden","title":"Forbidden","status":403,"code":"forbidden","detail":"Only an owner or admin can manage webhooks.","retryable":false,"action":"Ask an organization owner or admin to do this, or to grant the role."}}}}}},"paths":{"/research":{"post":{"operationId":"createResearch","summary":"Research a niche","description":"Derives keywords from an intent, searches every platform and produces one Digest.\n\n- **Pipeline:** de-duplicates by platform id, analyses the top `max_videos`, scores them against their creators' baselines, then ranks them.\n- **Timing:** always async. Typically 1-3 minutes for 50 videos, depending on how busy the video analysis service is, and longer toward 200. `run.progress` says how far it has got.\n- **Evidence:** the full lists page at `GET /v1/runs/{id}/items?type=videos|creators|hashtags|sounds`.\n- **Facebook:** opt-in. Name it in `platforms` and it is searched and analysed like the others, at the same price.\n- **Coverage:** Instagram and Facebook are reported as `coverage: \"partial\"`.\n\n**Price:** 1,036 credits covering up to 50 enriched videos, then 20 credits each, whether the analysis is fresh or already stored, so at most 4,036 credits at `max_videos` 200. Failed videos are never charged. The 402 pre-check uses that worst case.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=createResearch) (no API Key needed).","tags":["Research"],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"intent":{"type":"string","minLength":1,"maxLength":1000,"description":"What you want to learn, in plain language. At most 1000 characters."},"keywords":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"maxItems":4,"description":"Skip keyword derivation and use these. At most 4, each at most 100 characters."},"platforms":{"type":"array","items":{"type":"string","enum":["tiktok","instagram","youtube","facebook"]},"minItems":1,"description":"Omit for TikTok, Instagram and YouTube. `facebook` is opt-in: name it to research Facebook videos and Reels too; they are analysed like the others, at the same price."},"region":{"type":"string","minLength":2,"maxLength":5,"description":"Country code, such as `US` or `GB`, that the TikTok and YouTube searches run from; Instagram and Facebook ignore it. Omitted, each platform uses its own default."},"window":{"type":"string","enum":["day","week","month","quarter","half_year","all"],"default":"month","description":"Collect videos posted within the last `day`, `week`, `month` (the default), `quarter` or `half_year`, or `all` for no limit. Each platform applies its nearest window: Instagram has a week, a month and a year; YouTube has a day, a week and a month, and searches without a limit past that."},"max_videos":{"type":"integer","minimum":1,"maximum":200,"description":"Videos to enrich. Default 50, max 200."},"wait":{"type":"number","minimum":0,"maximum":120,"default":30,"description":"Seconds to hold the response open before returning a running Run to poll. Default 30, max 120."},"max_credits":{"type":"integer","minimum":0,"description":"As in the query."},"estimate":{"type":"boolean","description":"If a source the call would read is unavailable and the cache cannot answer, the estimate adds `unavailable` (the `{ platform, capability }` parts it cannot reach), or is a 503 `source_unavailable` when it can reach none."}},"required":["intent"],"additionalProperties":false}}}},"responses":{"200":{"description":"The Run finished: `{ run, result }`. Research is always async, so in practice this arrives from `GET /v1/runs/{id}`. The example is a `partial` Run: two of the fifty videos could not be fetched, and neither was charged for.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"$ref":"#/components/schemas/Research"}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"research","status":"partial","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":1036,"list_price_credits":1036,"cached":false},"result":{"digest_version":2,"mode":"keywords","intent":"why are cold plunge videos taking off","keywords":["cold plunge","ice bath","cold exposure","cold plunge routine"],"keyword_rationale":"The intent is about a practice rather than a product, so the keywords cover the practice and its two common synonyms.","coverage":{"tiktok":"complete","instagram":"partial"},"digest":{"summary":"Cold plunge videos are travelling on measured personal diaries rather than on science explainers. The videos that break out open on an unimpressive first number and pay it off with a later one, and keep the discomfort on camera instead of cutting around it. Sentiment is broadly positive, with the negative share concentrated on the cost of equipment.","themes":[{"name":"30-day diaries","share":0.45,"description":"One creator, one tub, a counter on screen, and the change stated as a number rather than a feeling.","video_ids":["tiktok:7300000000000000000"]},{"name":"Before-workout plunging","share":0.2,"description":"Shorter clips arguing about timing relative to training, usually with a gym setting.","video_ids":["tiktok:7300000000000000042"]}],"hooks":[{"text":"Day one I lasted eleven seconds.","video_id":"tiktok:7300000000000000000","hook_type":"stat","why_it_works":"An unimpressive concrete number sets up a payoff the viewer stays for.","template":"Day one I lasted [small number] [unit].","lift":{"value":"STORY","video_count":9,"median_views":1840000,"median_engagement_rate":0.0912,"views_lift":1.6,"engagement_lift":1.21,"low_confidence":false}}],"sentiment":{"positive":0.62,"neutral":0.23,"negative":0.15,"note":"Enthusiasm for the routine itself; the negative share is almost entirely the price of a tub."},"angles":[{"angle":"Open on the day-30 number and work backwards to day one.","rationale":"Every diary in the shortlist that led with the outcome outperformed the ones that led with the method."}],"gaps":[{"ask":"Viewers want a cold plunge setup that does not cost hundreds.","comments":[{"text":"ok but what do I do if I can't afford a 600 dollar tub","video_id":"tiktok:7300000000000000000"}],"angle":"A 30-day diary on a chest freezer or bathtub build, with the receipt on screen."}]},"videos":[{"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","author":"someone","is_original":true},"creator":{"id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","verified":false},"region":"US","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[{"kind":"54","label":"CapCut · Editing made easy"}]},"people":{"mentions":["coldplungeco"],"collaborators":[]},"location":null,"topics":{"keywords":[],"genre":null,"labels":["Fitness","Health"]},"chapters":null,"ai_generated":false,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":1284000,"likes":143200,"comments":2810,"shares":9040,"saves":21600},"scores":{"outlier":4.21,"outlier_p90":1.6,"percentile":95,"velocity":{"views_per_hour":6698.6,"window":"snapshot"},"reason":null,"baseline":{"median_views":305000,"p90_views":802000,"engagement_rate":0.1342,"posts_per_week":4.1,"sample":20,"confidence":"high","source":"videos","computed_at":"2026-09-08T09:14:03.902Z","stale":false}}},{"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","author":"Northbound","is_original":false},"creator":{"id":"cre_1a77c0b3de","handle":"anotherone","name":"Another One","follower_count":21400,"avatar_url":null,"verified":null},"region":"GB","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[]},"people":null,"location":null,"topics":null,"chapters":null,"ai_generated":null,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":96200,"likes":8140,"comments":212,"shares":401,"saves":1180},"scores":null}],"creators":[{"platform":"tiktok","id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","video_count":3,"best_outlier":4.21,"median_views":305000,"total_views":1611400,"video_ids":["tiktok:7300000000000000000"]}],"hashtags":[{"value":"coldplunge","platforms":["instagram","tiktok"],"video_count":34,"total_views":18402000,"video_ids":["tiktok:7300000000000000000","instagram:C9xExampleShortcode"]}],"sounds":[{"value":"7180000000000000000","title":"original sound - someone","author":"someone","is_original":true,"platforms":["tiktok"],"video_count":4,"total_views":2140000,"video_ids":["tiktok:7300000000000000000"]}],"research":{"requested":50,"completed":48,"failed":2,"cached":11,"fresh":37,"max_videos":50,"included_videos":50}}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":1036,"cached":false}}}}}},"202":{"$ref":"#/components/responses/CreateResearch202"},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"description":"`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`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/insufficient_balance","title":"Insufficient balance","status":402,"code":"insufficient_balance","detail":"Your balance is 0 Credits and this operation needs 1036 Credits. Nothing was charged.","retryable":false,"action":"Tell the Customer to top up the Balance, then repeat the same request.","balance_credits":0,"required_credits":1036}}}},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"$ref":"#/components/responses/Problem502"},"503":{"$ref":"#/components/responses/Problem503"}},"x-price":{"credits":1036,"unit":"call","max_credits":4036}}},"/research/{id}":{"get":{"operationId":"getResearch","summary":"Read a research's status","description":"What a research recorded about itself, without item lists. The videos, creators, hashtags and sounds behind the digest page separately.\n\n- **Returns:** the intent, the keywords derived from it and why, the coverage each platform reported, the requested, completed, failed, cached and fresh counts, and the digest.\n- **Still running:** a research id is its Run id, so this returns the Run envelope: 202 `{ run }` with status `running`, as polling answers. It is not an error.\n- **Failed:** as a failed Run polls, `application/problem+json` with the problem beside the envelope.\n- **Not found:** another Customer's id and a Run of another kind are the same 404.\n\n**Price:** Free, forever. Collection is the only thing charged.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=getResearch) (no API Key needed).","tags":["Research"],"parameters":[{"name":"id","in":"path","required":true,"description":"Research id — the id of the Run that collected it.","schema":{"type":"string"}}],"responses":{"200":{"$ref":"#/components/responses/GetResearch200"},"202":{"$ref":"#/components/responses/GetResearch202"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404"},"502":{"$ref":"#/components/responses/Problem502_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/research/{id}/videos":{"get":{"operationId":"listResearchVideos","summary":"Filter a research's videos","description":"The videos a research collected, filtered and ordered however you like. Filters compose. Ask a narrower question of a research you paid for (TikTok only, over 100k views, best outlier first) instead of running another.\n\n- **Paging:** `limit`/`offset` with a `total`, no `next_cursor`. A research is a frozen set of at most 200 rows in the order you choose, so a count is cheap and more useful.\n- **Past the end:** an empty page with the true `total`, not an error.\n- **Frozen numbers:** under `as_of=run`, the default, the numbers are as the research saw them, so the list agrees with the digest.\n- **Latest numbers:** under `as_of=latest` they are the newest this API holds and may not agree. The response's `as_of` says which you got.\n- **Errors:** A research that has not finished answers 409 `run_not_ready`.\n\n**Price:** Free, forever, filtered or not. Collection is the only thing charged.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=listResearchVideos) (no API Key needed).","tags":["Research"],"parameters":[{"name":"id","in":"path","required":true,"description":"Research id — the id of the Run that collected it.","schema":{"type":"string"}},{"$ref":"#/components/parameters/MinViews"},{"$ref":"#/components/parameters/MaxViews"},{"$ref":"#/components/parameters/Platforms"},{"$ref":"#/components/parameters/StartDate"},{"$ref":"#/components/parameters/EndDate"},{"$ref":"#/components/parameters/Creator"},{"$ref":"#/components/parameters/Hashtag"},{"$ref":"#/components/parameters/Sound"},{"$ref":"#/components/parameters/OrderBy"},{"$ref":"#/components/parameters/Sort"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"$ref":"#/components/parameters/AsOf"}],"responses":{"200":{"$ref":"#/components/responses/ListResearchVideos200"},"400":{"$ref":"#/components/responses/Problem400_2"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/research/{id}/creators":{"get":{"operationId":"listResearchCreators","summary":"Rank a research's creators","description":"The outlier creators a research surfaced, past the 25 the research response carries inline.\n\n- **Order:** by outlier by default, the best multiple any of their videos in this research hit.\n- **Filters:** follower count and platform.\n- **Nulls:** `best_outlier` and `median_views` are null, never zero, for a creator with no scored video. They sort last either way, because unknown is not smallest.\n- **Baseline:** `median_views` is the baseline the outlier was measured against, frozen at collection.\n- **Paging:** `total` and `as_of` as on the videos read.\n- **Errors:** A research that has not finished answers 409 `run_not_ready`.\n\n**Price:** Free, forever, filtered or not. Collection is the only thing charged.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=listResearchCreators) (no API Key needed).","tags":["Research"],"parameters":[{"name":"id","in":"path","required":true,"description":"Research id — the id of the Run that collected it.","schema":{"type":"string"}},{"$ref":"#/components/parameters/MinFollowers"},{"$ref":"#/components/parameters/MaxFollowers"},{"$ref":"#/components/parameters/Platforms_2"},{"$ref":"#/components/parameters/OrderBy_2"},{"$ref":"#/components/parameters/Sort_2"},{"$ref":"#/components/parameters/Limit_2"},{"$ref":"#/components/parameters/Offset_2"},{"$ref":"#/components/parameters/AsOf"}],"responses":{"200":{"$ref":"#/components/responses/ListResearchCreators200"},"400":{"$ref":"#/components/responses/Problem400_3"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/research/{id}/hashtags":{"get":{"operationId":"listResearchHashtags","summary":"Rank a research's hashtags","description":"The hashtags a research surfaced, past the 25 it carries inline.\n\n- **Order:** by `video_count` by default, or by `views`.\n- **Across platforms:** one row spans every platform the tag was seen on, because a research searches several to find what carries across. `platforms=tiktok` means \"tags that appeared on TikTok\", and the row still counts every video carrying the tag anywhere.\n- **Per-platform split:** `video_ids` are `platform:id`.\n- **Paging:** `total` and `as_of` as on the videos read.\n- **Errors:** A research that has not finished answers 409 `run_not_ready`.\n\n**Price:** Free, forever, filtered or not. Collection is the only thing charged.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=listResearchHashtags) (no API Key needed).","tags":["Research"],"parameters":[{"name":"id","in":"path","required":true,"description":"Research id — the id of the Run that collected it.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Platforms_3"},{"$ref":"#/components/parameters/OrderBy_3"},{"$ref":"#/components/parameters/Sort_3"},{"$ref":"#/components/parameters/Limit_3"},{"$ref":"#/components/parameters/Offset_3"},{"$ref":"#/components/parameters/AsOf"}],"responses":{"200":{"$ref":"#/components/responses/ListResearchHashtags200"},"400":{"$ref":"#/components/responses/Problem400_4"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/research/{id}/sounds":{"get":{"operationId":"listResearchSounds","summary":"Rank a research's sounds","description":"The sounds a research surfaced, past the 25 it carries inline.\n\n- **Order, filters, paging:** as on the hashtags read.\n- **Fields:** `value` is the sound id and `title` is its name, where a hashtag has none.\n- **Across platforms:** one rollup spans every platform the sound was seen on.\n- **Errors:** A research that has not finished answers 409 `run_not_ready`.\n\n**Price:** Free, forever, filtered or not. Collection is the only thing charged.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=listResearchSounds) (no API Key needed).","tags":["Research"],"parameters":[{"name":"id","in":"path","required":true,"description":"Research id — the id of the Run that collected it.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Platforms_4"},{"$ref":"#/components/parameters/OrderBy_4"},{"$ref":"#/components/parameters/Sort_4"},{"$ref":"#/components/parameters/Limit_4"},{"$ref":"#/components/parameters/Offset_4"},{"$ref":"#/components/parameters/AsOf"}],"responses":{"200":{"$ref":"#/components/responses/ListResearchSounds200"},"400":{"$ref":"#/components/responses/Problem400_4"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/research/{id}/digest":{"get":{"operationId":"getResearchDigest","summary":"Read a research's digest","description":"The digest alone, with the intent, keywords and coverage it was computed in, and none of the evidence. Use it to feed the synthesis into a prompt without the tokens for the rest.\n\n- **Overview:** `GET /v1/research/{id}` carries the digest too, beside the counts.\n- **Paging:** nothing pages, because a research has one digest.\n- **Frozen:** `as_of` is accepted as on every read, but always reads `run`.\n- **Not finished:** a research that has not finished answers 409 `run_not_ready` here, where the overview instead hands back the run to poll.\n\n**Price:** Free, forever. Collection is the only thing charged.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=getResearchDigest) (no API Key needed).","tags":["Research"],"parameters":[{"name":"id","in":"path","required":true,"description":"Research id — the id of the Run that collected it.","schema":{"type":"string"}},{"$ref":"#/components/parameters/AsOf_2"}],"responses":{"200":{"$ref":"#/components/responses/GetResearchDigest200"},"400":{"$ref":"#/components/responses/Problem400_5"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/research/{id}/refresh":{"post":{"operationId":"refreshResearch","summary":"Refresh a research's videos","description":"Sweeps fresh metrics for the videos a research serves, so you can see which of them kept growing.\n\n- **Reading the numbers:** afterwards `as_of=latest` on any research read serves these numbers. `as_of=run` stays byte for byte what the research recorded.\n- **Platforms:** only TikTok videos refresh today. Others are left out of the quote, sweep and charge and keep the research's numbers.\n- **Refused before any run:** 400 `unsupported_platform` with no TikTok videos, 400 `invalid_request` with no videos.\n- **Items:** one per video, each with its own status. Failed videos are uncharged, some failing makes the run partial, all failing makes it failed and free.\n- **Short Balance:** if the Balance runs short by settlement, the videos that came back are charged in order up to it and the rest fail with `insufficient_balance`, leaving the run partial.\n\n**Price:** 3 credits per video that comes back.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=refreshResearch) (no API Key needed).","tags":["Research"],"parameters":[{"name":"id","in":"path","required":true,"description":"Research id — the id of the Run that collected it.","schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Wait"},{"$ref":"#/components/parameters/MaxCredits"},{"$ref":"#/components/parameters/Estimate"}],"responses":{"200":{"$ref":"#/components/responses/RefreshResearch200"},"202":{"$ref":"#/components/responses/RefreshResearch202"},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"$ref":"#/components/responses/Problem402"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409_3"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"$ref":"#/components/responses/Problem502_3"},"503":{"$ref":"#/components/responses/Problem503_2"}},"x-price":{"credits":3,"unit":"video","max_credits":null}}},"/breakdowns":{"post":{"operationId":"createBreakdown","summary":"Run a Creator Breakdown","description":"Research on Creators, not keywords: analyses each Creator's latest `videos_per_creator` Videos into one Digest of what works for them. Read it at `GET /v1/breakdowns/{id}`.\n\n- **Outlier:** a Video's `outlier` is its views over its Creator's median in the Run.\n- **Lift tables:** use those ratios (`lift_tables.basis: creator_median`), so size does not skew them.\n- **Refused:** keyword fields.\n- **Cost:** a Video costs the same fresh or stored. The estimate and 402 check assume every Video is analysed.\n\n**Price:** 9 credits per Creator plus 20 credits per analysed Video, at most 4,090 credits; failed ones are free.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=createBreakdown) (no API Key needed).","tags":["Breakdowns"],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"creators":{"type":"array","items":{"anyOf":[{"type":"object","properties":{"platform":{"type":"string","enum":["tiktok","instagram","youtube","facebook"],"description":"The Creator's Platform."},"handle":{"type":"string","minLength":1,"maxLength":200,"description":"The Creator's handle, with or without `@`."}},"required":["platform","handle"],"additionalProperties":false},{"type":"string","description":"A profile URL."}]},"minItems":1,"maxItems":10,"description":"1 to 10 Creators of any Platforms, each named once. Or `collection_id`."},"collection_id":{"type":"string","description":"Or a Creator Collection, frozen at Run start."},"videos_per_creator":{"type":"integer","minimum":1,"maximum":50,"default":25,"description":"Recent Videos to read and analyse per Creator. Default 25, max 50; Creators × videos_per_creator at most 200."},"intent":{"type":"string","minLength":1,"maxLength":1000,"description":"Drops off-intent Videos read, unanalysed and free. None is read in their place. At most 1000 characters."},"wait":{"type":"number","minimum":0,"maximum":120,"default":30,"description":"Seconds to hold the response open before returning a running Run to poll. Default 30, max 120."},"max_credits":{"type":"integer","minimum":0,"description":"As in the query."},"estimate":{"type":"boolean","description":"If a source the call would read is unavailable and the cache cannot answer, the estimate adds `unavailable` (the `{ platform, capability }` parts it cannot reach), or is a 503 `source_unavailable` when it can reach none."}},"additionalProperties":false}}}},"responses":{"200":{"description":"The Run finished: a research result with `mode: creators`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"$ref":"#/components/schemas/Research"}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"research","status":"completed","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":1018,"list_price_credits":1018,"cached":false},"result":{"digest_version":5,"mode":"creators","coverage":{"tiktok":"complete"},"digest":{"summary":"Cold plunge videos are travelling on measured personal diaries rather than on science explainers. The videos that break out open on an unimpressive first number and pay it off with a later one, and keep the discomfort on camera instead of cutting around it. Sentiment is broadly positive, with the negative share concentrated on the cost of equipment.","themes":[{"name":"30-day diaries","share":0.45,"description":"One creator, one tub, a counter on screen, and the change stated as a number rather than a feeling.","video_ids":["tiktok:7300000000000000000"]},{"name":"Before-workout plunging","share":0.2,"description":"Shorter clips arguing about timing relative to training, usually with a gym setting.","video_ids":["tiktok:7300000000000000042"]}],"hooks":[{"text":"Day one I lasted eleven seconds.","video_id":"tiktok:7300000000000000000","hook_type":"stat","why_it_works":"An unimpressive concrete number sets up a payoff the viewer stays for.","template":"Day one I lasted [small number] [unit].","lift":{"value":"STORY","video_count":9,"median_views":1840000,"median_engagement_rate":0.0912,"views_lift":1.6,"engagement_lift":1.21,"low_confidence":false}}],"sentiment":{"positive":0.62,"neutral":0.23,"negative":0.15,"note":"Enthusiasm for the routine itself; the negative share is almost entirely the price of a tub."},"angles":[{"angle":"Open on the day-30 number and work backwards to day one.","rationale":"Every diary in the shortlist that led with the outcome outperformed the ones that led with the method."}],"gaps":[{"ask":"Viewers want a cold plunge setup that does not cost hundreds.","comments":[{"text":"ok but what do I do if I can't afford a 600 dollar tub","video_id":"tiktok:7300000000000000000"}],"angle":"A 30-day diary on a chest freezer or bathtub build, with the receipt on screen."}]},"videos":[{"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","author":"someone","is_original":true},"creator":{"id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","verified":false},"region":"US","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[{"kind":"54","label":"CapCut · Editing made easy"}]},"people":{"mentions":["coldplungeco"],"collaborators":[]},"location":null,"topics":{"keywords":[],"genre":null,"labels":["Fitness","Health"]},"chapters":null,"ai_generated":false,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":1284000,"likes":143200,"comments":2810,"shares":9040,"saves":21600},"scores":{"outlier":4.21,"outlier_p90":1.6,"percentile":95,"velocity":{"views_per_hour":6698.6,"window":"snapshot"},"reason":null,"baseline":{"median_views":305000,"p90_views":802000,"engagement_rate":0.1342,"posts_per_week":4.1,"sample":20,"confidence":"high","source":"videos","computed_at":"2026-09-08T09:14:03.902Z","stale":false}}},{"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","author":"Northbound","is_original":false},"creator":{"id":"cre_1a77c0b3de","handle":"anotherone","name":"Another One","follower_count":21400,"avatar_url":null,"verified":null},"region":"GB","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[]},"people":null,"location":null,"topics":null,"chapters":null,"ai_generated":null,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":96200,"likes":8140,"comments":212,"shares":401,"saves":1180},"scores":null}],"creators":[{"platform":"tiktok","id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","video_count":3,"best_outlier":4.21,"median_views":305000,"total_views":1611400,"video_ids":["tiktok:7300000000000000000"]}],"hashtags":[{"value":"coldplunge","platforms":["instagram","tiktok"],"video_count":34,"total_views":18402000,"video_ids":["tiktok:7300000000000000000","instagram:C9xExampleShortcode"]}],"sounds":[{"value":"7180000000000000000","title":"original sound - someone","author":"someone","is_original":true,"platforms":["tiktok"],"video_count":4,"total_views":2140000,"video_ids":["tiktok:7300000000000000000"]}],"breakdown":{"videos_per_creator":25,"creators":[{"platform":"tiktok","handle":"glowwithmaya","id":"6800000000000000101","videos_read":25,"ended":false},{"platform":"tiktok","handle":"skinbyjo","id":"6800000000000000102","videos_read":25,"ended":false}]},"research":{"requested":50,"completed":50,"failed":0,"cached":6,"fresh":44,"max_videos":50,"included_videos":0}}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":1018,"cached":false}}}}}},"202":{"$ref":"#/components/responses/CreateResearch202"},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"description":"`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`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/insufficient_balance","title":"Insufficient balance","status":402,"code":"insufficient_balance","detail":"Your balance is 0 Credits and this operation needs 1018 Credits. Nothing was charged.","retryable":false,"action":"Tell the Customer to top up the Balance, then repeat the same request.","balance_credits":0,"required_credits":1018}}}},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"$ref":"#/components/responses/Problem502"},"503":{"$ref":"#/components/responses/Problem503"}},"x-price":{"credits":9,"unit":"creator","max_credits":4090}}},"/breakdowns/{id}":{"get":{"operationId":"getBreakdown","summary":"Read a breakdown's status","description":"A Breakdown's status, answered as `GET /v1/research/{id}` answers it. An intent-mode Research id is the same 404 as an unknown id.\n\n**Price:** Free, forever. Collection is the only thing charged.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=getBreakdown) (no API Key needed).","tags":["Breakdowns"],"parameters":[{"name":"id","in":"path","required":true,"description":"Breakdown id — the id of its Run.","schema":{"type":"string"}}],"responses":{"200":{"$ref":"#/components/responses/GetResearch200"},"202":{"$ref":"#/components/responses/GetResearch202"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404"},"502":{"$ref":"#/components/responses/Problem502_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/breakdowns/{id}/videos":{"get":{"operationId":"listBreakdownVideos","summary":"Filter a breakdown's videos","description":"A Breakdown's Videos, answered as `GET /v1/research/{id}/videos` answers them: same filters, sort, paging and `as_of`, lift basis `creator_median`.\n\n**Price:** Free, forever, filtered or not. Collection is the only thing charged.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=listBreakdownVideos) (no API Key needed).","tags":["Breakdowns"],"parameters":[{"name":"id","in":"path","required":true,"description":"Breakdown id — the id of its Run.","schema":{"type":"string"}},{"$ref":"#/components/parameters/MinViews"},{"$ref":"#/components/parameters/MaxViews"},{"$ref":"#/components/parameters/Platforms"},{"$ref":"#/components/parameters/StartDate"},{"$ref":"#/components/parameters/EndDate"},{"$ref":"#/components/parameters/Creator"},{"$ref":"#/components/parameters/Hashtag"},{"$ref":"#/components/parameters/Sound"},{"$ref":"#/components/parameters/OrderBy"},{"$ref":"#/components/parameters/Sort"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"$ref":"#/components/parameters/AsOf"}],"responses":{"200":{"$ref":"#/components/responses/ListResearchVideos200"},"400":{"$ref":"#/components/responses/Problem400_2"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/breakdowns/{id}/creators":{"get":{"operationId":"listBreakdownCreators","summary":"Read a breakdown's creators and medians","description":"A Breakdown's input Creators with their medians, answered as `GET /v1/research/{id}/creators` answers them: `median_views` is the basis each lift was computed against.\n\n**Price:** Free, forever, filtered or not. Collection is the only thing charged.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=listBreakdownCreators) (no API Key needed).","tags":["Breakdowns"],"parameters":[{"name":"id","in":"path","required":true,"description":"Breakdown id — the id of its Run.","schema":{"type":"string"}},{"$ref":"#/components/parameters/MinFollowers"},{"$ref":"#/components/parameters/MaxFollowers"},{"$ref":"#/components/parameters/Platforms_2"},{"$ref":"#/components/parameters/OrderBy_2"},{"$ref":"#/components/parameters/Sort_2"},{"$ref":"#/components/parameters/Limit_2"},{"$ref":"#/components/parameters/Offset_2"},{"$ref":"#/components/parameters/AsOf"}],"responses":{"200":{"$ref":"#/components/responses/ListResearchCreators200"},"400":{"$ref":"#/components/responses/Problem400_3"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/breakdowns/{id}/hashtags":{"get":{"operationId":"listBreakdownHashtags","summary":"Rank a breakdown's hashtags","description":"A Breakdown's hashtags, lift basis `creator_median`, answered as `GET /v1/research/{id}/hashtags` answers them.\n\n**Price:** Free, forever, filtered or not. Collection is the only thing charged.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=listBreakdownHashtags) (no API Key needed).","tags":["Breakdowns"],"parameters":[{"name":"id","in":"path","required":true,"description":"Breakdown id — the id of its Run.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Platforms_3"},{"$ref":"#/components/parameters/OrderBy_3"},{"$ref":"#/components/parameters/Sort_3"},{"$ref":"#/components/parameters/Limit_3"},{"$ref":"#/components/parameters/Offset_3"},{"$ref":"#/components/parameters/AsOf"}],"responses":{"200":{"$ref":"#/components/responses/ListResearchHashtags200"},"400":{"$ref":"#/components/responses/Problem400_4"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/breakdowns/{id}/sounds":{"get":{"operationId":"listBreakdownSounds","summary":"Rank a breakdown's sounds","description":"A Breakdown's sounds, lift basis `creator_median`, answered as `GET /v1/research/{id}/sounds` answers them.\n\n**Price:** Free, forever, filtered or not. Collection is the only thing charged.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=listBreakdownSounds) (no API Key needed).","tags":["Breakdowns"],"parameters":[{"name":"id","in":"path","required":true,"description":"Breakdown id — the id of its Run.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Platforms_4"},{"$ref":"#/components/parameters/OrderBy_4"},{"$ref":"#/components/parameters/Sort_4"},{"$ref":"#/components/parameters/Limit_4"},{"$ref":"#/components/parameters/Offset_4"},{"$ref":"#/components/parameters/AsOf"}],"responses":{"200":{"$ref":"#/components/responses/ListResearchSounds200"},"400":{"$ref":"#/components/responses/Problem400_4"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/breakdowns/{id}/digest":{"get":{"operationId":"getBreakdownDigest","summary":"Read a breakdown's digest","description":"A Breakdown's Digest, answered as `GET /v1/research/{id}/digest` answers it.\n\n**Price:** Free, forever. Collection is the only thing charged.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=getBreakdownDigest) (no API Key needed).","tags":["Breakdowns"],"parameters":[{"name":"id","in":"path","required":true,"description":"Breakdown id — the id of its Run.","schema":{"type":"string"}},{"$ref":"#/components/parameters/AsOf_2"}],"responses":{"200":{"$ref":"#/components/responses/GetResearchDigest200"},"400":{"$ref":"#/components/responses/Problem400_5"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/breakdowns/{id}/refresh":{"post":{"operationId":"refreshBreakdown","summary":"Refresh a breakdown's videos","description":"Sweeps fresh metrics for a Breakdown's videos, as `POST /v1/research/{id}/refresh` does: same price, rules and response. An intent-mode Research id is the same 404 as an unknown id.\n\n**Price:** 3 credits per video that comes back.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=refreshBreakdown) (no API Key needed).","tags":["Breakdowns"],"parameters":[{"name":"id","in":"path","required":true,"description":"Breakdown id — the id of its Run.","schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Wait"},{"$ref":"#/components/parameters/MaxCredits"},{"$ref":"#/components/parameters/Estimate"}],"responses":{"200":{"$ref":"#/components/responses/RefreshResearch200"},"202":{"$ref":"#/components/responses/RefreshResearch202"},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"$ref":"#/components/responses/Problem402"},"404":{"$ref":"#/components/responses/Problem404"},"409":{"$ref":"#/components/responses/Problem409_3"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"$ref":"#/components/responses/Problem502_3"},"503":{"$ref":"#/components/responses/Problem503_2"}},"x-price":{"credits":3,"unit":"video","max_credits":null}}},"/videos/search":{"post":{"operationId":"searchVideos","summary":"Search videos by keyword","description":"Keyword search across TikTok, Instagram and YouTube, one page per call. Facebook is opt-in: it joins when `platforms` names it, and the default stays the three.\n\n- **Coverage:** `coverage` reports each platform as complete, partial or failed.\n- **Best-effort platforms:** Instagram and Facebook results are best-effort (`coverage: \"partial\"`). Facebook results carry a view count only where Facebook shows one, and no other counts.\n- **Unavailable Source:** reported `failed: source_unavailable`, uncharged, and leaves the Run `partial`.\n- **Analysis:** with `intelligence: true` the search runs in the request and the enrichment passes as a workflow. Each enriched video is a RunItem with its own status and charge at `GET /v1/runs/{id}/items`.\n- **Long videos:** a video over 10 minutes is not analysed or charged. Its item fails with `video_too_long`, decided from the length the search reported, else when the pass reads the video.\n- **Photo carousels:** TikTok ones are analysed from their images, at the same price.\n- **Analysis failures:** a video that cannot be analysed comes back on the page with `intelligence: null` and `intelligence_error` saying why.\n\n**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. `focus`: +3 credits per Video the model judges, +1 credit per Video `must_mention` rules out, nothing for one already judged under the same Focus or one that could not be judged (shown); `estimate` quotes every returned Video judged.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=searchVideos) (no API Key needed).","tags":["Videos"],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","minLength":1,"maxLength":200,"description":"At most 200 characters."},"platforms":{"type":"array","items":{"type":"string","enum":["tiktok","instagram","youtube","facebook"]},"minItems":1,"description":"Omit for TikTok, Instagram and YouTube. `facebook` is opt-in: name it to search Facebook videos and Reels."},"region":{"type":"string","minLength":2,"maxLength":5,"description":"Country code, such as `US` or `GB`, that the TikTok and YouTube searches run from; Instagram and Facebook ignore it. Omitted, each platform uses its own default."},"window":{"type":"string","enum":["day","week","month","quarter","half_year","all"],"default":"month","description":"Videos posted within the last `day`, `week`, `month` (the default), `quarter` or `half_year`, or `all` for no limit. Each platform applies its nearest window: Instagram has a week, a month and a year; YouTube has a day, a week and a month, and searches without a limit past that."},"sort":{"type":"string","enum":["relevance","likes","date"],"default":"relevance","description":"`relevance` (the default) keeps each platform's order, `likes` puts the most liked first, `date` the newest first. YouTube has no date order and keeps relevance."},"limit":{"type":"integer","minimum":1,"maximum":30,"default":25,"description":"Videos on the page, across every platform searched, interleaved. Default 25, max 30."},"cursor":{"type":"string","minLength":1,"description":"The `next_cursor` of the previous page, to read the next one. Send the same `query` and `platforms`; a cursor that does not continue those platforms is a 400. Each page is charged."},"intelligence":{"type":"boolean","description":"Analyse the top 20 results."},"focus":{"type":"object","properties":{"text":{"type":"string","description":"Which Videos are relevant to you, in plain language, exclusions included, e.g. `Apple Inc. and its products (iPhone, Mac, AirPods, iOS). Not the fruit, recipes or orchards.` 1 to 1000 characters."},"must_mention":{"type":"array","items":{"type":"string"},"description":"Up to 20 terms of at most 60 characters. A Video that has captions or an analysis transcript, and whose caption, hashtags, captions and transcript name none of them (any case, whole term), is off focus without a model call; one with neither goes to the model, so a term said aloud still counts; one naming any is still judged against `text`."}},"required":["text"],"additionalProperties":false,"description":"Judge each result against your Focus and hide the off-focus ones; `off_focus_count` says how many, `unjudged_count` how many shown ones could not be judged. With `intelligence`, only in-focus and unjudged results are analysed. +3 credits per Video the model judges, +1 credit per Video `must_mention` rules out, nothing for one already judged under the same Focus or one that could not be judged (shown); `estimate` quotes every returned Video judged."},"include_off_focus":{"type":"boolean","description":"With `focus`: return every result, each with `focus: { verdict, reason }`."},"wait":{"type":"number","minimum":0,"maximum":120,"default":30,"description":"Seconds to hold the response open before returning a running Run to poll. Default 30, max 120."},"max_credits":{"type":"integer","minimum":0,"description":"As in the query."},"estimate":{"type":"boolean","description":"If a source the call would read is unavailable and the cache cannot answer, the estimate adds `unavailable` (the `{ platform, capability }` parts it cannot reach), or is a 503 `source_unavailable` when it can reach none."}},"required":["query"],"additionalProperties":false}}}},"responses":{"200":{"description":"The Run finished inside the wait budget: `{ run, result }`. With `estimate=true`, `{ estimate_credits, cached }` instead.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"type":"object","properties":{"items":{"type":"array","items":{"description":"One normalised video, the same shape on every platform.","allOf":[{"$ref":"#/components/schemas/Video"},{"type":"object","properties":{"intelligence":{"description":"The analysis. Null when this video could not be analysed (uncharged); absent past the cap.","anyOf":[{"$ref":"#/components/schemas/Analysis"},{"type":"null"}]},"intelligence_error":{"$ref":"#/components/schemas/Problem","description":"Why `intelligence` is null."},"focus":{"type":"object","properties":{"verdict":{"type":"string","enum":["in_focus","off_focus","unjudged"],"description":"`unjudged`: the Video could not be judged (or is not judged yet) and is shown."},"reason":{"type":"string"}},"required":["verdict","reason"],"description":"Present only with `focus` and `include_off_focus`."}}}]},"description":"With `intelligence: true`, the enriched videos carry `intelligence`, or `intelligence: null` and `intelligence_error` when they could not be analysed."},"next_cursor":{"type":["string","null"]},"coverage":{"type":"object","additionalProperties":{"type":"string"},"description":"Per platform: `complete`, `partial`, or `failed: <code>`."},"intelligence":{"type":"object","properties":{"requested":{"type":"integer"},"completed":{"type":"integer"},"failed":{"type":"integer"},"cap":{"type":"integer"}},"required":["requested","completed","failed","cap"],"description":"Present only with `intelligence: true`. Per-video outcomes page at `GET /v1/runs/{id}/items`."},"off_focus_count":{"type":"integer","description":"Present only with `focus`: how many Videos were judged off focus (hidden unless `include_off_focus`)."},"unjudged_count":{"type":"integer","description":"Present only with `focus`: how many shown Videos could not be judged (never counted in focus)."}},"required":["items","next_cursor","coverage"]}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"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","author":"someone","is_original":true},"creator":{"id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","verified":false},"region":"US","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[{"kind":"54","label":"CapCut · Editing made easy"}]},"people":{"mentions":["coldplungeco"],"collaborators":[]},"location":null,"topics":{"keywords":[],"genre":null,"labels":["Fitness","Health"]},"chapters":null,"ai_generated":false,"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","author":"Northbound","is_original":false},"creator":{"id":"cre_1a77c0b3de","handle":"anotherone","name":"Another One","follower_count":21400,"avatar_url":null,"verified":null},"region":"GB","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[]},"people":null,"location":null,"topics":null,"chapters":null,"ai_generated":null,"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"}}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":3,"cached":false}}}}}},"202":{"description":"Still running: `{ run }`. Poll `GET /v1/runs/{id}`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningEnvelope"},"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},"poll_url":"https://www.shortsintel.com/v1/runs/run_8f2c1ad04b"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"$ref":"#/components/responses/Problem402_2"},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"description":"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.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Retry with a backoff; nothing was charged.","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":{"description":"`source_unavailable`: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; `endpoints` names the source. Wait `retry_after_seconds` (also sent as `Retry-After`) and retry rather than treating it as empty.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Wait `retry_after_seconds`, then retry; do not treat this as an empty result.","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},"retry_after_seconds":60}}}}},"x-price":{"credits":3,"unit":"platform_page","max_credits":502}}},"/videos/lookup":{"post":{"operationId":"lookupVideo","summary":"Look up a video by URL","description":"The same operation as `GET /v1/videos/{platform}/{id}`, addressed by whatever URL the user pasted. Platform and id are parsed out of the URL, so both spellings charge and cache alike.\n\n- **Instagram:** `/p/`, `/reel/` and `/reels/` URLs are one post with one cache entry.\n- **YouTube:** accepts `watch?v=`, `/shorts/`, `/embed/` and `youtu.be` URLs, e.g. `{\"url\":\"https://www.youtube.com/shorts/myZ9kn9MIWQ\"}`.\n- **TikTok short links:** `vm.tiktok.com`, `vt.tiktok.com` and `tiktok.com/t/...` are resolved by following TikTok's redirect (https only, at most 3 hops, 5 s), after the 402 check and before the Run opens, out of `wait`.\n- **Estimates:** a short link quotes the fresh price with `cached: false`, the video being unknown until resolved.\n- **Idempotency:** matches the URL as sent, so a retry replays without resolving again.\n\n**Price:** 3 credits, the same when a Snapshot under 24 h old can answer.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=lookupVideo) (no API Key needed).","tags":["Videos"],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":2048,"description":"Any TikTok, Instagram (`/p/`, `/reel/`, `/reels/`) or Shorts URL, including a TikTok short link, or a Facebook `/reel/{id}`, `/watch?v={id}` or `/{page}/videos/{id}` URL."},"wait":{"type":"number","minimum":0,"maximum":120,"default":30,"description":"Seconds to hold the response open before returning a running Run to poll. Default 30, max 120."},"max_credits":{"type":"integer","minimum":0,"description":"As in the query."},"estimate":{"type":"boolean","description":"If a source the call would read is unavailable and the cache cannot answer, the estimate adds `unavailable` (the `{ platform, capability }` parts it cannot reach), or is a 503 `source_unavailable` when it can reach none."}},"required":["url"],"additionalProperties":false}}}},"responses":{"200":{"description":"The Run finished inside the wait budget: `{ run, result }`. The example was answered from a Snapshot under 24 h old, which is why `run.cached` is true; a stored answer costs the same as a fresh one, so `charge_credits` equals `list_price_credits`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"$ref":"#/components/schemas/Video"}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"video_lookup","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":true},"result":{"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","author":"someone","is_original":true},"creator":{"id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","verified":false},"region":"US","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[{"kind":"54","label":"CapCut · Editing made easy"}]},"people":{"mentions":["coldplungeco"],"collaborators":[]},"location":null,"topics":{"keywords":[],"genre":null,"labels":["Fitness","Health"]},"chapters":null,"ai_generated":false,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":1284000,"likes":143200,"comments":2810,"shares":9040,"saves":21600},"scores":{"outlier":4.21,"outlier_p90":1.6,"percentile":95,"velocity":{"views_per_hour":6698.6,"window":"snapshot"},"reason":null,"baseline":{"median_views":305000,"p90_views":802000,"engagement_rate":0.1342,"posts_per_week":4.1,"sample":20,"confidence":"high","source":"videos","computed_at":"2026-09-08T09:14:03.902Z","stale":false}}}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":3,"cached":true}}}}}},"202":{"$ref":"#/components/responses/LookupVideo202"},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"$ref":"#/components/responses/Problem402_2"},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"$ref":"#/components/responses/Problem502_4"},"503":{"$ref":"#/components/responses/Problem503_3"}},"x-price":{"credits":3,"unit":"call","max_credits":3}}},"/videos/{platform}/{id}":{"get":{"operationId":"getVideo","summary":"Look up a video by id","description":"Metadata, stats, the latest Snapshot and Scores for one video on TikTok, Instagram, YouTube or Facebook.\n\n**Ids by platform**\n\n- **Instagram:** the post's shortcode (`/p/{id}`, `/reel/{id}`) or the numeric media id search returns. Reels, photos and carousels are all videos. Instagram reports no shares or saves, so they read 0.\n- **YouTube:** the 11-character video id. `description` holds the title then the description, with no `sound` and `shares`/`saves` 0, as YouTube publishes neither.\n- **Facebook:** the numeric video or reel id. `shares` over 1,000 may be rounded as Facebook shows it (1.4K reads 1400).\n\n**Scores and history**\n\n- **Scores:** returned where the creator has a baseline, else `null` Scores rather than a fetch. `POST /videos/{platform}/{id}/score` forces it (TikTok only; other platforms are 400 `unsupported_platform` before any Run).\n- **History:** the Snapshots behind `velocity` are at `GET /v1/videos/{platform}/{id}/snapshots`.\n\n**Adding analysis or a download**\n\n- **One Run:** any `include` makes the call one video analysis Run (kind `video_intelligence`) at a single price in place of the lookup price. `include` works on every platform, YouTube long-form included.\n- **Analysis and transcript prices:** `include=intelligence` (alone or with `transcript`) is the analysis price. `include=transcript` alone is the flat transcript price.\n- **Download link:** `include=download` adds `download_url`, a link to our own short-lived copy of the file. Anyone holding it can download the file.\n- **Link expiry:** `download_expires_at`, 7 days after the copy was made and at least a day away. Ask again for a fresh link.\n- **Download price:** alone it is the download price. With `intelligence` or `transcript` it is added to theirs, copy or no copy.\n- **Failed copy:** with `download` beside `intelligence` or `transcript`, a file that cannot be copied does not fail the analysis. The result carries `download_error` and the download is not charged.\n\n**Errors**\n\n- **Unavailable media:** a post gone, private or restricted fails the Run with `media_unavailable`, uncharged.\n- **Long videos:** a video over 10 minutes is refused for analysis and download with 422 `video_too_long`, before any Run when its length is known (YouTube is asked first, free), else the Run fails uncharged.\n\n**Price:** 3 credits. With `include=intelligence`: 23 credits instead of the lookup price. With `include=transcript` only: a flat 10 credits. With `include=download`: 3 credits alone, else 3 credits on top of the analysis or transcript price. A stored answer (or an existing copy) costs the same as a fresh one.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=getVideo) (no API Key needed).","tags":["Videos"],"parameters":[{"name":"platform","in":"path","required":true,"description":"Platform the subject lives on.","schema":{"type":"string","enum":["tiktok","instagram","youtube","facebook"]}},{"name":"id","in":"path","required":true,"description":"Platform video id.","schema":{"type":"string"}},{"name":"include","in":"query","required":false,"description":"`intelligence` adds the full analysis object (a TikTok photo carousel is analysed from its images, slide by slide); `transcript` adds the transcript; `download` adds `download_url` and `download_expires_at` (refused for a photo carousel: `media_unavailable`, reason `not_a_video`). Repeat the param or comma-separate (`include=intelligence,download`). Any value changes the price; see above.","schema":{"type":"array","items":{"type":"string","enum":["intelligence","transcript","download"]}}},{"name":"refresh","in":"query","required":false,"description":"Only with `include`. `true` recomputes the analysis even when a current one is stored, and is charged as fresh. Ignored without `include`.","schema":{"type":"boolean"}},{"$ref":"#/components/parameters/Wait"},{"$ref":"#/components/parameters/MaxCredits"},{"$ref":"#/components/parameters/Estimate_2"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"The Run finished inside the wait budget: `{ run, result }`. With `estimate=true`, `{ estimate_credits, cached }` instead.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"description":"One normalised video, the same shape on every platform.","allOf":[{"$ref":"#/components/schemas/Video"},{"type":"object","properties":{"download_url":{"type":"string","description":"With `include=download`: a link to the video file, served from our own copy. Works until `download_expires_at`; anyone holding it can download the file."},"download_expires_at":{"type":"string","description":"With `include=download`: when `download_url` stops working, 7 days after our copy was made (at least a day away)."},"download_error":{"$ref":"#/components/schemas/Problem","description":"With `include=download` beside analysis: why the file could not be copied (e.g. `media_unavailable`, too large). The analysis is still served and the download is not charged."}}}]}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"video_lookup","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":{"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","author":"someone","is_original":true},"creator":{"id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","verified":false},"region":"US","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[{"kind":"54","label":"CapCut · Editing made easy"}]},"people":{"mentions":["coldplungeco"],"collaborators":[]},"location":null,"topics":{"keywords":[],"genre":null,"labels":["Fitness","Health"]},"chapters":null,"ai_generated":false,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":1284000,"likes":143200,"comments":2810,"shares":9040,"saves":21600},"scores":{"outlier":4.21,"outlier_p90":1.6,"percentile":95,"velocity":{"views_per_hour":6698.6,"window":"snapshot"},"reason":null,"baseline":{"median_views":305000,"p90_views":802000,"engagement_rate":0.1342,"posts_per_week":4.1,"sample":20,"confidence":"high","source":"videos","computed_at":"2026-09-08T09:14:03.902Z","stale":false}}}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":3,"cached":false}}}}}},"202":{"$ref":"#/components/responses/LookupVideo202"},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"$ref":"#/components/responses/Problem402_2"},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"$ref":"#/components/responses/Problem502_4"},"503":{"$ref":"#/components/responses/Problem503_3"}},"x-price":{"credits":3,"unit":"call","max_credits":26}}},"/videos/{platform}/{id}/intelligence":{"post":{"operationId":"computeVideoIntelligence","summary":"Analyse a video","description":"The full video pass: a scene pass over the media, then a structured pass producing one versioned object with `content`, `hook`, `persuasion`, `tone`, `visual` and `safety` groups.\n\n- **Platforms:** TikTok, Instagram, YouTube (Shorts and long-form) and Facebook.\n- **Caching:** cached forever per version.\n- **No speech:** videos with no speech still run.\n- **Unfetchable media:** only a post gone, private or restricted, or media the pass cannot read, fails, with terminal `media_unavailable`. A retry will not succeed.\n- **Long videos:** a video over 10 minutes is refused with 422 `video_too_long`, before any Run when its length is known (YouTube is asked first, free), else the Run fails uncharged.\n\n**Price:** 23 credits, whether computed now or already stored, and with `refresh: true`.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=computeVideoIntelligence) (no API Key needed).","tags":["Videos"],"parameters":[{"name":"platform","in":"path","required":true,"description":"Platform the subject lives on.","schema":{"type":"string","enum":["tiktok","instagram","youtube","facebook"]}},{"name":"id","in":"path","required":true,"description":"Platform video id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Wait"},{"$ref":"#/components/parameters/MaxCredits"},{"$ref":"#/components/parameters/Estimate_2"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"refresh":{"type":"boolean","description":"Recompute even when a current version is stored: the scene pass over the media runs again, not just the structured pass. Always charged as fresh."},"wait":{"type":"number","minimum":0,"maximum":120,"default":30,"description":"Seconds to hold the response open before returning a running Run to poll. Default 30, max 120."},"estimate":{"type":"boolean","description":"`true` returns `{ estimate_credits, cached }`, creates no Run and charges nothing."},"max_credits":{"type":"integer","minimum":0,"description":"As in the query."}},"additionalProperties":false}}}},"responses":{"200":{"description":"The Run finished inside the wait budget: `{ run, result }`. With `estimate=true`, `{ estimate_credits, cached }` instead.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"description":"One normalised video, the same shape on every platform.","allOf":[{"$ref":"#/components/schemas/Video"},{"type":"object","properties":{"intelligence":{"$ref":"#/components/schemas/Analysis"}},"required":["intelligence"]}]}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"video_intelligence","status":"completed","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":23,"list_price_credits":23,"cached":false},"result":{"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","author":"someone","is_original":true},"creator":{"id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","verified":false},"region":"US","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[{"kind":"54","label":"CapCut · Editing made easy"}]},"people":{"mentions":["coldplungeco"],"collaborators":[]},"location":null,"topics":{"keywords":[],"genre":null,"labels":["Fitness","Health"]},"chapters":null,"ai_generated":false,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":1284000,"likes":143200,"comments":2810,"shares":9040,"saves":21600},"scores":{"outlier":4.21,"outlier_p90":1.6,"percentile":95,"velocity":{"views_per_hour":6698.6,"window":"snapshot"},"reason":null,"baseline":{"median_views":305000,"p90_views":802000,"engagement_rate":0.1342,"posts_per_week":4.1,"sample":20,"confidence":"high","source":"videos","computed_at":"2026-09-08T09:14:03.902Z","stale":false}},"intelligence":{"version":1,"model":"gemini-2.5-flash","computed_at":"2026-09-08T09:14:04.612Z","source":"speech","content":{"summary":"A 30-day cold plunge diary that leads with the measurable change and keeps the discomfort visible rather than heroic.","niche":"HEALTH_AND_FITNESS","languages":["en"],"content_styles":["TALKING_HEAD","PROGRESS_DIARY"],"keywords":[{"keyword":"cold plunge","category":"ACTION","sentiment":0.4},{"keyword":"recovery","category":"TOPIC","sentiment":0.6}],"transcript":"Day one I lasted eleven seconds. Day thirty I stopped noticing the cold at all, and that is the part nobody warns you about...","transcript_segments":[{"start_ms":0,"end_ms":2400,"text":"Day one I lasted eleven seconds."}]},"hook":{"opening_line":"Day one I lasted eleven seconds.","type":"SPECIFIC_DETAIL","visual_hook":"Timer overlay counting up on a shot of the plunge tub at dawn","rationale":"A concrete, unimpressive number invites the viewer to stay for the number it becomes."},"persuasion":{"call_to_action":{"type":"FOLLOW","text":"Following along? Day 60 starts Monday."},"sponsored":false,"sponsorship_signals":[],"brands_and_products":[{"name":"Plunge","kind":"PRODUCT","prominence":"INCIDENTAL"}],"trend_references":[{"name":"30-day challenge","kind":"FORMAT"}]},"tone":{"sentiment_label":"Positive","sentiment_score":0.42,"primary_emotion":"Determination","emotion_intensity":0.6,"emotion_rationale":"The delivery stays level through visible discomfort, which reads as resolve rather than excitement.","speaking_style":"CONVERSATIONAL","speaking_style_notes":"Unhurried voiceover over hard cuts between mornings, with no music bed under the first ten seconds."},"visual":{"format":"VLOG","setting":"OUTDOOR_HOME","face_visibility":"CREATOR_ON_CAMERA","on_screen_text":["DAY 1","DAY 30","11s → 3:00"],"has_on_screen_captions":true,"camera_notes":"Fixed tripod at tub height, one handheld reaction shot per morning, cut roughly every two seconds.","lighting_notes":"Natural dawn light, cool and slightly underexposed throughout.","elements":[{"type":"OBJECT","name":"ice bath","confidence":0.97}]},"safety":{"brand_safety_tier":"SAFE","reasons":[],"notes":null}}}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":23,"cached":false}}}}}},"202":{"description":"Still running: `{ run }`. Poll `GET /v1/runs/{id}`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningEnvelope"},"example":{"run":{"id":"run_8f2c1ad04b","kind":"video_intelligence","status":"running","created_at":"2026-09-08T09:14:02.418Z","completed_at":null,"charge_credits":0,"list_price_credits":0,"cached":false},"poll_url":"https://www.shortsintel.com/v1/runs/run_8f2c1ad04b"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"description":"`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`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/insufficient_balance","title":"Insufficient balance","status":402,"code":"insufficient_balance","detail":"Your balance is 0 Credits and this operation needs 23 Credits. Nothing was charged.","retryable":false,"action":"Tell the Customer to top up the Balance, then repeat the same request.","balance_credits":0,"required_credits":23}}}},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"description":"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.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Retry with a backoff; nothing was charged.","run":{"id":"run_8f2c1ad04b","kind":"video_intelligence","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":{"description":"`source_unavailable`: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; `endpoints` names the source. Wait `retry_after_seconds` (also sent as `Retry-After`) and retry rather than treating it as empty.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Wait `retry_after_seconds`, then retry; do not treat this as an empty result.","endpoints":["tiktok/video"],"run":{"id":"run_8f2c1ad04b","kind":"video_intelligence","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},"retry_after_seconds":60}}}}},"x-price":{"credits":23,"unit":"call","max_credits":23}}},"/videos/{platform}/{id}/score":{"post":{"operationId":"scoreVideo","summary":"Score a video against its creator","description":"Outlier multiple against the creator's median views, `outlier_p90`, views per hour and percentile within the creator's sample. Forces the creator fetch and the baseline computation. Velocity is `null` with `reason: aged_out` past 30 days. Numbers only, no labels.\n\n**Price:** 9 credits, always fresh — asking for a score is asking for the fetch.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=scoreVideo) (no API Key needed).","tags":["Videos"],"parameters":[{"name":"platform","in":"path","required":true,"description":"Platform the subject lives on.","schema":{"type":"string","enum":["tiktok"]}},{"name":"id","in":"path","required":true,"description":"Platform video id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Wait"},{"$ref":"#/components/parameters/MaxCredits"},{"$ref":"#/components/parameters/Estimate_2"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"The Run finished inside the wait budget: `{ run, result }`. With `estimate=true`, `{ estimate_credits, cached }` instead.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"type":"object","properties":{"video":{"$ref":"#/components/schemas/Video"},"creator":{"description":"The creator whose baseline the video was scored against.","anyOf":[{"$ref":"#/components/schemas/Creator"},{"type":"null"}]}},"required":["video","creator"],"description":"Scoring forces the creator fetch, so both come back."}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"video_score","status":"completed","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":9,"list_price_credits":9,"cached":false},"result":{"video":{"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","author":"someone","is_original":true},"creator":{"id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","verified":false},"region":"US","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[{"kind":"54","label":"CapCut · Editing made easy"}]},"people":{"mentions":["coldplungeco"],"collaborators":[]},"location":null,"topics":{"keywords":[],"genre":null,"labels":["Fitness","Health"]},"chapters":null,"ai_generated":false,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":1284000,"likes":143200,"comments":2810,"shares":9040,"saves":21600},"scores":{"outlier":4.21,"outlier_p90":1.6,"percentile":95,"velocity":{"views_per_hour":6698.6,"window":"snapshot"},"reason":null,"baseline":{"median_views":305000,"p90_views":802000,"engagement_rate":0.1342,"posts_per_week":4.1,"sample":20,"confidence":"high","source":"videos","computed_at":"2026-09-08T09:14:03.902Z","stale":false}}},"creator":{"platform":"tiktok","id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","follower_count":184300,"bio":"Cold water, early mornings, and the numbers behind both. hello@someone.example","verified":false,"video_count":214,"total_likes":4210000,"following_count":312,"links":[{"title":null,"url":"https://linktr.ee/someone"}],"joined_at":"2020-01-14T09:12:40.000Z","country":"US","business":{"is_business":false,"category":null},"total_views":null,"contact":{"email":"hello@someone.example","phone":null,"address":null,"website":null,"source":"bio"},"snapshot":{"at":"2026-09-08T09:14:04.219Z","followers":184300},"baseline":{"median_views":305000,"p90_views":802000,"engagement_rate":0.1342,"posts_per_week":4.1,"sample":20,"confidence":"high","source":"videos","computed_at":"2026-09-08T09:14:03.902Z","stale":false}}}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":9,"cached":false}}}}}},"202":{"description":"Still running: `{ run }`. Poll `GET /v1/runs/{id}`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningEnvelope"},"example":{"run":{"id":"run_8f2c1ad04b","kind":"video_score","status":"running","created_at":"2026-09-08T09:14:02.418Z","completed_at":null,"charge_credits":0,"list_price_credits":0,"cached":false},"poll_url":"https://www.shortsintel.com/v1/runs/run_8f2c1ad04b"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"description":"`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`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/insufficient_balance","title":"Insufficient balance","status":402,"code":"insufficient_balance","detail":"Your balance is 0 Credits and this operation needs 9 Credits. Nothing was charged.","retryable":false,"action":"Tell the Customer to top up the Balance, then repeat the same request.","balance_credits":0,"required_credits":9}}}},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"description":"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.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Retry with a backoff; nothing was charged.","run":{"id":"run_8f2c1ad04b","kind":"video_score","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":{"description":"`source_unavailable`: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; `endpoints` names the source. Wait `retry_after_seconds` (also sent as `Retry-After`) and retry rather than treating it as empty.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Wait `retry_after_seconds`, then retry; do not treat this as an empty result.","endpoints":["tiktok/video"],"run":{"id":"run_8f2c1ad04b","kind":"video_score","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},"retry_after_seconds":60}}}}},"x-price":{"credits":9,"unit":"call","max_credits":9}}},"/videos/{platform}/{id}/comments":{"get":{"operationId":"getVideoComments","summary":"Read a video's comments","description":"A page of comments, optionally with a sentiment summary. Read the video first with `GET /v1/videos/{platform}/{id}`.\n\n- **Authors:** none. Author information is dropped as each comment is fetched, before it is stored.\n- **Retention:** raw comments are purged after 90 days. The analysis is kept.\n- **Replies:** the page holds top-level comments only. On TikTok, Instagram and Facebook a comment's replies are at `GET /v1/videos/{platform}/{id}/comments/{comment_id}/replies`.\n- **Reply counts:** TikTok and Facebook count them in `reply_count`. Instagram often shows 0 for a comment that may still have replies.\n- **Instagram:** comments may be a capped preview of a longer list. The result then carries `coverage: \"partial\"` and the Run completes at the normal price.\n- **YouTube:** top-level comments in its Top comments order, with an approximate `posted_at`, as YouTube shows only how long ago.\n- **Facebook:** `like_count` is the comment's reaction count.\n\n**Price:** 3 credits per page, plus 10 credits with `analyze=true`, whether the analysis is computed now or already stored.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=getVideoComments) (no API Key needed).","tags":["Videos"],"parameters":[{"name":"platform","in":"path","required":true,"description":"Platform the subject lives on.","schema":{"type":"string","enum":["tiktok","instagram","youtube","facebook"]}},{"name":"id","in":"path","required":true,"description":"Platform video id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit_5"},{"$ref":"#/components/parameters/Cursor"},{"name":"analyze","in":"query","required":false,"description":"Add a sentiment summary over the page.","schema":{"type":"boolean"}},{"$ref":"#/components/parameters/Wait"},{"$ref":"#/components/parameters/MaxCredits"},{"$ref":"#/components/parameters/Estimate_2"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"The Run finished inside the wait budget: `{ run, result }`. The example was called with `analyze=true`, so it carries both the page and the summary and cost both prices.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"type":"object","properties":{"platform":{"type":"string"},"video_id":{"type":"string"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"text":{"type":"string","description":"No author information: it is dropped as the comment is fetched."},"like_count":{"type":"integer"},"reply_count":{"type":"integer"},"posted_at":{"type":["string","null"]},"parent_id":{"type":["string","null"],"description":"Null on the comments page; on a replies page, the comment replied to."},"fetched_at":{"type":"string"}},"required":["id","text","like_count","reply_count","posted_at","parent_id","fetched_at"]}},"next_cursor":{"type":["string","null"]},"analysis":{"type":["object","null"],"properties":{"version":{"type":"string"},"sample_size":{"type":"integer"},"sentiment":{"type":"object","properties":{"positive":{"type":"integer"},"neutral":{"type":"integer"},"negative":{"type":"integer"}},"required":["positive","neutral","negative"]},"average_score":{"type":["number","null"]},"themes":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"mentions":{"type":"integer"},"sentiment":{"type":"string"}},"required":["label","mentions","sentiment"]}},"computed_at":{"type":"string"}},"required":["version","sample_size","sentiment","average_score","themes","computed_at"],"description":"Null unless `analyze=true`."},"coverage":{"type":"string","enum":["partial"],"description":"Present when the comments are a capped preview of a longer list (Instagram can serve only the comments a public post page shows). Absent when the list is read in full."}},"required":["platform","video_id","items","next_cursor","analysis"]}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"video_comments","status":"completed","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":13,"list_price_credits":13,"cached":false},"result":{"platform":"tiktok","video_id":"7300000000000000000","items":[{"id":"7300100000000000001","text":"Does the temperature matter more than the time?","like_count":4821,"reply_count":12,"posted_at":"2026-09-06T08:41:00.000Z","parent_id":null,"fetched_at":"2026-09-08T09:14:04.219Z"},{"id":"7300100000000000002","text":"started last week and the first minute is still brutal","like_count":218,"reply_count":0,"posted_at":"2026-09-06T09:02:00.000Z","parent_id":null,"fetched_at":"2026-09-08T09:14:04.219Z"}],"next_cursor":"eyJvIjoyNX0","analysis":{"version":"v1","sample_size":25,"sentiment":{"positive":16,"neutral":6,"negative":3},"average_score":0.41,"themes":[{"label":"water temperature","mentions":9,"sentiment":"neutral"},{"label":"cost of a tub","mentions":4,"sentiment":"negative"}],"computed_at":"2026-09-08T09:14:04.780Z"}}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":13,"cached":false}}}}}},"202":{"description":"Still running: `{ run }`. Poll `GET /v1/runs/{id}`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningEnvelope"},"example":{"run":{"id":"run_8f2c1ad04b","kind":"video_comments","status":"running","created_at":"2026-09-08T09:14:02.418Z","completed_at":null,"charge_credits":0,"list_price_credits":0,"cached":false},"poll_url":"https://www.shortsintel.com/v1/runs/run_8f2c1ad04b"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"description":"`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`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/insufficient_balance","title":"Insufficient balance","status":402,"code":"insufficient_balance","detail":"Your balance is 0 Credits and this operation needs 13 Credits. Nothing was charged.","retryable":false,"action":"Tell the Customer to top up the Balance, then repeat the same request.","balance_credits":0,"required_credits":13}}}},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"description":"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.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Retry with a backoff; nothing was charged.","run":{"id":"run_8f2c1ad04b","kind":"video_comments","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":{"description":"`source_unavailable`: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; `endpoints` names the source. Wait `retry_after_seconds` (also sent as `Retry-After`) and retry rather than treating it as empty.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Wait `retry_after_seconds`, then retry; do not treat this as an empty result.","endpoints":["tiktok/video"],"run":{"id":"run_8f2c1ad04b","kind":"video_comments","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},"retry_after_seconds":60}}}}},"x-price":{"credits":3,"unit":"page","max_credits":13}}},"/videos/{platform}/{id}/comments/{comment_id}/replies":{"get":{"operationId":"getCommentReplies","summary":"Read a comment's replies","description":"A page of the replies to one comment, in the order the platform ranks them. Read the comments page first: `comment_id` is a comment's `id` from `GET /v1/videos/{platform}/{id}/comments`.\n\n- **Unlisted comment:** a free 404 `comment_not_found`.\n- **Items:** each reply is a comment item with `parent_id` set to `comment_id` and, like comments, no author information.\n- **No replies:** an empty `items` and a null `next_cursor`.\n- **Retention:** purged after 90 days, like comments.\n- **Platforms:** TikTok, Instagram and Facebook. Other platforms are `unsupported_platform`.\n- **Facebook:** one level of replies is returned (replies to a reply are not walked), and a comment the platform no longer lists is a free `comment_not_found`.\n- **Instagram:** a comment's `reply_count` is often 0 even when it has replies, so a thread can be worth asking for.\n\n**Price:** 3 credits per page, the same when the replies are already stored.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=getCommentReplies) (no API Key needed).","tags":["Videos"],"parameters":[{"name":"platform","in":"path","required":true,"description":"Platform the subject lives on.","schema":{"type":"string","enum":["tiktok","instagram","facebook"]}},{"name":"id","in":"path","required":true,"description":"Platform video id.","schema":{"type":"string"}},{"name":"comment_id","in":"path","required":true,"description":"The comment's `id`, as the comments page returned it.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit_5"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Wait"},{"$ref":"#/components/parameters/MaxCredits"},{"$ref":"#/components/parameters/Estimate_2"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"The Run finished inside the wait budget: `{ run, result }`. With `estimate=true`, `{ estimate_credits, cached }` instead.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"type":"object","properties":{"platform":{"type":"string"},"video_id":{"type":"string"},"comment_id":{"type":"string","description":"The comment whose replies these are."},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"text":{"type":"string","description":"No author information: it is dropped as the comment is fetched."},"like_count":{"type":"integer"},"reply_count":{"type":"integer"},"posted_at":{"type":["string","null"]},"parent_id":{"type":["string","null"],"description":"Null on the comments page; on a replies page, the comment replied to."},"fetched_at":{"type":"string"}},"required":["id","text","like_count","reply_count","posted_at","parent_id","fetched_at"]}},"next_cursor":{"type":["string","null"]}},"required":["platform","video_id","comment_id","items","next_cursor"]}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"video_comment_replies","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":{"platform":"tiktok","video_id":"7300000000000000000","comment_id":"7300100000000000001","items":[{"id":"7300200000000000001","text":"colder for longer, in my experience","like_count":312,"reply_count":0,"posted_at":"2026-09-06T09:15:00.000Z","parent_id":"7300100000000000001","fetched_at":"2026-09-08T09:14:04.219Z"},{"id":"7300200000000000002","text":"the creator answered this in her next video","like_count":87,"reply_count":0,"posted_at":"2026-09-06T10:40:00.000Z","parent_id":"7300100000000000001","fetched_at":"2026-09-08T09:14:04.219Z"}],"next_cursor":"eyJpZCI6ImNtXzAyIn0"}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":3,"cached":false}}}}}},"202":{"description":"Still running: `{ run }`. Poll `GET /v1/runs/{id}`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningEnvelope"},"example":{"run":{"id":"run_8f2c1ad04b","kind":"video_comment_replies","status":"running","created_at":"2026-09-08T09:14:02.418Z","completed_at":null,"charge_credits":0,"list_price_credits":0,"cached":false},"poll_url":"https://www.shortsintel.com/v1/runs/run_8f2c1ad04b"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"$ref":"#/components/responses/Problem402_2"},"404":{"description":"`comment_not_found`: the video is not held, or the comment is not one of its top-level comments the comments page listed. Refused before any Run opens; nothing is charged.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/comment_not_found","title":"Comment not found","status":404,"code":"comment_not_found","detail":"We don't hold that comment for that video. Read GET /v1/videos/{platform}/{id}/comments first and use a comment's `id`.","retryable":false,"action":"Read the video's comments page first and pass one of its item ids as `comment_id`."}}}},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"description":"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.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Retry with a backoff; nothing was charged.","run":{"id":"run_8f2c1ad04b","kind":"video_comment_replies","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":{"description":"`source_unavailable`: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; `endpoints` names the source. Wait `retry_after_seconds` (also sent as `Retry-After`) and retry rather than treating it as empty.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Wait `retry_after_seconds`, then retry; do not treat this as an empty result.","endpoints":["tiktok/video"],"run":{"id":"run_8f2c1ad04b","kind":"video_comment_replies","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},"retry_after_seconds":60}}}}},"x-price":{"credits":3,"unit":"page","max_credits":3}}},"/videos/{platform}/{id}/snapshots":{"get":{"operationId":"listVideoSnapshots","summary":"Read a video's metric history","description":"Views and metrics over time, newest first. `not_found` until looked up with `GET /v1/videos/{platform}/{id}`.\n\n- **Nulls and zeros:** a metric is null where its Snapshot marks it unreported. One a Platform never reports can still read 0, such as Instagram and Facebook shares and saves.\n- **Ad fields:** `is_ad`/`paid_partnership` appear where recorded.\n- **Retention:** shared and kept forever, so history predates your first lookup.\n- **Gaps:** a video gets Snapshots only when a lookup, search, Creator Tracker page or Keyword, Hashtag or Sound Sample reads it, so a missing day is not a drop.\n\n**Price:** Free.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=listVideoSnapshots) (no API Key needed).","tags":["Videos"],"parameters":[{"name":"platform","in":"path","required":true,"description":"Platform the subject lives on.","schema":{"type":"string","enum":["tiktok","instagram","youtube","facebook"]}},{"name":"id","in":"path","required":true,"description":"Platform video id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit_5"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"`{ items, next_cursor }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string","description":"When the metrics were read."},"views":{"type":["number","null"],"description":"Views at `at`. Null when the Snapshot marks them unreported."},"metrics":{"type":"object","properties":{"views":{"type":["number","null"],"description":"Views. Null when the Snapshot marks it unreported."},"likes":{"type":["number","null"],"description":"Likes. Null when the Snapshot marks it unreported."},"comments":{"type":["number","null"],"description":"Comments. Null when the Snapshot marks it unreported."},"shares":{"type":["number","null"],"description":"Shares. Null when the Snapshot marks it unreported."},"saves":{"type":["number","null"],"description":"Saves. Null when the Snapshot marks it unreported."},"is_ad":{"type":["boolean","null"],"description":"The Platform marked the video as an ad at `at`. Present only when the read recorded ad flags."},"paid_partnership":{"type":["boolean","null"],"description":"The Platform marked a paid partnership at `at`. Present only when the read recorded ad flags."}},"required":["views","likes","comments","shares","saves"],"description":"The public metrics recorded at `at`."},"source":{"type":"string","description":"`vendor` or `backfill`."}},"required":["at","views","metrics","source"]}}},"required":["items"]}]},"example":{"items":[{"at":"2026-09-08T09:14:04.219Z","views":1284000,"metrics":{"views":1284000,"likes":98200,"comments":1410,"shares":3020,"saves":7650,"is_ad":false,"paid_partnership":false},"source":"vendor"},{"at":"2026-09-07T09:12:58.104Z","views":912400,"metrics":{"views":912400,"likes":70150,"comments":1022,"shares":2210,"saves":null},"source":"vendor"}],"next_cursor":"eyJpZCI6ImNsdjRxOHoifQ"}}}},"400":{"$ref":"#/components/responses/Problem400_6"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/creators/{platform}/{handle}":{"get":{"operationId":"getCreator","summary":"Look up a creator and baseline","description":"Profile, follower stats, baseline and Scores for one creator on TikTok, Instagram, YouTube or Facebook.\n\n- **Baseline:** median views, p90, mean engagement rate, posts per week, sample size and confidence. It is stale after 7 days and refreshed by this lookup.\n- **Contact details:** `contact` carries what the account publishes itself: a Facebook Page's public email, phone, address and website (`source: \"profile\"`), else the first email address in the bio on any platform (`source: \"bio\"`). Null when none.\n- **Contact use:** using it lawfully (anti-spam and data-protection rules) is the caller's responsibility.\n\n**Instagram**\n\n- **Profile:** adds `verified`.\n- **Videos:** `include=videos` returns the first page of the creator's Reels, or of all their posts (carousels and photos too) with `videos_from=posts`, with a `next_cursor` to pass back as `cursor`.\n- **Feed items:** they come as the source gave them. An unreported count is 0, and such a video has no Scores.\n\n**YouTube**\n\n- **Handle:** `{handle}` is an `@handle`, a channel id (`UC…`) or a channel URL.\n- **Profile:** the creator is the channel, with subscribers as `follower_count`, description as `bio`, plus `video_count` and `verified`.\n- **Videos:** `include=videos` returns one page of its Shorts (never long-form) with a `next_cursor`.\n\n**Facebook**\n\n- **Handle:** the Creator is a Page, by vanity name, numeric id, Page URL or `profile.php?id=` URL.\n- **Profile:** adds `like_count` and `category`.\n- **Videos:** `include=videos` reads its reels (default) or posts (`videos_from=posts`) with `next_cursor` as on Instagram.\n- **Advertiser:** `advertiser` links the Meta Advertiser with the same Page id when we hold it.\n\n**Price:** 6 credits, the same when a creator Snapshot under 24 h old and a baseline under 7 days old can answer. A next page of videos (`cursor`) is 3 credits.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=getCreator) (no API Key needed).","tags":["Creators"],"parameters":[{"name":"platform","in":"path","required":true,"description":"Platform the subject lives on.","schema":{"type":"string","enum":["tiktok","instagram","youtube","facebook"]}},{"name":"handle","in":"path","required":true,"description":"A bare handle, an `@handle`, or a URL-encoded profile URL — whichever the user pasted.","schema":{"type":"string"}},{"name":"include","in":"query","required":false,"description":"`videos` adds the creator's recent videos.","schema":{"type":"string","enum":["videos"]}},{"name":"videos_from","in":"query","required":false,"description":"Instagram (and Facebook): which feed `include=videos` reads, `reels` (default) or `posts`, every post including photo carousels. Refused with `invalid_request` on TikTok and YouTube.","schema":{"type":"string","enum":["reels","posts"],"default":"reels"}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` a previous lookup with `include=videos` returned: reads only the next page of that feed, for 3 credits. It continues only the creator and platform that returned it; any other is refused with `invalid_request`.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Wait"},{"$ref":"#/components/parameters/MaxCredits"},{"$ref":"#/components/parameters/Estimate_2"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"The Run finished inside the wait budget: `{ run, result }`. With `estimate=true`, `{ estimate_credits, cached }` instead.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"$ref":"#/components/schemas/Creator"}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"creator_lookup","status":"completed","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":6,"list_price_credits":6,"cached":false},"result":{"platform":"tiktok","id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","follower_count":184300,"bio":"Cold water, early mornings, and the numbers behind both. hello@someone.example","verified":false,"video_count":214,"total_likes":4210000,"following_count":312,"links":[{"title":null,"url":"https://linktr.ee/someone"}],"joined_at":"2020-01-14T09:12:40.000Z","country":"US","business":{"is_business":false,"category":null},"total_views":null,"contact":{"email":"hello@someone.example","phone":null,"address":null,"website":null,"source":"bio"},"snapshot":{"at":"2026-09-08T09:14:04.219Z","followers":184300},"baseline":{"median_views":305000,"p90_views":802000,"engagement_rate":0.1342,"posts_per_week":4.1,"sample":20,"confidence":"high","source":"videos","computed_at":"2026-09-08T09:14:03.902Z","stale":false},"videos":[{"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","author":"someone","is_original":true},"creator":{"id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","verified":false},"region":"US","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[{"kind":"54","label":"CapCut · Editing made easy"}]},"people":{"mentions":["coldplungeco"],"collaborators":[]},"location":null,"topics":{"keywords":[],"genre":null,"labels":["Fitness","Health"]},"chapters":null,"ai_generated":false,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":1284000,"likes":143200,"comments":2810,"shares":9040,"saves":21600},"scores":{"outlier":4.21,"outlier_p90":1.6,"percentile":95,"velocity":{"views_per_hour":6698.6,"window":"snapshot"},"reason":null,"baseline":{"median_views":305000,"p90_views":802000,"engagement_rate":0.1342,"posts_per_week":4.1,"sample":20,"confidence":"high","source":"videos","computed_at":"2026-09-08T09:14:03.902Z","stale":false}}},{"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","author":"Northbound","is_original":false},"creator":{"id":"cre_1a77c0b3de","handle":"anotherone","name":"Another One","follower_count":21400,"avatar_url":null,"verified":null},"region":"GB","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[]},"people":null,"location":null,"topics":null,"chapters":null,"ai_generated":null,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":96200,"likes":8140,"comments":212,"shares":401,"saves":1180},"scores":null}]}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":6,"cached":false}}}}}},"202":{"description":"Still running: `{ run }`. Poll `GET /v1/runs/{id}`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningEnvelope"},"example":{"run":{"id":"run_8f2c1ad04b","kind":"creator_lookup","status":"running","created_at":"2026-09-08T09:14:02.418Z","completed_at":null,"charge_credits":0,"list_price_credits":0,"cached":false},"poll_url":"https://www.shortsintel.com/v1/runs/run_8f2c1ad04b"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"$ref":"#/components/responses/Problem402_3"},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"description":"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.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Retry with a backoff; nothing was charged.","run":{"id":"run_8f2c1ad04b","kind":"creator_lookup","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":{"description":"`source_unavailable`: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; `endpoints` names the source. Wait `retry_after_seconds` (also sent as `Retry-After`) and retry rather than treating it as empty.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Wait `retry_after_seconds`, then retry; do not treat this as an empty result.","endpoints":["tiktok/video"],"run":{"id":"run_8f2c1ad04b","kind":"creator_lookup","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},"retry_after_seconds":60}}}}},"x-price":{"credits":6,"unit":"call","max_credits":6}}},"/creators/{platform}/{handle}/videos":{"get":{"operationId":"listCreatorVideos","summary":"Page a creator's stored videos","description":"The creator's videos as we already hold them, newest first, each with its Scores. It fetches nothing new: for fresh videos, call the creator lookup with `include=videos` first, then page here.\n\n- **Analysis:** with `intelligence=true` the page is analysed exactly like `POST /v1/videos/search` with `intelligence: true`, on every Platform.\n- **Run:** its passes run as a workflow, one RunItem per analysed video at `GET /v1/runs/{id}/items`, at most 20 videos analysed.\n- **Failures:** a video that cannot be analysed (`media_unavailable`, or `video_too_long` past 10 minutes) comes back with `intelligence: null` and `intelligence_error`, uncharged. A Run where none could be analysed fails free.\n\n**Price:** Free. Counts toward the per-key request limit. `intelligence=true` costs 20 credits for each of the first 20 videos analysed, whether analysed now or already; the page itself stays free.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=listCreatorVideos) (no API Key needed).","tags":["Creators"],"parameters":[{"name":"platform","in":"path","required":true,"description":"Platform the subject lives on.","schema":{"type":"string","enum":["tiktok","instagram","youtube","facebook"]}},{"name":"handle","in":"path","required":true,"description":"A bare handle, an `@handle`, or a URL-encoded profile URL — whichever the user pasted.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit_5"},{"$ref":"#/components/parameters/Cursor"},{"name":"intelligence","in":"query","required":false,"description":"Analyse the page's first 20 videos in a Run, like search with `intelligence: true`. Takes `wait`, `estimate` and an Idempotency-Key.","schema":{"type":"boolean"}},{"$ref":"#/components/parameters/Wait"},{"$ref":"#/components/parameters/MaxCredits"},{"$ref":"#/components/parameters/Estimate"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"`{ items, next_cursor }`. With `intelligence=true`, the Run envelope `{ run, result }` instead, `result` being the page with `intelligence` on each analysed video (or `{ estimate_credits, ... }` with `estimate=true`).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Video"}}},"required":["items"]}]},{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"type":"object","properties":{"items":{"type":"array","items":{"description":"One normalised video, the same shape on every platform.","allOf":[{"$ref":"#/components/schemas/Video"},{"type":"object","properties":{"intelligence":{"description":"The analysis. Null when this video could not be analysed (uncharged); absent past the cap.","anyOf":[{"$ref":"#/components/schemas/Analysis"},{"type":"null"}]},"intelligence_error":{"$ref":"#/components/schemas/Problem","description":"Why `intelligence` is null."}}}]}},"next_cursor":{"type":["string","null"]},"intelligence":{"type":"object","properties":{"requested":{"type":"integer"},"completed":{"type":"integer"},"failed":{"type":"integer"},"cap":{"type":"integer"}},"required":["requested","completed","failed","cap"],"description":"Per-video outcomes page at `GET /v1/runs/{id}/items`."}},"required":["items","next_cursor","intelligence"]}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]}]},"example":{"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","author":"someone","is_original":true},"creator":{"id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","verified":false},"region":"US","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[{"kind":"54","label":"CapCut · Editing made easy"}]},"people":{"mentions":["coldplungeco"],"collaborators":[]},"location":null,"topics":{"keywords":[],"genre":null,"labels":["Fitness","Health"]},"chapters":null,"ai_generated":false,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":1284000,"likes":143200,"comments":2810,"shares":9040,"saves":21600},"scores":{"outlier":4.21,"outlier_p90":1.6,"percentile":95,"velocity":{"views_per_hour":6698.6,"window":"snapshot"},"reason":null,"baseline":{"median_views":305000,"p90_views":802000,"engagement_rate":0.1342,"posts_per_week":4.1,"sample":20,"confidence":"high","source":"videos","computed_at":"2026-09-08T09:14:03.902Z","stale":false}}},{"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","author":"Northbound","is_original":false},"creator":{"id":"cre_1a77c0b3de","handle":"anotherone","name":"Another One","follower_count":21400,"avatar_url":null,"verified":null},"region":"GB","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[]},"people":null,"location":null,"topics":null,"chapters":null,"ai_generated":null,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":96200,"likes":8140,"comments":212,"shares":401,"saves":1180},"scores":null}],"next_cursor":"eyJpZCI6ImNsdjRxOHkifQ"}}}},"202":{"description":"Still running: `{ run }`. Poll `GET /v1/runs/{id}`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningEnvelope"},"example":{"run":{"id":"run_8f2c1ad04b","kind":"creator_videos","status":"running","created_at":"2026-09-08T09:14:02.418Z","completed_at":null,"charge_credits":0,"list_price_credits":0,"cached":false},"poll_url":"https://www.shortsintel.com/v1/runs/run_8f2c1ad04b"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"description":"`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`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/insufficient_balance","title":"Insufficient balance","status":402,"code":"insufficient_balance","detail":"Your balance is 0 Credits and this operation needs 20 Credits. Nothing was charged.","retryable":false,"action":"Tell the Customer to top up the Balance, then repeat the same request.","balance_credits":0,"required_credits":20}}}},"404":{"$ref":"#/components/responses/Problem404_2"},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"description":"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.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Retry with a backoff; nothing was charged.","run":{"id":"run_8f2c1ad04b","kind":"creator_videos","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":{"description":"`source_unavailable`: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; `endpoints` names the source. Wait `retry_after_seconds` (also sent as `Retry-After`) and retry rather than treating it as empty.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Wait `retry_after_seconds`, then retry; do not treat this as an empty result.","endpoints":["tiktok/video"],"run":{"id":"run_8f2c1ad04b","kind":"creator_videos","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},"retry_after_seconds":60}}}}},"x-price":{"credits":0,"unit":"page","max_credits":400}}},"/creators/{platform}/{handle}/snapshots":{"get":{"operationId":"listCreatorSnapshots","summary":"Read follower history","description":"Follower history, newest first. Snapshots are shared across Customers and kept forever, so history predates your first lookup.\n\n**Price:** Free.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=listCreatorSnapshots) (no API Key needed).","tags":["Creators"],"parameters":[{"name":"platform","in":"path","required":true,"description":"Platform the subject lives on.","schema":{"type":"string","enum":["tiktok","instagram","youtube","facebook"]}},{"name":"handle","in":"path","required":true,"description":"A bare handle, an `@handle`, or a URL-encoded profile URL — whichever the user pasted.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit_5"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"`{ items, next_cursor }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string"},"followers":{"type":["number","null"]},"metrics":{},"source":{"type":"string"}},"required":["at","followers","source"]}}},"required":["items"]}]},"example":{"items":[{"at":"2026-09-08T09:14:04.219Z","followers":184300,"metrics":{"followers":184300,"likes":3120000},"source":"vendor"},{"at":"2026-09-07T09:12:58.104Z","followers":181950,"metrics":{"followers":181950,"likes":3094000},"source":"vendor"}],"next_cursor":null}}}},"400":{"$ref":"#/components/responses/Problem400_6"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/hashtags/{platform}/{tag}":{"get":{"operationId":"getHashtag","summary":"Look up a hashtag's trend","description":"Stats, trend direction and top videos, with a Snapshot written every time so the next lookup has something to compare against.\n\n**Price:** 3 credits, the same when a Snapshot under 24 h old can answer.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=getHashtag) (no API Key needed).","tags":["Hashtags"],"parameters":[{"name":"platform","in":"path","required":true,"description":"Platform the subject lives on.","schema":{"type":"string","enum":["tiktok","instagram"]}},{"name":"tag","in":"path","required":true,"description":"Tag without the `#`.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Wait"},{"$ref":"#/components/parameters/MaxCredits"},{"$ref":"#/components/parameters/Estimate_2"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"The Run finished inside the wait budget: `{ run, result }`. With `estimate=true`, `{ estimate_credits, cached }` instead.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"type":"object","properties":{"platform":{"type":"string"},"tag":{"type":"string"},"url":{"type":["string","null"]},"platform_id":{"type":["string","null"],"description":"The platform's own id for the tag, as its videos report it. TikTok only; null on Instagram or when no video reported it."},"description":{"type":["string","null"],"description":"The platform's description of the tag, as its videos report it. TikTok only; null on Instagram or when none was given."},"stats":{"type":"object","properties":{"sampled_videos":{"type":"integer"},"views_total":{"type":"number"},"views_median":{"type":["number","null"]},"views_max":{"type":["number","null"]},"likes_total":{"type":"number"},"comments_total":{"type":"number"},"engagement_rate":{"type":["number","null"]}},"required":["sampled_videos","views_total","views_median","views_max","likes_total","comments_total","engagement_rate"]},"trend":{"type":"object","properties":{"direction":{"type":["string","null"],"enum":["rising","falling","flat",null]},"change_ratio":{"type":["number","null"]},"since":{"type":["string","null"]}},"required":["direction","change_ratio","since"],"description":"Movement between the two most recent Snapshots."},"snapshot":{"type":"object","properties":{"at":{"type":"string"},"sampled_videos":{"type":"integer"},"views_total":{"type":"number"},"views_median":{"type":["number","null"]},"views_max":{"type":["number","null"]},"likes_total":{"type":"number"},"comments_total":{"type":"number"},"engagement_rate":{"type":["number","null"]}},"required":["at","sampled_videos","views_total","views_median","views_max","likes_total","comments_total","engagement_rate"]},"top_videos":{"type":"array","items":{"$ref":"#/components/schemas/Video"}},"coverage":{"type":"string","enum":["partial"]}},"required":["platform","tag","url","platform_id","description","stats","trend","snapshot","top_videos"]}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"hashtag_lookup","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":{"platform":"tiktok","tag":"coldplunge","url":"https://www.tiktok.com/tag/coldplunge","platform_id":"1610000000000000","description":"Cold water, warm takes. Share your plunge.","stats":{"sampled_videos":30,"views_total":41280000,"views_median":214500,"views_max":1284000,"likes_total":3914000,"comments_total":71200,"engagement_rate":0.1021},"trend":{"direction":"rising","change_ratio":1.34,"since":"2026-09-06T09:11:40.000Z"},"snapshot":{"at":"2026-09-08T09:14:04.219Z","sampled_videos":30,"views_total":41280000,"views_median":214500,"views_max":1284000,"likes_total":3914000,"comments_total":71200,"engagement_rate":0.1021},"top_videos":[{"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","author":"someone","is_original":true},"creator":{"id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","verified":false},"region":"US","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[{"kind":"54","label":"CapCut · Editing made easy"}]},"people":{"mentions":["coldplungeco"],"collaborators":[]},"location":null,"topics":{"keywords":[],"genre":null,"labels":["Fitness","Health"]},"chapters":null,"ai_generated":false,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":1284000,"likes":143200,"comments":2810,"shares":9040,"saves":21600},"scores":{"outlier":4.21,"outlier_p90":1.6,"percentile":95,"velocity":{"views_per_hour":6698.6,"window":"snapshot"},"reason":null,"baseline":{"median_views":305000,"p90_views":802000,"engagement_rate":0.1342,"posts_per_week":4.1,"sample":20,"confidence":"high","source":"videos","computed_at":"2026-09-08T09:14:03.902Z","stale":false}}}]}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":3,"cached":false}}}}}},"202":{"$ref":"#/components/responses/GetHashtag202"},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"$ref":"#/components/responses/Problem402_2"},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"$ref":"#/components/responses/Problem502_5"},"503":{"$ref":"#/components/responses/Problem503_4"}},"x-price":{"credits":3,"unit":"call","max_credits":3}}},"/hashtags/{platform}/{tag}/videos":{"get":{"operationId":"listHashtagVideos","summary":"Page a hashtag's videos","description":"Pages the videos carrying a tag in the platform's own ordering. Always fresh: the ordering is the thing being paged, so a page cannot be served from stored data without answering a different question.\n\n**Price:** 3 credits per page.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=listHashtagVideos) (no API Key needed).","tags":["Hashtags"],"parameters":[{"name":"platform","in":"path","required":true,"description":"Platform the subject lives on.","schema":{"type":"string","enum":["tiktok","instagram"]}},{"name":"tag","in":"path","required":true,"description":"Tag without the `#`.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit_6"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Wait"},{"$ref":"#/components/parameters/MaxCredits"},{"$ref":"#/components/parameters/Estimate"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"The Run finished inside the wait budget: `{ run, result }`. With `estimate=true`, `{ estimate_credits, cached }` instead.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"type":"object","properties":{"platform":{"type":"string"},"tag":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/Video"}},"next_cursor":{"type":["string","null"]},"coverage":{"type":"string","enum":["partial"]}},"required":["platform","tag","items","next_cursor"]}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"hashtag_lookup","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":{"platform":"tiktok","tag":"coldplunge","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","author":"someone","is_original":true},"creator":{"id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","verified":false},"region":"US","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[{"kind":"54","label":"CapCut · Editing made easy"}]},"people":{"mentions":["coldplungeco"],"collaborators":[]},"location":null,"topics":{"keywords":[],"genre":null,"labels":["Fitness","Health"]},"chapters":null,"ai_generated":false,"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","author":"Northbound","is_original":false},"creator":{"id":"cre_1a77c0b3de","handle":"anotherone","name":"Another One","follower_count":21400,"avatar_url":null,"verified":null},"region":"GB","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[]},"people":null,"location":null,"topics":null,"chapters":null,"ai_generated":null,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":96200,"likes":8140,"comments":212,"shares":401,"saves":1180},"scores":null}],"next_cursor":"eyJjIjoiMjUifQ"}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":3,"cached":false}}}}}},"202":{"$ref":"#/components/responses/GetHashtag202"},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"$ref":"#/components/responses/Problem402_2"},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"$ref":"#/components/responses/Problem502_5"},"503":{"$ref":"#/components/responses/Problem503_4"}},"x-price":{"credits":3,"unit":"page","max_credits":3}}},"/sounds/{platform}/{id}":{"get":{"operationId":"getSound","summary":"Look up a sound's trend","description":"Track metadata, the platform's own count of videos using it, sample stats, trend direction and top videos, with a Snapshot written every time. On TikTok `{id}` is the `clipId` from a `/music/<slug>-<clipId>` URL — not the `music.id` carried on a video payload.\n\n**Price:** 6 credits, the same when a Snapshot under 24 h old can answer.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=getSound) (no API Key needed).","tags":["Sounds"],"parameters":[{"name":"platform","in":"path","required":true,"description":"Platform the subject lives on.","schema":{"type":"string","enum":["tiktok"]}},{"name":"id","in":"path","required":true,"description":"Sound id — TikTok's `clipId`.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Wait"},{"$ref":"#/components/parameters/MaxCredits"},{"$ref":"#/components/parameters/Estimate_2"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"The Run finished inside the wait budget: `{ run, result }`. With `estimate=true`, `{ estimate_credits, cached }` instead.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"type":"object","properties":{"platform":{"type":"string"},"id":{"type":"string"},"title":{"type":["string","null"]},"author_name":{"type":["string","null"]},"duration_seconds":{"type":["number","null"]},"cover_url":{"type":["string","null"]},"url":{"type":["string","null"]},"is_original":{"type":["boolean","null"]},"album":{"type":["string","null"],"description":"The album the track is from. Null when not reported."},"artists":{"type":["array","null"],"items":{"type":"object","properties":{"handle":{"type":["string","null"],"description":"The artist's handle on the platform, when they have an account."},"id":{"type":["string","null"],"description":"The artist's platform account id."},"name":{"type":["string","null"]}},"required":["handle","id","name"]},"description":"The people credited on the track. Null when not reported."},"is_commercial":{"type":["boolean","null"],"description":"True for a catalogue track with commercial rights, cleared for business use. Null when the platform did not say, which is not the same as false."},"full_duration_seconds":{"type":["number","null"],"description":"The full song's length, when the sound is a clip of a catalogue track. `duration_seconds` is the clip's."},"released_at":{"type":["string","null"],"description":"When the track was released, ISO 8601. Null when not reported."},"stats":{"type":"object","properties":{"video_count":{"type":["number","null"],"description":"The platform's own count. Authoritative."},"sampled_videos":{"type":"integer"},"views_total":{"type":"number"},"views_median":{"type":["number","null"]},"views_max":{"type":["number","null"]},"likes_total":{"type":"number"},"comments_total":{"type":"number"},"engagement_rate":{"type":["number","null"]}},"required":["video_count","sampled_videos","views_total","views_median","views_max","likes_total","comments_total","engagement_rate"]},"trend":{"type":"object","properties":{"direction":{"type":["string","null"],"enum":["rising","falling","flat",null]},"change_ratio":{"type":["number","null"]},"since":{"type":["string","null"]}},"required":["direction","change_ratio","since"],"description":"Movement between the two most recent Snapshots."},"snapshot":{"type":"object","properties":{"at":{"type":"string"},"video_count":{"type":["number","null"]},"sampled_videos":{"type":"integer"},"views_total":{"type":"number"},"views_median":{"type":["number","null"]},"views_max":{"type":["number","null"]},"likes_total":{"type":"number"},"comments_total":{"type":"number"},"engagement_rate":{"type":["number","null"]}},"required":["at","video_count","sampled_videos","views_total","views_median","views_max","likes_total","comments_total","engagement_rate"]},"top_videos":{"type":"array","items":{"$ref":"#/components/schemas/Video"}}},"required":["platform","id","title","author_name","duration_seconds","cover_url","url","is_original","album","artists","is_commercial","full_duration_seconds","released_at","stats","trend","snapshot","top_videos"]}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"sound_lookup","status":"completed","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":6,"list_price_credits":6,"cached":false},"result":{"platform":"tiktok","id":"7180000000000000000","title":"original sound - someone","author_name":"Someone","duration_seconds":41,"cover_url":"https://p16-sign.tiktokcdn.com/obj/tos-music-7180000000000000000.jpeg","url":"https://www.tiktok.com/music/original-sound-7180000000000000000","is_original":true,"album":null,"artists":[{"handle":"someone","id":"6900000000000000000","name":"Someone"}],"is_commercial":false,"full_duration_seconds":null,"released_at":null,"stats":{"video_count":148230,"sampled_videos":30,"views_total":41280000,"views_median":214500,"views_max":1284000,"likes_total":3914000,"comments_total":71200,"engagement_rate":0.1021},"trend":{"direction":"flat","change_ratio":1.01,"since":"2026-09-06T09:11:40.000Z"},"snapshot":{"at":"2026-09-08T09:14:04.219Z","video_count":148230,"sampled_videos":30,"views_total":41280000,"views_median":214500,"views_max":1284000,"likes_total":3914000,"comments_total":71200,"engagement_rate":0.1021},"top_videos":[{"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","author":"someone","is_original":true},"creator":{"id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","verified":false},"region":"US","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[{"kind":"54","label":"CapCut · Editing made easy"}]},"people":{"mentions":["coldplungeco"],"collaborators":[]},"location":null,"topics":{"keywords":[],"genre":null,"labels":["Fitness","Health"]},"chapters":null,"ai_generated":false,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":1284000,"likes":143200,"comments":2810,"shares":9040,"saves":21600},"scores":{"outlier":4.21,"outlier_p90":1.6,"percentile":95,"velocity":{"views_per_hour":6698.6,"window":"snapshot"},"reason":null,"baseline":{"median_views":305000,"p90_views":802000,"engagement_rate":0.1342,"posts_per_week":4.1,"sample":20,"confidence":"high","source":"videos","computed_at":"2026-09-08T09:14:03.902Z","stale":false}}}]}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":6,"cached":false}}}}}},"202":{"$ref":"#/components/responses/GetSound202"},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"$ref":"#/components/responses/Problem402_3"},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"$ref":"#/components/responses/Problem502_6"},"503":{"$ref":"#/components/responses/Problem503_5"}},"x-price":{"credits":6,"unit":"call","max_credits":6}}},"/sounds/{platform}/{id}/videos":{"get":{"operationId":"listSoundVideos","summary":"Page a sound's videos","description":"Pages the videos using a sound, in the platform's own ordering. Always fresh, for the same reason as the hashtag videos page.\n\n**Price:** 6 credits per page.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=listSoundVideos) (no API Key needed).","tags":["Sounds"],"parameters":[{"name":"platform","in":"path","required":true,"description":"Platform the subject lives on.","schema":{"type":"string","enum":["tiktok"]}},{"name":"id","in":"path","required":true,"description":"Sound id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit_6"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/Wait"},{"$ref":"#/components/parameters/MaxCredits"},{"$ref":"#/components/parameters/Estimate"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"The Run finished inside the wait budget: `{ run, result }`. With `estimate=true`, `{ estimate_credits, cached }` instead.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"type":"object","properties":{"platform":{"type":"string"},"id":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/Video"}},"next_cursor":{"type":["string","null"]}},"required":["platform","id","items","next_cursor"]}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"sound_lookup","status":"completed","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":6,"list_price_credits":6,"cached":false},"result":{"platform":"tiktok","id":"7180000000000000000","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","author":"someone","is_original":true},"creator":{"id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","verified":false},"region":"US","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[{"kind":"54","label":"CapCut · Editing made easy"}]},"people":{"mentions":["coldplungeco"],"collaborators":[]},"location":null,"topics":{"keywords":[],"genre":null,"labels":["Fitness","Health"]},"chapters":null,"ai_generated":false,"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","author":"Northbound","is_original":false},"creator":{"id":"cre_1a77c0b3de","handle":"anotherone","name":"Another One","follower_count":21400,"avatar_url":null,"verified":null},"region":"GB","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[]},"people":null,"location":null,"topics":null,"chapters":null,"ai_generated":null,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":96200,"likes":8140,"comments":212,"shares":401,"saves":1180},"scores":null}],"next_cursor":"eyJjIjoiMjUifQ"}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":6,"cached":false}}}}}},"202":{"$ref":"#/components/responses/GetSound202"},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"$ref":"#/components/responses/Problem402_3"},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"$ref":"#/components/responses/Problem502_6"},"503":{"$ref":"#/components/responses/Problem503_5"}},"x-price":{"credits":6,"unit":"page","max_credits":6}}},"/keywords/{platform}":{"get":{"operationId":"getKeyword","summary":"Sample a keyword search","description":"One page of the platform's search for a phrase: sample stats, trend direction and the top 10 videos by views. The numbers are sample-based, not platform totals.\n\n- **Search:** relevance order, the past month, unfiltered, no region.\n- **Snapshots:** one per call, for the next lookup to compare against.\n- **Matching:** a phrase matches ignoring case and extra spaces, otherwise exactly. `Skin  Care` is `skin care`, and `skincare` is a different keyword.\n- **Limits:** an empty phrase, or one over 100 characters, is `invalid_request` before any Run.\n- **Coverage:** best-effort on Instagram and Facebook (`coverage: \"partial\"`).\n- **Focus:** with `focus` the top videos are judged against it and off-focus ones hidden, `off_focus_count` saying how many. The stats and Snapshot stay unfiltered.\n\n**Price:** 3 credits, the same when a Snapshot under 24 h old can answer. `focus`: +3 credits per Video the model judges, +1 credit per Video `must_mention` rules out, nothing for one already judged under the same Focus or one that could not be judged (shown); `estimate` quotes every returned Video judged.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=getKeyword) (no API Key needed).","tags":["Keywords"],"parameters":[{"name":"platform","in":"path","required":true,"description":"Platform the subject lives on.","schema":{"type":"string","enum":["tiktok","instagram","youtube","facebook"]}},{"name":"phrase","in":"query","required":true,"description":"The search phrase, at most 100 characters. URL-encode its spaces.","schema":{"type":"string","minLength":1,"maxLength":100,"example":"cold plunge routine"}},{"name":"focus","in":"query","required":false,"description":"Which Videos are relevant to you, in plain language, exclusions included, e.g. `Apple Inc. and its products (iPhone, Mac, AirPods, iOS). Not the fruit, recipes or orchards.` 1 to 1000 characters. Judges the top videos against it and hides the off-focus ones.","schema":{"type":"string","minLength":1,"maxLength":1000}},{"name":"must_mention","in":"query","required":false,"description":"With `focus`: one term per param, repeated (`must_mention=apple&must_mention=iphone`); a comma is part of the term. Up to 20 terms of at most 60 characters. A Video that has captions or an analysis transcript, and whose caption, hashtags, captions and transcript name none of them (any case, whole term), is off focus without a model call; one with neither goes to the model, so a term said aloud still counts; one naming any is still judged against `text`.","schema":{"type":"array","items":{"type":"string","maxLength":60}},"style":"form","explode":true},{"name":"include_off_focus","in":"query","required":false,"description":"With `focus`: `true` returns every top video, each with `focus: { verdict, reason }`.","schema":{"type":"boolean"}},{"$ref":"#/components/parameters/Wait"},{"$ref":"#/components/parameters/MaxCredits"},{"$ref":"#/components/parameters/Estimate_2"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"The Run finished inside the wait budget: `{ run, result }`. With `estimate=true`, `{ estimate_credits, cached }` instead.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"type":"object","properties":{"platform":{"type":"string"},"phrase":{"type":"string","description":"The phrase as normalised: trimmed, spaces collapsed, lowercased."},"stats":{"type":"object","properties":{"sampled_videos":{"type":"integer"},"views_total":{"type":"number"},"views_median":{"type":["number","null"]},"views_max":{"type":["number","null"]},"likes_total":{"type":"number"},"comments_total":{"type":"number"},"engagement_rate":{"type":["number","null"]}},"required":["sampled_videos","views_total","views_median","views_max","likes_total","comments_total","engagement_rate"],"description":"Sample-based: one page of the platform's search, not its totals."},"trend":{"type":"object","properties":{"direction":{"type":["string","null"],"enum":["rising","falling","flat",null]},"change_ratio":{"type":["number","null"]},"since":{"type":["string","null"]}},"required":["direction","change_ratio","since"],"description":"Movement between the two most recent Snapshots."},"snapshot":{"type":"object","properties":{"at":{"type":"string"},"sampled_videos":{"type":"integer"},"views_total":{"type":"number"},"views_median":{"type":["number","null"]},"views_max":{"type":["number","null"]},"likes_total":{"type":"number"},"comments_total":{"type":"number"},"engagement_rate":{"type":["number","null"]}},"required":["at","sampled_videos","views_total","views_median","views_max","likes_total","comments_total","engagement_rate"]},"top_videos":{"type":"array","items":{"description":"One normalised video, the same shape on every platform.","allOf":[{"$ref":"#/components/schemas/Video"},{"type":"object","properties":{"focus":{"type":"object","properties":{"verdict":{"type":"string","enum":["in_focus","off_focus","unjudged"],"description":"`unjudged`: the Video could not be judged (or is not judged yet) and is shown."},"reason":{"type":"string"}},"required":["verdict","reason"],"description":"Present only with `focus` and `include_off_focus`."}}}]},"description":"With `focus`, the in-focus and unjudged ones (every one with `include_off_focus`)."},"coverage":{"type":"string","enum":["partial"],"description":"`partial` on Instagram and Facebook, whose search is a best-effort index."},"off_focus_count":{"type":"integer","description":"Present only with `focus`: how many Videos were judged off focus (hidden unless `include_off_focus`)."},"unjudged_count":{"type":"integer","description":"Present only with `focus`: how many shown Videos could not be judged (never counted in focus)."}},"required":["platform","phrase","stats","trend","snapshot","top_videos"]}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"keyword_lookup","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":{"platform":"tiktok","phrase":"cold plunge routine","stats":{"sampled_videos":30,"views_total":41280000,"views_median":214500,"views_max":1284000,"likes_total":3914000,"comments_total":71200,"engagement_rate":0.1021},"trend":{"direction":"rising","change_ratio":1.21,"since":"2026-09-06T09:11:40.000Z"},"snapshot":{"at":"2026-09-08T09:14:04.219Z","sampled_videos":30,"views_total":41280000,"views_median":214500,"views_max":1284000,"likes_total":3914000,"comments_total":71200,"engagement_rate":0.1021},"top_videos":[{"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","author":"someone","is_original":true},"creator":{"id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","verified":false},"region":"US","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[{"kind":"54","label":"CapCut · Editing made easy"}]},"people":{"mentions":["coldplungeco"],"collaborators":[]},"location":null,"topics":{"keywords":[],"genre":null,"labels":["Fitness","Health"]},"chapters":null,"ai_generated":false,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":1284000,"likes":143200,"comments":2810,"shares":9040,"saves":21600},"scores":{"outlier":4.21,"outlier_p90":1.6,"percentile":95,"velocity":{"views_per_hour":6698.6,"window":"snapshot"},"reason":null,"baseline":{"median_views":305000,"p90_views":802000,"engagement_rate":0.1342,"posts_per_week":4.1,"sample":20,"confidence":"high","source":"videos","computed_at":"2026-09-08T09:14:03.902Z","stale":false}}}]}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":3,"cached":false}}}}}},"202":{"description":"Still running: `{ run }`. Poll `GET /v1/runs/{id}`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningEnvelope"},"example":{"run":{"id":"run_8f2c1ad04b","kind":"keyword_lookup","status":"running","created_at":"2026-09-08T09:14:02.418Z","completed_at":null,"charge_credits":0,"list_price_credits":0,"cached":false},"poll_url":"https://www.shortsintel.com/v1/runs/run_8f2c1ad04b"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"$ref":"#/components/responses/Problem402_2"},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"description":"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.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Retry with a backoff; nothing was charged.","run":{"id":"run_8f2c1ad04b","kind":"keyword_lookup","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":{"description":"`source_unavailable`: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; `endpoints` names the source. Wait `retry_after_seconds` (also sent as `Retry-After`) and retry rather than treating it as empty.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Wait `retry_after_seconds`, then retry; do not treat this as an empty result.","endpoints":["tiktok/video"],"run":{"id":"run_8f2c1ad04b","kind":"keyword_lookup","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},"retry_after_seconds":60}}}}},"x-price":{"credits":3,"unit":"call","max_credits":33}}},"/ads/search":{"post":{"operationId":"searchAds","summary":"Search ad libraries","description":"The Meta or TikTok ad library, by keyword or by advertiser. Pass exactly one of `query` or `advertiser`. Keyword searches are always live.\n\n**Meta**\n\n- **Advertiser:** a Facebook Page id, Page URL or name.\n- **Ambiguous name:** a name several Pages carry is a free 409 `advertiser_ambiguous` with `candidates` (`page_id`, `name`, `page_url`, `instagram`, `ad_count`), never a guess. An estimate answers the same 409 when two or more stored Advertisers carry the name.\n- **Stored results:** an `advertiser` search by Page id or URL within 6 hours of a complete observation is served from storage at the same price unless it sets `country`, saying `cached` and `as_of`.\n- **Complete observation:** a `status: all` search with no other filter read to the end, or a fresh `GET /v1/advertisers/{page_id}`.\n- **Filters:** `country` (omit for every country), `status` (running by default), `kind` (commercial by default), `media_type`, `placements` and a start-date range.\n- **Paging:** a `limit` up to 500, read across library pages. `next_cursor` gives more.\n- **Storage:** every Meta Ad returned is stored with its Advertiser and a Snapshot, one Run item each.\n\n**TikTok**\n\n- **Regions:** the library holds only Ads delivered in the EU/EEA, Switzerland, the UK and Turkey.\n- **Results:** one page per call, stored (media archived once looked up), with `spend` and `impressions` null.\n- **Not available:** `country`, Meta-only filters and `analyze`.\n- **Advertiser:** an advertiser id (once stored), a library.tiktok.com advertiser URL or a name.\n- **Ambiguous name:** a name several advertisers carry (case counts) is the same free 409, with `candidates` `{ advertiser_id, name, url }`. Pass one's `url` back.\n\n**Analysis**\n\n- **Scope:** `analyze: true` analyses the first 50 Ads from our archived media, the ad copy as context.\n- **Video Ads:** the video set (transcript, hook, persuasion, tone, visual, safety).\n- **Image and carousel Ads:** the image set (copy angle, offer, CTA, visual format, topics, sentiment).\n- **Reuse:** computed once per Ad and version, reused by later Runs at the same charge. Every Ad carries any stored analysis.\n- **Timing:** after the read, so expect a 202 and poll.\n- **Failures:** a failed Ad is uncharged and makes the Run `partial`. A Run with no analysis fails, uncharged.\n\n**Library failures**\n\n- **Part-way:** the Run is left `partial`, charged for the Ads delivered, with `incomplete` saying why and `next_cursor` resuming.\n- **Unreachable:** the Run (and an estimate) fails with `source_unavailable`, uncharged.\n\n**Price:** Meta: 1 credit per Ad delivered, the same when served from a recent advertiser observation, plus 20 credits per Ad analysed with `analyze`, computed or already stored; the estimate quotes `limit` Ads, all analysed up to the cap with `analyze`. TikTok: 3 credits per page.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=searchAds) (no API Key needed).","tags":["Ads"],"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"library":{"type":"string","enum":["meta","tiktok"],"description":"`meta`, the Meta Ad Library (Facebook and Instagram Ads, priced per Ad delivered), or `tiktok`, the TikTok ad library (Ads delivered in the EU/EEA, Switzerland, the UK and Turkey, priced per page)."},"query":{"type":"string","minLength":1,"description":"Keywords to search Ads for. Pass this or `advertiser`, exactly one. A Meta keyword search is always fetched live."},"advertiser":{"type":"string","minLength":1,"description":"Every Ad of one advertiser instead of a keyword search; pass this or `query`, exactly one. Meta: a Facebook Page id, Page URL or name. TikTok: the library's advertiser id, a library.tiktok.com URL or a name. A name several advertisers carry is 409 `advertiser_ambiguous` with candidates, not charged."},"country":{"type":"string","minLength":2,"maxLength":2,"description":"Two-letter country code; omitted searches every country. Meta only; the TikTok library (Ads delivered in the EU/EEA, Switzerland, the UK and Turkey, searched together) refuses it."},"status":{"type":"string","enum":["active","inactive","all"],"description":"Running (`active`, the default), stopped (`inactive`) or `all`. Meta only; the TikTok library refuses it."},"kind":{"type":"string","enum":["commercial","political","issue","all"],"description":"`commercial` (the default), `political`, `issue` or `all`. Meta only; the TikTok library refuses it."},"media_type":{"type":"string","enum":["video","image","carousel"],"description":"Only Ads of this format; omitted means every format. Meta only; the TikTok library refuses it."},"placements":{"type":"array","items":{"type":"string","enum":["facebook","instagram","messenger","audience_network"]},"minItems":1,"maxItems":4,"description":"Only Ads placed on at least one of these. Meta only; the TikTok library refuses it."},"started_after":{"type":"string","description":"ISO date or timestamp; Ads that started on or after it. Meta only; the TikTok library refuses it."},"started_before":{"type":"string","description":"ISO date or timestamp; Ads that started before it. Meta only; the TikTok library refuses it."},"limit":{"type":"integer","minimum":1,"maximum":500,"description":"Meta: default 50, at most 500, fetched across as many library pages as it takes. TikTok: default 25, at most 30."},"cursor":{"type":"string","minLength":1,"description":"The `next_cursor` of the previous page, to read the next one with the same `library` and filters. Each page is charged."},"order_by":{"type":"string","enum":["relevance","winner","days_running","start_date"],"description":"`relevance` (the default) keeps the library's order; `winner` sorts by winner Score, `days_running` by days run, `start_date` newest first. Highest first, unknowns last; it sorts the returned page, and `next_cursor` still follows the library's order. Meta only; the TikTok library accepts only `relevance`."},"analyze":{"type":"boolean","description":"Ad analysis on the first 50 Ads: 20 credits per Ad, whether computed or already stored at this Ad's current version. Meta only; the TikTok library refuses it."},"wait":{"type":"number","minimum":0,"maximum":120,"default":30,"description":"Seconds to hold the response open before returning a running Run to poll. Default 30, max 120."},"max_credits":{"type":"integer","minimum":0,"description":"As in the query."},"estimate":{"type":"boolean","description":"Meta: If a source the call would read is unavailable and the cache cannot answer, the estimate adds `unavailable` (the `{ platform, capability }` parts it cannot reach), or is a 503 `source_unavailable` when it can reach none. A TikTok library estimate quotes the price without checking."}},"required":["library"],"additionalProperties":false}}}},"responses":{"200":{"description":"The Run finished inside the wait budget: `{ run, result }`. With `estimate=true`, `{ estimate_credits, cached }` instead.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"type":"object","properties":{"library":{"type":"string","enum":["meta","tiktok"]},"items":{"type":"array","items":{"$ref":"#/components/schemas/Ad"}},"next_cursor":{"type":["string","null"]},"total":{"type":["number","null"],"description":"What the library reports for the query, when it reports one and no filter was applied after fetching (any `kind` but `all`, `media_type`, `placements`, a start date)."},"cached":{"type":"boolean","description":"Meta `advertiser` searches only: true when the Ads were served from the advertiser's last complete observation (under 6 hours old) at the cached per-Ad price."},"as_of":{"type":"string","description":"Meta `advertiser` searches only: when these Ads were observed in the library."},"incomplete":{"type":"object","properties":{"code":{"type":"string"},"detail":{"type":"string"}},"required":["code","detail"],"description":"Meta only, on a `partial` Run: the problem that stopped the read after some Ads were delivered."},"intelligence":{"type":"object","properties":{"requested":{"type":"integer"},"computed":{"type":"integer"},"reused":{"type":"integer"},"failed":{"type":"integer"},"cap":{"type":"integer"}},"required":["requested","computed","reused","failed","cap"],"description":"Present only with `analyze: true`: Ads within the cap, how many were computed or reused (both charged) or failed (not charged). Per-Ad outcomes page at `GET /v1/runs/{id}/items`."}},"required":["library","items","next_cursor","total"]}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"ads_search","status":"completed","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":2,"list_price_credits":2,"cached":false},"result":{"library":"meta","items":[{"library":"meta","id":"1122334455667788","url":"https://www.facebook.com/ads/library/?id=1122334455667788","advertiser":{"id":"100064000000001","name":"Plunge"},"is_active":true,"first_shown":"2026-08-01T00:00:00.000Z","last_shown":null,"placements":["FACEBOOK","INSTAGRAM"],"creative":{"title":"Cold water, on your schedule","body":"The tub our testers refused to give back.","cta":"Shop Now","link_url":"https://plunge.example/tub","format":"VIDEO","image_urls":[],"video_urls":["https://video.xx.fbcdn.net/ads/plunge-tub-hd.mp4"],"thumbnail_urls":[]},"reach":{"impressions":null,"spend":null,"currency":null,"audience":null},"kind":"commercial","media_type":"video","countries":null,"variant_count":4,"days_running":72,"winner_score":{"score":88,"confidence":"high","inputs":{"days_running":72,"variants_added":2,"snapshots":6,"advertiser_ads":14},"reason":null}},{"library":"meta","id":"2233445566778899","url":"https://www.facebook.com/ads/library/?id=2233445566778899","advertiser":{"id":"100064000000001","name":"Plunge"},"is_active":false,"first_shown":"2026-06-02T00:00:00.000Z","last_shown":"2026-07-14T00:00:00.000Z","placements":["INSTAGRAM"],"creative":{"title":"Three minutes. Every morning.","body":"Our coldest tub yet, now in matte black.","cta":"Learn More","link_url":"https://plunge.example/black","format":"IMAGE","image_urls":["https://scontent.xx.fbcdn.net/ads/plunge-black.jpg"],"video_urls":[],"thumbnail_urls":[]},"reach":{"impressions":null,"spend":null,"currency":null,"audience":null},"kind":"commercial","media_type":"image","countries":null,"variant_count":null,"days_running":42,"winner_score":{"score":54,"confidence":"low","inputs":{"days_running":42,"variants_added":0,"snapshots":1,"advertiser_ads":14},"reason":"single_snapshot"}}],"next_cursor":"eyJjIjoiQVpVWiIsIm8iOjB9","total":null}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":2,"cached":false,"per_ad_credits":1,"max_ads":2,"priced_per":"ad_delivered"}}}}}},"202":{"description":"Still running: `{ run }`. Poll `GET /v1/runs/{id}`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningEnvelope"},"example":{"run":{"id":"run_8f2c1ad04b","kind":"ads_search","status":"running","created_at":"2026-09-08T09:14:02.418Z","completed_at":null,"charge_credits":0,"list_price_credits":0,"cached":false},"poll_url":"https://www.shortsintel.com/v1/runs/run_8f2c1ad04b"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"description":"`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`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/insufficient_balance","title":"Insufficient balance","status":402,"code":"insufficient_balance","detail":"Your balance is 0 Credits and this operation needs 2 Credits. Nothing was charged.","retryable":false,"action":"Tell the Customer to top up the Balance, then repeat the same request.","balance_credits":0,"required_credits":2}}}},"409":{"description":"`idempotency_conflict` — the same Idempotency-Key with a different payload. Or: `advertiser_ambiguous`: several advertisers carry the name; `candidates` as described above. The Run fails uncharged.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"idempotency_conflict":{"summary":"`idempotency_conflict` — the same Idempotency-Key with a different payload.","value":{"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.","retryable":false,"action":"Resend the original payload with this key, or use a new key for the new payload.","run_id":"run_8f2c1ad04b"}},"advertiser_ambiguous":{"summary":"`advertiser_ambiguous`: several advertisers carry the name; `candidates` as described above. The Run fails uncharged.","value":{"type":"https://www.shortsintel.com/docs/reference/errors/advertiser_ambiguous","title":"Advertiser ambiguous","status":409,"code":"advertiser_ambiguous","detail":"Several TikTok advertisers are named \"Acme\". Ask again with one candidate's url as advertiser. Nothing was charged.","retryable":false,"action":"Ask again with one of `candidates`' `page_id` or `url`.","candidates":[{"advertiser_id":"7614257280497991696","name":"Acme","url":"https://library.tiktok.com/ads?adv_name=Acme&region=all&query_type=2&adv_biz_ids=7614257280497991696"},{"advertiser_id":"7569985924331847688","name":"acme","url":"https://library.tiktok.com/ads?adv_name=acme&region=all&query_type=2&adv_biz_ids=7569985924331847688"}]}}}}}},"429":{"$ref":"#/components/responses/Problem429"},"502":{"description":"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.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Retry with a backoff; nothing was charged.","run":{"id":"run_8f2c1ad04b","kind":"ads_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":{"description":"`source_unavailable`: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; `endpoints` names the source. Wait `retry_after_seconds` (also sent as `Retry-After`) and retry rather than treating it as empty.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Wait `retry_after_seconds`, then retry; do not treat this as an empty result.","endpoints":["tiktok/video"],"run":{"id":"run_8f2c1ad04b","kind":"ads_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},"retry_after_seconds":60}}}}},"x-price":{"credits":1,"unit":"ad","max_credits":1500}}},"/ads/meta/{library_id}":{"get":{"operationId":"getMetaAd","summary":"Look up a Meta Ad by id","description":"One Meta Ad by its Ad Library id, trimmed like a search result, with `as_of` (when it was last observed in the library).\n\n- **Freshness:** served from our stored copy when observed under 6 hours ago. Otherwise read live, stored and given a Snapshot.\n- **Removed Ads:** served from our stored copy with `removed_from_library: true`, at the same price.\n- **Errors:** an id never stored here and not in the library is a free 404 `not_found`. An unreachable library fails the Run with `source_unavailable`, uncharged.\n- **Analysis:** `analyze=true` adds Ad analysis (the video set for a video Ad, the image set for an image or carousel Ad), computed once per Ad and version from our archived media with the ad copy as context.\n- **Analysis timing:** when it must be computed expect a 202 and poll. If it fails the Run fails, uncharged.\n- **Stored analysis:** free on every lookup.\n\n**Price:** 3 credits, read live or from our stored copy (observed under 6 h ago, or removed from the library). With `analyze=true`, plus 20 credits, whether the analysis is computed or already stored.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=getMetaAd) (no API Key needed).","tags":["Ads"],"parameters":[{"name":"library_id","in":"path","required":true,"description":"The Meta Ad Library id: the number in `facebook.com/ads/library/?id=...`.","schema":{"type":"string"}},{"name":"analyze","in":"query","required":false,"description":"`true` to add Ad analysis: 20 credits, computed or already stored.","schema":{"type":"string","enum":["true","false"]}},{"$ref":"#/components/parameters/Wait"},{"$ref":"#/components/parameters/MaxCredits"},{"$ref":"#/components/parameters/Estimate_2"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"The Run finished inside the wait budget: `{ run, result }`. The example is an Ad Meta has removed, served from our stored copy at the same price as a live read.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"type":"object","properties":{"ad":{"allOf":[{"$ref":"#/components/schemas/Ad"},{"type":"object","properties":{"removed_from_library":{"type":"boolean","description":"True when the library no longer shows the Ad and it was served from our stored copy."},"removed_at":{"type":["string","null"],"description":"When this API first found the Ad gone from the library."}},"required":["removed_from_library","removed_at"]}]},"as_of":{"type":["string","null"],"description":"When the Ad was last observed in the library."}},"required":["ad","as_of"]}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"ad_lookup","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":true},"result":{"ad":{"library":"meta","id":"2233445566778899","url":"https://www.facebook.com/ads/library/?id=2233445566778899","advertiser":{"id":"100064000000001","name":"Plunge"},"is_active":false,"first_shown":"2026-06-02T00:00:00.000Z","last_shown":"2026-07-14T00:00:00.000Z","placements":["INSTAGRAM"],"creative":{"title":"Three minutes. Every morning.","body":"Our coldest tub yet, now in matte black.","cta":"Learn More","link_url":"https://plunge.example/black","format":"IMAGE","image_urls":["https://scontent.xx.fbcdn.net/ads/plunge-black.jpg"],"video_urls":[],"thumbnail_urls":[]},"reach":{"impressions":null,"spend":null,"currency":null,"audience":null},"kind":"commercial","media_type":"image","countries":null,"variant_count":null,"days_running":42,"winner_score":{"score":54,"confidence":"low","inputs":{"days_running":42,"variants_added":0,"snapshots":1,"advertiser_ads":14},"reason":"single_snapshot"},"removed_from_library":true,"removed_at":"2026-09-20T08:00:00.000Z"},"as_of":"2026-07-14T09:12:58.104Z"}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":3,"cached":true,"priced_per":"ad_delivered"}}}}}},"202":{"$ref":"#/components/responses/GetMetaAd202"},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"$ref":"#/components/responses/Problem402_2"},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"$ref":"#/components/responses/Problem502_7"},"503":{"$ref":"#/components/responses/Problem503_6"}},"x-price":{"credits":3,"unit":"call","max_credits":23}}},"/ads/tiktok/{ad_id}":{"get":{"operationId":"getTikTokAd","summary":"Get a TikTok Ad","description":"One TikTok Ad by its ad library id: a search result plus landing page, CTA, objective, advertiser id, its TikTok account (`advertiser_account`) and `targeting`. EU/EEA, Swiss, UK and Turkish Ads only.\n\n- **Targeting:** countries, ages, genders, impressions per country by age and gender.\n- **Fallback:** when the library cannot answer, Creative Center may. `targeting` is then null and `performance` has CTR, likes, comments and shares.\n- **Nulls:** unpublished fields are null, never zero.\n- **Storage:** stored with archived media. Served from our copy within 6 hours, or with `removed_from_library: true` once dropped, at the same price. `as_of` says when it was last observed.\n- **Analysis:** carries `intelligence` when a Tracker analysed it.\n- **Errors:** unknown id is 404 `not_found` and an unreachable library is `source_unavailable`. Neither is charged.\n\n**Price:** 3 credits.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=getTikTokAd) (no API Key needed).","tags":["Ads"],"parameters":[{"name":"ad_id","in":"path","required":true,"description":"The TikTok ad library id: the number in `library.tiktok.com/ads/detail/?ad_id=...`, or an `id` from a TikTok `POST /ads/search`.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Wait"},{"$ref":"#/components/parameters/MaxCredits"},{"$ref":"#/components/parameters/Estimate_2"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"The Run finished inside the wait budget: `{ run, result }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"type":"object","properties":{"ad":{"allOf":[{"$ref":"#/components/schemas/Ad"},{"type":"object","properties":{"removed_from_library":{"type":"boolean","description":"True when the library's own detail read answered not found for the Ad; it is then served from our stored copy, at the same price."},"removed_at":{"type":["string","null"],"description":"When this API first found the Ad gone from the library."}},"required":["removed_from_library","removed_at"]}]},"as_of":{"type":["string","null"],"description":"When the Ad was last observed in the library. Null for a Creative Center answer, which is not stored."}},"required":["ad","as_of"]}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"ad_lookup","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":{"ad":{"library":"tiktok","id":"1879578150853938","url":"https://library.tiktok.com/ads/detail/?ad_id=1879578150853938","advertiser":{"id":"6876453864464188162","name":"Northpeak Outdoor GmbH"},"is_active":null,"first_shown":"2026-10-20T00:00:00.000Z","last_shown":"2026-10-22T00:00:00.000Z","placements":[],"creative":{"title":"New winter gear, in store now.","body":null,"cta":"Learn more","link_url":"https://www.example.com/winter","format":null,"image_urls":[],"video_urls":["https://library.tiktok.com/api/v1/cdn/1792740803/video/..."],"thumbnail_urls":["https://p16-common-sign.tiktokcdn.com/ad-site-i18n-sg/..."]},"reach":{"impressions":"100K-200K","spend":null,"currency":null,"audience":"100K-200K"},"countries":["DE"],"advertiser_account":{"username":"northpeak","display_name":"Northpeak","followers":"1.2M","verified":true,"url":"https://www.tiktok.com/@northpeak"},"targeting":{"countries":["DE"],"impressions":"100K-200K","audience_size":"15.2M-18.6M","ages":["18-24","25-34","35-44"],"genders":["female","male","unknown"],"by_country":[{"country":"DE","impressions":"124K","breakdown":[{"age":"18-24","gender":"female","impressions":"34K"}]}]},"performance":null,"objective":"Traffic","archived":true,"removed_from_library":false,"removed_at":null},"as_of":"2026-10-23T09:12:58.104Z"}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":3,"cached":false}}}}}},"202":{"$ref":"#/components/responses/GetMetaAd202"},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"$ref":"#/components/responses/Problem402_2"},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"$ref":"#/components/responses/Problem502_7"},"503":{"$ref":"#/components/responses/Problem503_6"}},"x-price":{"credits":3,"unit":"call","max_credits":3}}},"/ads/meta/{library_id}/intelligence":{"get":{"operationId":"getMetaAdIntelligence","summary":"Get a Meta Ad's analysis","description":"The Ad's latest stored analysis, as an earlier `analyze` computed it. Nothing is computed here: an Ad with none yet is `not_found`; ask for it with `analyze`. Shared across Customers.\n\n**Price:** Free.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=getMetaAdIntelligence) (no API Key needed).","tags":["Ads"],"parameters":[{"name":"library_id","in":"path","required":true,"description":"The Meta Ad Library id.","schema":{"type":"string"}}],"responses":{"200":{"description":"`{ library_id, intelligence }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"library_id":{"type":"string"},"intelligence":{"anyOf":[{"type":"object","properties":{"version":{"type":"integer"},"model":{"type":"string"},"computed_at":{"type":"string"},"source":{"type":"string"},"content":{"type":"object","properties":{"summary":{"type":"string"},"niche":{"type":"string"},"languages":{"type":"array","items":{"type":"string"}},"content_styles":{"type":"array","items":{"type":"string"}},"keywords":{"type":"array","items":{"type":"object","properties":{"keyword":{"type":"string"},"category":{"type":"string"},"sentiment":{"type":"number"}},"required":["keyword","category","sentiment"]}},"transcript":{"type":["string","null"]},"transcript_segments":{"type":["array","null"],"items":{"type":"object","properties":{"start_ms":{"type":"integer"},"end_ms":{"type":"integer"},"text":{"type":"string"}},"required":["start_ms","end_ms","text"]},"description":"Timed transcript lines (ms from the start), to see when the hook lands. From YouTube captions or TikTok's caption track; null on Instagram, Facebook, with no timed captions, and on older analyses."}},"required":["summary","niche","languages","content_styles","keywords","transcript","transcript_segments"]},"hook":{"type":"object","properties":{"opening_line":{"type":["string","null"]},"type":{"type":"string"},"visual_hook":{"type":["string","null"]},"rationale":{"type":["string","null"]}},"required":["opening_line","type","visual_hook","rationale"]},"persuasion":{"type":"object","properties":{"call_to_action":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":["string","null"]}},"required":["type","text"]},"sponsored":{"type":"boolean","description":"Whether the video is plausibly a paid promotion. Always true when the Platform labels it an ad or a paid partnership."},"sponsorship_signals":{"type":"array","items":{"type":"string"}},"brands_and_products":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"kind":{"type":"string"},"prominence":{"type":"string"}},"required":["name","kind","prominence"]}},"trend_references":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"kind":{"type":"string"}},"required":["name","kind"]}}},"required":["call_to_action","sponsored","sponsorship_signals","brands_and_products","trend_references"]},"tone":{"type":"object","properties":{"sentiment_label":{"type":"string"},"sentiment_score":{"type":"number"},"primary_emotion":{"type":"string"},"emotion_intensity":{"type":["number","null"]},"emotion_rationale":{"type":["string","null"]},"speaking_style":{"type":"string"},"speaking_style_notes":{"type":["string","null"]}},"required":["sentiment_label","sentiment_score","primary_emotion","emotion_intensity","emotion_rationale","speaking_style","speaking_style_notes"]},"visual":{"type":"object","properties":{"format":{"type":"string"},"setting":{"type":"string"},"face_visibility":{"type":"string"},"on_screen_text":{"type":"array","items":{"type":"string"}},"has_on_screen_captions":{"type":"boolean"},"camera_notes":{"type":["string","null"]},"lighting_notes":{"type":["string","null"]},"elements":{}},"required":["format","setting","face_visibility","on_screen_text","has_on_screen_captions","camera_notes","lighting_notes"]},"safety":{"type":"object","properties":{"brand_safety_tier":{"type":"string"},"reasons":{"type":"array","items":{"type":"string"}},"notes":{"type":["string","null"]}},"required":["brand_safety_tier","reasons","notes"]},"pipeline":{"type":"string","enum":["video"]}},"required":["version","model","computed_at","source","content","hook","persuasion","tone","visual","safety","pipeline"],"description":"Video Ads: the full video analysis, read from the archived video with the ad copy as context."},{"type":"object","properties":{"pipeline":{"type":"string","enum":["image"]},"version":{"type":"integer"},"model":{"type":"string"},"computed_at":{"type":"string"},"images_analyzed":{"type":"integer"},"summary":{"type":"string"},"copy":{"type":"object","properties":{"angle":{"type":"string"},"rationale":{"type":["string","null"]},"headline":{"type":["string","null"]}},"required":["angle","rationale","headline"]},"offer":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":["string","null"]}},"required":["type","text"]},"call_to_action":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":["string","null"]}},"required":["type","text"]},"visual":{"type":"object","properties":{"format":{"type":"string"},"on_image_text":{"type":"array","items":{"type":"string"}}},"required":["format","on_image_text"]},"topics":{"type":"array","items":{"type":"string"}},"tone":{"type":"object","properties":{"sentiment_label":{"type":"string"},"sentiment_score":{"type":"number"}},"required":["sentiment_label","sentiment_score"]}},"required":["pipeline","version","model","computed_at","images_analyzed","summary","copy","offer","call_to_action","visual","topics","tone"],"description":"Image and carousel Ads: the analysis an image can carry, read from the archived images with the ad copy as context."}],"description":"Ad analysis, versioned and computed once per Ad and version. `pipeline` says which set it is."}},"required":["library_id","intelligence"]},"example":{"library_id":"2233445566778899","intelligence":{"pipeline":"image","version":1,"model":"gemini-3.5-flash-lite","computed_at":"2026-09-21T10:02:11.000Z","images_analyzed":1,"summary":"A matte black cold plunge tub shot in a bright bathroom, sold on a daily three-minute routine.","copy":{"angle":"TRANSFORMATION","rationale":"The headline frames the tub as a daily ritual and the copy as an upgrade.","headline":"Three minutes. Every morning."},"offer":{"type":"NONE","text":null},"call_to_action":{"type":"VISIT_SITE","text":"Learn More"},"visual":{"format":"PRODUCT_SHOT","on_image_text":["Three minutes. Every morning."]},"topics":["cold plunge","morning routine","home wellness"],"tone":{"sentiment_label":"POSITIVE","sentiment_score":0.6}}}}}},"401":{"$ref":"#/components/responses/Problem401"},"404":{"description":"`not_found`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/not_found","title":"Not found","status":404,"code":"not_found","detail":"This Ad has no analysis yet. Request it with `analyze: true`.","retryable":false,"action":"Check the id or handle; list your resources to find the right one."}}}}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/ads/meta/{library_id}/snapshots":{"get":{"operationId":"listMetaAdSnapshots","summary":"Read a Meta Ad's history","description":"Every observation of the Ad, newest first: running state, placements, countries, variant count, and disclosed spend and reach. Snapshots are shared across Customers and kept forever. `not_found` until the Ad has been looked up or returned by a search.\n\n**Price:** Free.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=listMetaAdSnapshots) (no API Key needed).","tags":["Ads"],"parameters":[{"name":"library_id","in":"path","required":true,"description":"The Meta Ad Library id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit_5"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"`{ items, next_cursor }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string"},"metrics":{"description":"Meta: running, placements, countries, variant_count, and spend, impressions and reach ranges with currency where disclosed. TikTok: running, last_shown, audience, countries, targeting."},"source":{"type":"string"}},"required":["at","source"]}}},"required":["items"]}]},"example":{"items":[{"at":"2026-07-14T09:12:58.104Z","metrics":{"running":false,"placements":["INSTAGRAM"],"countries":null,"variant_count":null,"spend":null,"impressions":null,"reach":null,"currency":null},"source":"vendor"}],"next_cursor":null}}}},"400":{"$ref":"#/components/responses/Problem400_6"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/ads/tiktok/{ad_id}/snapshots":{"get":{"operationId":"listTikTokAdSnapshots","summary":"List a TikTok Ad's snapshots","description":"Every observation of the Ad, newest first. `not_found` until the Ad has been looked up or searched.\n\n**Price:** Free.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=listTikTokAdSnapshots) (no API Key needed).","tags":["Ads"],"parameters":[{"name":"ad_id","in":"path","required":true,"description":"The TikTok ad library id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit_5"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"`{ items, next_cursor }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string"},"metrics":{"description":"Meta: running, placements, countries, variant_count, and spend, impressions and reach ranges with currency where disclosed. TikTok: running, last_shown, audience, countries, targeting."},"source":{"type":"string"}},"required":["at","source"]}}},"required":["items"]}]},"example":{"items":[{"at":"2026-10-23T09:12:58.104Z","metrics":{"running":true,"last_shown":"2026-10-22T00:00:00.000Z","audience":"100K-200K","countries":null},"source":"vendor"}],"next_cursor":null}}}},"400":{"$ref":"#/components/responses/Problem400_6"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/advertisers/{page_id}":{"get":{"operationId":"getAdvertiser","summary":"Look up an advertiser profile","description":"One advertiser's profile, from the Meta library or, with `library=tiktok`, the TikTok one.\n\n**Meta**\n\n- **Advertiser:** a Facebook Page that runs Ads.\n- **Profile:** name, Page URL, running and total Ad counts as last observed, and `last_observed_at`.\n- **Linked accounts:** its linked Instagram account and Creator, only when Meta shows the link, never guessed from the name.\n- **Fresh lookup:** reads and stores every Ad (every status and country) with a Snapshot. Reading to the end is a complete observation, which stamps the counts.\n- **Stored results:** for 6 hours after that, the profile and any `advertiser` search on it are served from storage, saying `cached` and `as_of`.\n- **Large advertisers:** one with more Ads than a lookup reads keeps its last complete counts (and Meta's own total when reported).\n- **No Ads in the library:** 404 `not_found`, free.\n\n**TikTok**\n\n- **Profile:** TikTok account, registry location, paid by and counts (running: active, shown in the past 3 days). Its Ads are stored and archived.\n- **Complete observation:** unless the library broke it off part-way.\n- **Truncated reads:** a `truncated` read counts, serving the profile for 6 hours. It is normal for a busy advertiser, because the library's paging skips Ads shown the same day.\n- **Unobserved id:** a bare TikTok id we have not observed yet is 404 `not_found`, free, because the library needs the exact name beside it. Pass its library URL or name.\n\n**Price:** 15 credits, the same when served within 6 hours of a complete observation.\n\n[Run it in the Playground](https://www.shortsintel.com/console/playground?op=getAdvertiser) (no API Key needed).","tags":["Ads"],"parameters":[{"name":"page_id","in":"path","required":true,"description":"The numeric Facebook Page id (from a name or Page URL, search with `advertiser` first). TikTok: an advertiser id, library URL or name; several matches 409 `advertiser_ambiguous`, none 404.","schema":{"type":"string"}},{"name":"library","in":"query","required":false,"description":"`meta` (default) or `tiktok`.","schema":{"type":"string","enum":["meta","tiktok"],"default":"meta"}},{"$ref":"#/components/parameters/Wait"},{"$ref":"#/components/parameters/MaxCredits"},{"$ref":"#/components/parameters/Estimate_2"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"The Run finished inside the wait budget: `{ run, result }`. With `estimate=true`, `{ estimate_credits, cached }` instead.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"anyOf":[{"$ref":"#/components/schemas/Advertiser"},{"type":"object","properties":{"name":{"type":["string","null"]},"running_ad_count":{"type":["integer","null"],"description":"Running Ads as last observed; null until a complete observation."},"total_ad_count":{"type":["integer","null"],"description":"Every Ad the Page has in the library, running or stopped, as last observed."},"last_observed_at":{"type":["string","null"],"description":"When every Ad of the advertiser was last read in one go."},"first_seen_at":{"type":"string"},"cached":{"type":"boolean","description":"True when served from a complete observation under 6 hours old."},"as_of":{"type":"string","description":"When this profile was observed."},"library":{"type":"string","enum":["tiktok"]},"advertiser_id":{"type":"string","description":"The library's advertiser id."},"url":{"type":["string","null"]},"tiktok_account":{"type":["object","null"],"properties":{"username":{"type":"string"},"display_name":{"type":["string","null"]},"followers":{"type":["string","null"],"description":"As TikTok shows it (`9.3M`), not a number."},"verified":{"type":["boolean","null"]},"url":{"type":["string","null"]}},"required":["username","display_name","followers","verified","url"]},"creator":{"type":["object","null"],"properties":{"id":{"type":"string"},"platform":{"type":"string","enum":["tiktok"]},"handle":{"type":["string","null"]},"name":{"type":"string"}},"required":["id","platform","handle","name"]},"registry_location":{"type":["string","null"]},"paid_by":{"type":["string","null"]}},"required":["name","running_ad_count","total_ad_count","last_observed_at","first_seen_at","cached","as_of","library","advertiser_id","url","tiktok_account","creator","registry_location","paid_by"]}]}},"required":["result"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"advertiser_lookup","status":"completed","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":15,"list_price_credits":15,"cached":false},"result":{"page_id":"100064000000001","name":"Plunge","page_url":"https://www.facebook.com/plunge/","instagram":{"handle":"plunge","url":"https://www.instagram.com/plunge/"},"creator":{"id":"17841400000000001","platform":"instagram","handle":"plunge","name":"Plunge"},"running_ad_count":14,"total_ad_count":61,"last_observed_at":"2026-10-12T08:00:00.000Z","first_seen_at":"2026-09-02T10:15:00.000Z","cached":false,"as_of":"2026-10-12T08:00:00.000Z"}}},"estimate":{"summary":"With `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":15,"cached":false}}}}}},"202":{"description":"Still running: `{ run }`. Poll `GET /v1/runs/{id}`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningEnvelope"},"example":{"run":{"id":"run_8f2c1ad04b","kind":"advertiser_lookup","status":"running","created_at":"2026-09-08T09:14:02.418Z","completed_at":null,"charge_credits":0,"list_price_credits":0,"cached":false},"poll_url":"https://www.shortsintel.com/v1/runs/run_8f2c1ad04b"}}}},"400":{"$ref":"#/components/responses/Problem400"},"401":{"$ref":"#/components/responses/Problem401"},"402":{"description":"`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`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/insufficient_balance","title":"Insufficient balance","status":402,"code":"insufficient_balance","detail":"Your balance is 0 Credits and this operation needs 15 Credits. Nothing was charged.","retryable":false,"action":"Tell the Customer to top up the Balance, then repeat the same request.","balance_credits":0,"required_credits":15}}}},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429"},"502":{"description":"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.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Retry with a backoff; nothing was charged.","run":{"id":"run_8f2c1ad04b","kind":"advertiser_lookup","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":{"description":"`source_unavailable`: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; `endpoints` names the source. Wait `retry_after_seconds` (also sent as `Retry-After`) and retry rather than treating it as empty.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Wait `retry_after_seconds`, then retry; do not treat this as an empty result.","endpoints":["tiktok/video"],"run":{"id":"run_8f2c1ad04b","kind":"advertiser_lookup","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},"retry_after_seconds":60}}}}},"x-price":{"credits":15,"unit":"call","max_credits":15}}},"/trackers":{"post":{"operationId":"createTracker","summary":"Start tracking a target","description":"Creates a daily creator, hashtag, sound, keyword or advertiser Tracker and runs its first cycle now, so you have a baseline at once. It then joins the daily schedule.\n\n- **Duplicates:** one Tracker per target. Creating it again returns 200 with the existing Tracker and `created: false`, uncharged and not a conflict.\n- **Deleted Trackers:** final. Tracking the target again creates a new one.\n- **Collections:** `collection_ids` also puts the Tracker in those Collections, checked before anything is fetched or charged.\n\n**Meta advertiser cycles**\n\n- **Reads:** the Ads the Advertiser runs or ran, up to 20 library pages (`truncated: true` past that), stored with Snapshots and archived media.\n- **Change Report:** new Ads, stopped Ads, Ads whose variant count grew, and new countries or placements.\n\n**TikTok advertiser cycles**\n\n- **Regions:** EU/EEA, Swiss, UK and Turkish Ads only.\n- **Reads:** up to 25 library pages: Ads shown in the past 3 days and Ads ended since the last cycle, stored with Snapshots and archived media, and each new Ad's details once.\n- **Change Report:** new Ads (with `targeting`, `landing_page`, `cta`), stopped Ads and `reach_growth` (audience bucket moved up), with `truncated` when the library's paging left Ads unread.\n- **Stopped Ads:** ended, or not shown for 3 days, and never for a missed read. After a `truncated` read a detail read confirms the last day shown.\n- **Broken-off reads:** a read the library breaks off is `partial`, charged 3 credits per page read up to the cycle.\n- **No library Ads:** the advertiser answers `coverage: \"library_regions_only\"`.\n\n**Hashtag cycles**\n\n- **Reads:** one page of the tag's videos, as no platform reports a tag's totals. Writes a Snapshot of sample stats and the top 10 video ids.\n- **Change Report:** fires when the sample's median views move 25% or more, or a video enters the top 10.\n\n**Sound cycles (TikTok)**\n\n- **Reads:** the sound (its video count is the platform's own) and one page of its videos. Writes a Snapshot of the video count, sample stats and top 10 video ids.\n- **Change Report:** fires when the video count rises 10% or more, or the sample's most viewed video changes.\n\n**Price:** The first cycle is charged on create: 6 credits for a creator, 3 credits for a hashtag, 6 credits for a sound, 3 credits for a keyword, 30 credits for an advertiser, plus 20 credits per new video when `intelligence` is on (per new Ad, on its own Run, for an advertiser). A TikTok advertiser cycle includes 10 new Ads' detail reads, then 3 credits each; the estimate and Balance check quote every running Ad as new, at most 300, the most a cycle charges for. A first (baseline) cycle reports nothing but reads up to 10 Ads' details, included, so lookups and the first Change Report carry targeting. Each later daily cycle costs the same; an already tracked target costs nothing.","tags":["Trackers"],"parameters":[{"$ref":"#/components/parameters/Estimate_3"},{"$ref":"#/components/parameters/MaxCredits"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","enum":["creator","hashtag","sound","advertiser","keyword"],"description":"`creator`, `hashtag`, `sound`, `keyword` (a search phrase on one Platform) or `advertiser` (a Meta or TikTok Advertiser). `video` is deprecated and refused with 400 `kind_deprecated`."},"platform":{"type":"string","enum":["tiktok","instagram","youtube","meta"],"description":"Required for `creator` (`tiktok`, `instagram` or `facebook`; `youtube` is refused with 400 `unsupported_platform`), `hashtag` (`tiktok` or `instagram`), `sound` (`tiktok`) and `keyword` (`tiktok`, `instagram`, `youtube` or `facebook`). For `advertiser` omit it or pass `meta` (the Meta Ad Library), or pass `tiktok` (the TikTok ad library)."},"target":{"type":"string","minLength":1,"description":"`creator`: the handle. `hashtag`: the tag, with or without `#` (stored lowercased). `sound`: TikTok's sound id (the number at the end of a `tiktok.com/music/` URL) or that URL. `keyword`: the search phrase, at most 100 characters (trimmed, spaces collapsed and lowercased, so `Skin  Care` and `skin care` are one keyword). `advertiser`: the Facebook Page id, or a Page URL carrying it; a name works when only one Advertiser carries it, else 409 `advertiser_ambiguous` with candidates, free. With `platform: tiktok`: the library's advertiser id, a library.tiktok.com URL carrying it, or a name with exactly one exact match (several: 409 with candidates; none: 404; both free). The library reads an id only together with the advertiser's exact name, so a bare id we have not observed yet is 404 `not_found`, free: pass its library URL (it carries `adv_name`) or its name."},"intelligence":{"type":"boolean","description":"Analyse each new video (or new Ad) the cycle finds. On `advertiser` Trackers each new Ad is analysed and charged, whether computed or already stored; one whose analysis fails is not charged."},"focus":{"type":["object","null"],"properties":{"text":{"type":"string","description":"Which Videos are relevant to you, in plain language, exclusions included, e.g. `Apple Inc. and its products (iPhone, Mac, AirPods, iOS). Not the fruit, recipes or orchards.` 1 to 1000 characters."},"must_mention":{"type":"array","items":{"type":"string"},"description":"Up to 20 terms of at most 60 characters. A Video that has captions or an analysis transcript, and whose caption, hashtags, captions and transcript name none of them (any case, whole term), is off focus without a model call; one with neither goes to the model, so a term said aloud still counts; one naming any is still judged against `text`."}},"required":["text"],"additionalProperties":false,"description":"`creator`, `hashtag`, `sound` and `keyword` only: each cycle judges the Sample's Videos (a Creator's new Videos, and any of its newest 20 not yet judged under this Focus) in focus, off focus or unjudged, and `GET /v1/trackers/{id}` hides the off-focus ones. A Video's caption, hashtags and any analysis transcript count, so spoken mentions do too. Sample stats and Snapshots are unchanged. +3 credits per Video the model judges, +1 credit per Video `must_mention` rules out, nothing for a Video already judged under the same Focus (shared across your Trackers) or one that could not be judged; `estimate` adds a full Sample (a Creator: its newest 20 Videos) judged. On a target you already track, a different Focus is not applied: the Tracker comes back unchanged and uncharged with `focus_applied: false` and a `focus_note` pointing to `PUT /v1/trackers/{id}/focus`; leaving `focus` out never clears one. Another kind is refused with 422 `focus_unsupported_kind`; a malformed Focus with 400 `invalid_request`."},"collection_ids":{"type":"array","items":{"type":"string"},"description":"Also put the Tracker in these Collections, even when it already exists. Checked before anything is charged."},"estimate":{"type":"boolean","description":"As in the query."}},"required":["kind","target"],"additionalProperties":false}}}},"responses":{"200":{"description":"`{ tracker, created: false, run: null, change_report: null, collections }` — you were already tracking that target. Not charged, and left unchanged: a different `focus` adds `focus_applied: false` and `focus_note` (set it with `PUT /v1/trackers/{id}/focus`). With `estimate=true`, `{ estimate_credits, cached, already_tracking, tracker_id, per_cycle }` instead (the same `focus_applied`/`focus_note` when it applies).","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"tracker":{"$ref":"#/components/schemas/Tracker"},"created":{"type":"boolean","description":"False when you already tracked this target: the existing Tracker, and nothing charged."},"run":{"description":"The first cycle, run on create. Null when `created` is false.","anyOf":[{"$ref":"#/components/schemas/Run"},{"type":"null"}]},"change_report":{"description":"The first cycle's report, null when quiet or not `created`.","anyOf":[{"$ref":"#/components/schemas/ChangeReport"},{"type":"null"}]},"collections":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"description":"Every Collection the Tracker is now in."},"collection_errors":{"type":"array","items":{"type":"object","properties":{"collection_id":{"type":"string"},"error":{"$ref":"#/components/schemas/Problem"}},"required":["collection_id","error"]},"description":"Only when a Collection in `collection_ids` was deleted while the first cycle ran: the Tracker stands, paid for, outside it."},"intelligence_run":{"description":"Advertiser Trackers with `intelligence: true`: the Run analysing the first cycle's new Ads in the background, charged per Ad computed. Null when no Ad needed analysis. Only when `created`.","anyOf":[{"$ref":"#/components/schemas/Run"},{"type":"null"}]},"coverage":{"type":"string","enum":["library_regions_only","partial"],"description":"`library_regions_only` when a TikTok advertiser's first cycle found no Ads in the library (with `coverage_note`); `partial` for a Keyword on Instagram or Facebook, whose search is a best-effort index. Absent otherwise."},"coverage_note":{"type":"string","description":"The regions the TikTok ad library covers, beside `coverage`."},"focus_applied":{"type":"boolean","enum":[false],"description":"Only when `created` is false and `focus` differs from the Tracker's: the Focus was not applied and nothing was charged. Set it with `PUT /v1/trackers/{id}/focus`."},"focus_note":{"type":"string","description":"Beside `focus_applied`: how to set the Focus on this Tracker."}},"required":["tracker","created","run","change_report","collections"]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"tracker":{"id":"trk_4b1e90c7aa","kind":"creator","platform":"tiktok","target":"someone","intelligence":true,"state":"active","last_cycle_at":"2026-09-08T04:00:11.402Z","last_run_id":"run_c07a41bb92","created_at":"2026-09-01T11:20:03.118Z","updated_at":"2026-09-08T04:00:11.402Z"},"created":false,"run":null,"change_report":null,"collections":[]}},"estimate":{"summary":"With `estimate=true`: the price of the first cycle, nothing created or charged.","value":{"estimate_credits":6,"cached":false,"already_tracking":false,"tracker_id":null,"per_cycle":true}}}}}},"201":{"description":"`{ tracker, created: true, run, change_report, intelligence_run, collections }` — newly created, with its first (charged) cycle. `intelligence_run` is the Run analysing an advertiser's new Ads, or null. If a Collection in `collection_ids` was deleted while the first cycle ran, the paid Tracker still stands and `collection_errors` lists it. `coverage` and `coverage_note` when a TikTok advertiser has no Ads in the library; `coverage: \"partial\"` for a Keyword on Instagram or Facebook, whose search is a best-effort index.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"tracker":{"$ref":"#/components/schemas/Tracker"},"created":{"type":"boolean","description":"False when you already tracked this target: the existing Tracker, and nothing charged."},"run":{"description":"The first cycle, run on create. Null when `created` is false.","anyOf":[{"$ref":"#/components/schemas/Run"},{"type":"null"}]},"change_report":{"description":"The first cycle's report, null when quiet or not `created`.","anyOf":[{"$ref":"#/components/schemas/ChangeReport"},{"type":"null"}]},"collections":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"description":"Every Collection the Tracker is now in."},"collection_errors":{"type":"array","items":{"type":"object","properties":{"collection_id":{"type":"string"},"error":{"$ref":"#/components/schemas/Problem"}},"required":["collection_id","error"]},"description":"Only when a Collection in `collection_ids` was deleted while the first cycle ran: the Tracker stands, paid for, outside it."},"intelligence_run":{"description":"Advertiser Trackers with `intelligence: true`: the Run analysing the first cycle's new Ads in the background, charged per Ad computed. Null when no Ad needed analysis. Only when `created`.","anyOf":[{"$ref":"#/components/schemas/Run"},{"type":"null"}]},"coverage":{"type":"string","enum":["library_regions_only","partial"],"description":"`library_regions_only` when a TikTok advertiser's first cycle found no Ads in the library (with `coverage_note`); `partial` for a Keyword on Instagram or Facebook, whose search is a best-effort index. Absent otherwise."},"coverage_note":{"type":"string","description":"The regions the TikTok ad library covers, beside `coverage`."},"focus_applied":{"type":"boolean","enum":[false],"description":"Only when `created` is false and `focus` differs from the Tracker's: the Focus was not applied and nothing was charged. Set it with `PUT /v1/trackers/{id}/focus`."},"focus_note":{"type":"string","description":"Beside `focus_applied`: how to set the Focus on this Tracker."}},"required":["tracker","created","run","change_report","collections"]},"example":{"tracker":{"id":"trk_4b1e90c7aa","kind":"creator","platform":"tiktok","target":"someone","intelligence":true,"state":"active","last_cycle_at":"2026-09-08T04:00:11.402Z","last_run_id":"run_c07a41bb92","created_at":"2026-09-01T11:20:03.118Z","updated_at":"2026-09-08T04:00:11.402Z"},"created":true,"run":{"id":"run_8f2c1ad04b","kind":"tracker_cycle","status":"completed","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":50,"list_price_credits":50,"cached":false},"change_report":null,"intelligence_run":null,"collections":[{"id":"col_7d20e1b5c4","name":"Competitors"}]}}}},"400":{"description":"`invalid_request` — a malformed body. Or `unsupported_platform`: an unknown platform, or a creator on YouTube (creator Trackers cycle on TikTok, Instagram and Facebook). Nothing is created or charged. Or: `kind_deprecated` — `video` is deprecated: no new Video Trackers. Track the Creator, a Hashtag or a Sound instead. Nothing is created or charged.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"unsupported_platform":{"summary":"`invalid_request` — a malformed body. Or `unsupported_platform`: an unknown platform, or a creator on YouTube (creator Trackers cycle on TikTok, Instagram and Facebook). Nothing is created or charged.","value":{"type":"https://www.shortsintel.com/docs/reference/errors/unsupported_platform","title":"Unsupported platform","status":400,"code":"unsupported_platform","detail":"Tracking a creator on youtube is not available yet. Creator Trackers are supported on: tiktok, instagram, facebook.","retryable":false,"action":"Use a platform this operation lists as supported."}},"kind_deprecated":{"summary":"`kind_deprecated` — `video` is deprecated: no new Video Trackers. Track the Creator, a Hashtag or a Sound instead. Nothing is created or charged.","value":{"type":"https://www.shortsintel.com/docs/reference/errors/kind_deprecated","title":"Kind deprecated","status":400,"code":"kind_deprecated","detail":"Video Trackers and Collections can no longer be created. Track the Creator, a Hashtag or a Sound instead: their cycles re-snapshot the Videos they find every day.","retryable":false,"action":"Track the Creator, a Hashtag or a Sound instead of a Video.","supported_kinds":["creator","hashtag","sound","advertiser","keyword"]}}}}}},"401":{"$ref":"#/components/responses/Problem401"},"402":{"description":"`insufficient_balance` — the first cycle is not covered. Nothing is created.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/insufficient_balance","title":"Insufficient balance","status":402,"code":"insufficient_balance","detail":"Your balance is 0 Credits and this operation needs 6 Credits. Nothing was charged.","retryable":false,"action":"Tell the Customer to top up the Balance, then repeat the same request.","balance_credits":0,"required_credits":6}}}},"404":{"description":"`not_found`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/not_found","title":"Not found","status":404,"code":"not_found","detail":"A `collection_ids` entry is not one of this Customer's Collections, or there is no such creator, or no such Advertiser (no Ads in the Meta Ad Library under that Page id or name). Nothing is created or charged.","retryable":false,"action":"Check the id or handle; list your resources to find the right one."}}}},"409":{"description":"`tracker_limit_exceeded` at 100 active Trackers. Paused Trackers do not count. Or: `advertiser_ambiguous` with `candidates` (each `{ page_id, name, page_url, instagram, ad_count }`) when an advertiser name matches several Pages (TikTok: `{ advertiser_id, name, url }`). Nothing is created or charged; ask again with the Page id (TikTok: a candidate's `url`). Or: `collection_kind_mismatch` — the Tracker is not of the Collection's kind.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"tracker_limit_exceeded":{"summary":"`tracker_limit_exceeded` at 100 active Trackers. Paused Trackers do not count.","value":{"type":"https://www.shortsintel.com/docs/reference/errors/tracker_limit_exceeded","title":"Tracker limit exceeded","status":409,"code":"tracker_limit_exceeded","detail":"You already have 100 active Trackers. Pause one before starting another.","retryable":false,"action":"Pause or delete a Tracker, then retry.","limit":100,"active":100}},"advertiser_ambiguous":{"summary":"`advertiser_ambiguous` with `candidates` (each `{ page_id, name, page_url, instagram, ad_count }`) when an advertiser name matches several Pages (TikTok: `{ advertiser_id, name, url }`). Nothing is created or charged; ask again with the Page id (TikTok: a candidate's `url`).","value":{"type":"https://www.shortsintel.com/docs/reference/errors/advertiser_ambiguous","title":"Advertiser ambiguous","status":409,"code":"advertiser_ambiguous","detail":"Several Facebook Pages are called Acme. Pass the Page id of the one you mean.","retryable":false,"action":"Ask again with one of `candidates`' `page_id` or `url`."}},"collection_kind_mismatch":{"summary":"`collection_kind_mismatch` — the Tracker is not of the Collection's kind.","value":{"type":"https://www.shortsintel.com/docs/reference/errors/collection_kind_mismatch","title":"Collection kind mismatch","status":409,"code":"collection_kind_mismatch","detail":"\"Competitors\" is a Collection of creator Trackers and cannot hold a video.","retryable":false,"action":"Add this target to a Collection of its own kind.","collection_kind":"creator","kind":"video"}}}}}},"429":{"$ref":"#/components/responses/Problem429_2"}},"x-price":{"credits":6,"unit":"cycle","max_credits":null}},"get":{"operationId":"listTrackers","summary":"List your trackers","description":"The Customer's Trackers, newest first.\n\n**Price:** Free.","tags":["Trackers"],"parameters":[{"$ref":"#/components/parameters/Limit_5"},{"$ref":"#/components/parameters/Cursor"},{"name":"state","in":"query","required":false,"description":"`active` or `paused`.","schema":{"type":"string","enum":["active","paused"]}},{"name":"kind","in":"query","required":false,"description":"`creator`, `hashtag`, `sound` or `advertiser`; `video` (deprecated) lists any remaining Video Trackers.","schema":{"type":"string","enum":["creator","hashtag","sound","advertiser","keyword","video"]}}],"responses":{"200":{"description":"`{ items, next_cursor }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Tracker"}}},"required":["items"]}]},"example":{"items":[{"id":"trk_4b1e90c7aa","kind":"creator","platform":"tiktok","target":"someone","intelligence":true,"state":"active","last_cycle_at":"2026-09-08T04:00:11.402Z","last_run_id":"run_c07a41bb92","created_at":"2026-09-01T11:20:03.118Z","updated_at":"2026-09-08T04:00:11.402Z"}],"next_cursor":null}}}},"400":{"$ref":"#/components/responses/Problem400_6"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/trackers/{id}":{"get":{"operationId":"getTracker","summary":"Read one tracker","description":"One Tracker. Another Customer's id is a 404, never a 403.\n\n- **TikTok advertiser:** when its latest observation found no Ads in the library it carries `coverage: \"library_regions_only\"` and `coverage_note`. The library holds only EU/EEA, Swiss, UK and Turkish Ads.\n- **Keyword on Instagram or Facebook:** carries `coverage: \"partial\"`, as their search is a best-effort index.\n\n**Price:** Free.","tags":["Trackers"],"parameters":[{"name":"id","in":"path","required":true,"description":"Tracker id.","schema":{"type":"string"}},{"name":"include_off_focus","in":"query","required":false,"description":"A Tracker with a Focus: `true` returns every sampled Video in `sample.videos` (a Creator's in `recent_videos.videos`), each with `focus: { verdict, reason }`.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"`{ tracker }`, plus `sample` on a Tracker with a Focus: its latest Sample with off-focus Videos hidden, `off_focus_count`, and in-focus counts and stats beside the full-Sample stats. A Creator Tracker with a Focus has `recent_videos` instead: its newest 20 Videos with off-focus ones hidden, `off_focus_count`, \"N of M in focus\" and in-focus stats.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"tracker":{"$ref":"#/components/schemas/Tracker"},"sample":{"type":"object","properties":{"at":{"type":"string","description":"When the latest Sample's Snapshot was taken."},"stats":{"type":"object","properties":{"sampled_videos":{"type":"integer"},"views_total":{"type":"number"},"views_median":{"type":["number","null"]},"views_max":{"type":["number","null"]},"likes_total":{"type":"number"},"comments_total":{"type":"number"},"engagement_rate":{"type":["number","null"]}},"required":["sampled_videos","views_total","views_median","views_max","likes_total","comments_total","engagement_rate"],"description":"The full Sample's stats, unchanged by the Focus."},"videos":{"type":"array","items":{"description":"One normalised video, the same shape on every platform.","allOf":[{"$ref":"#/components/schemas/Video"},{"type":"object","properties":{"focus":{"type":"object","properties":{"verdict":{"type":"string","enum":["in_focus","off_focus","unjudged"],"description":"`unjudged`: the Video could not be judged (or is not judged yet) and is shown."},"reason":{"type":"string"}},"required":["verdict","reason"]}}}]},"description":"In-focus and unjudged Videos; with `include_off_focus=true` (and on a preview) every Video, each with `focus`."},"off_focus_count":{"type":"integer","description":"Videos hidden as off focus."},"focus":{"type":"object","properties":{"total":{"type":"integer","description":"Videos read."},"in_focus":{"type":"integer"},"unjudged":{"type":"integer","description":"Shown, but not counted in focus."},"summary":{"type":"string","description":"\"N of M in focus\"."},"stats":{"type":"object","properties":{"sampled_videos":{"type":"integer"},"views_total":{"type":"number"},"views_median":{"type":["number","null"]},"views_max":{"type":["number","null"]},"likes_total":{"type":"number"},"comments_total":{"type":"number"},"engagement_rate":{"type":["number","null"]}},"required":["sampled_videos","views_total","views_median","views_max","likes_total","comments_total","engagement_rate"],"description":"Stats over the in-focus Videos only."}},"required":["total","in_focus","unjudged","summary","stats"]}},"required":["at","stats","videos","off_focus_count","focus"],"description":"Only on a Tracker with a Focus: its latest Sample through the Focus."},"recent_videos":{"type":"object","properties":{"videos":{"type":"array","items":{"description":"One normalised video, the same shape on every platform.","allOf":[{"$ref":"#/components/schemas/Video"},{"type":"object","properties":{"focus":{"type":"object","properties":{"verdict":{"type":"string","enum":["in_focus","off_focus","unjudged"],"description":"`unjudged`: the Video could not be judged (or is not judged yet) and is shown."},"reason":{"type":"string"}},"required":["verdict","reason"]}}}]},"description":"The Creator's newest Videos, newest first: in-focus and unjudged ones; with `include_off_focus=true` every Video, each with `focus`."},"off_focus_count":{"type":"integer","description":"Videos hidden as off focus."},"focus":{"type":"object","properties":{"total":{"type":"integer","description":"Videos read."},"in_focus":{"type":"integer"},"unjudged":{"type":"integer","description":"Shown, but not counted in focus."},"summary":{"type":"string","description":"\"N of M in focus\"."},"stats":{"type":"object","properties":{"sampled_videos":{"type":"integer"},"views_total":{"type":"number"},"views_median":{"type":["number","null"]},"views_max":{"type":["number","null"]},"likes_total":{"type":"number"},"comments_total":{"type":"number"},"engagement_rate":{"type":["number","null"]}},"required":["sampled_videos","views_total","views_median","views_max","likes_total","comments_total","engagement_rate"],"description":"Stats over the in-focus Videos only."}},"required":["total","in_focus","unjudged","summary","stats"]}},"required":["videos","off_focus_count","focus"],"description":"Only on a Creator Tracker with a Focus: its newest Videos through the Focus."}},"required":["tracker"]},"example":{"tracker":{"id":"trk_4b1e90c7aa","kind":"creator","platform":"tiktok","target":"someone","intelligence":true,"state":"active","last_cycle_at":"2026-09-08T04:00:11.402Z","last_run_id":"run_c07a41bb92","created_at":"2026-09-01T11:20:03.118Z","updated_at":"2026-09-08T04:00:11.402Z"}}}}},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404_3"}},"x-price":{"credits":0,"unit":"call","max_credits":0}},"patch":{"operationId":"updateTracker","summary":"Pause, resume or set analysis","description":"Pauses or resumes the Tracker, switches its analysis on or off, or both. A paused Tracker runs no cycles and is charged nothing. Analysis applies from the next cycle and is charged per new video or Ad it analyses.\n\n**Price:** Free.","tags":["Trackers"],"parameters":[{"name":"id","in":"path","required":true,"description":"Tracker id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"state":{"type":"string","enum":["active","paused"],"description":"Pause or resume. A paused Tracker runs no cycles."},"intelligence":{"type":"boolean","description":"Switch analysis of new videos or Ads on or off, from the next cycle. Pass this, `state`, or both."}},"additionalProperties":false}}}},"responses":{"200":{"description":"`{ tracker }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"tracker":{"$ref":"#/components/schemas/Tracker"}},"required":["tracker"]},"example":{"tracker":{"id":"trk_4b1e90c7aa","kind":"creator","platform":"tiktok","target":"someone","intelligence":true,"state":"paused","last_cycle_at":"2026-09-08T04:00:11.402Z","last_run_id":"run_c07a41bb92","created_at":"2026-09-01T11:20:03.118Z","updated_at":"2026-09-08T04:00:11.402Z"}}}}},"401":{"$ref":"#/components/responses/Problem401"},"409":{"description":"`tracker_limit_exceeded` when resuming would exceed the cap.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/tracker_limit_exceeded","title":"Tracker limit exceeded","status":409,"code":"tracker_limit_exceeded","detail":"Resuming this Tracker would take you past 100 active Trackers.","retryable":false,"action":"Pause or delete a Tracker, then retry.","limit":100,"active":100}}}}},"x-price":{"credits":0,"unit":"call","max_credits":0}},"delete":{"operationId":"deleteTracker","summary":"Stop tracking","description":"Stops the cycles. Snapshots and Change Reports are kept, and the Tracker's change reports stay readable at `GET /v1/trackers/{id}/changes` after deletion. Deleting is final: tracking the target again creates a new Tracker.\n\n**Price:** Free.","tags":["Trackers"],"parameters":[{"name":"id","in":"path","required":true,"description":"Tracker id.","schema":{"type":"string"}}],"responses":{"200":{"description":"`{ tracker }` with state `deleted`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"tracker":{"$ref":"#/components/schemas/Tracker"}},"required":["tracker"]},"example":{"tracker":{"id":"trk_4b1e90c7aa","kind":"creator","platform":"tiktok","target":"someone","intelligence":true,"state":"deleted","last_cycle_at":"2026-09-08T04:00:11.402Z","last_run_id":"run_c07a41bb92","created_at":"2026-09-01T11:20:03.118Z","updated_at":"2026-09-08T04:00:11.402Z"}}}}},"401":{"$ref":"#/components/responses/Problem401"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/trackers/{id}/refresh":{"post":{"operationId":"refreshTracker","summary":"Run a tracker cycle now","description":"Runs the Tracker's cycle now, forcing a fresh fetch rather than reading a fresh Snapshot. `change_report` is null on a quiet cycle.\n\n- **Advertiser analysis:** an Advertiser Tracker's new Ads are analysed in the background on `intelligence_run`, never in the request.\n- **Focus line:** with a Focus, the Run's `result.focus` is `{ judged, gated, cached, unjudged, credits }`.\n- **Skipped Videos:** a Creator's `off_focus_new_videos` counts the new Videos skipped as off focus.\n- **Hidden Videos:** `off_focus_unreported` counts the off-focus Videos a cycle with no Change Report hid, carried into the next report's `off_focus_count`.\n\n**Price:** 6 credits for a creator, 30 credits for an advertiser, plus 20 credits per new video when the Tracker opted into analysis (per new Ad, on its own Run, for an advertiser); a TikTok advertiser's new Ads' detail reads beyond 10 at 3 credits each, quoted at worst (every running Ad new, at most 300). Same price as a scheduled cycle.","tags":["Trackers"],"parameters":[{"name":"id","in":"path","required":true,"description":"Tracker id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"},{"name":"estimate","in":"query","required":false,"description":"Return `{ estimate_credits, cached, per_cycle }`, the cycle's floor price, and run nothing. With analysis on, each new video the cycle finds adds to the charge.","schema":{"type":"boolean"}},{"$ref":"#/components/parameters/MaxCredits"}],"responses":{"200":{"description":"`{ run, tracker, change_report, intelligence_run }`. A replayed Idempotency-Key returns the original Runs and is not charged again. With `estimate=true`, `{ estimate_credits, cached, per_cycle }` instead.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"tracker":{"$ref":"#/components/schemas/Tracker"},"change_report":{"description":"Null on a quiet cycle.","anyOf":[{"$ref":"#/components/schemas/ChangeReport"},{"type":"null"}]},"intelligence_run":{"description":"Advertiser Trackers with `intelligence: true`: the Run analysing this cycle's new Ads in the background, charged per Ad computed. Null when no Ad needed analysis.","anyOf":[{"$ref":"#/components/schemas/Run"},{"type":"null"}]}},"required":["tracker","change_report","intelligence_run"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"tracker_cycle","status":"completed","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":50,"list_price_credits":50,"cached":false},"tracker":{"id":"trk_4b1e90c7aa","kind":"creator","platform":"tiktok","target":"someone","intelligence":true,"state":"active","last_cycle_at":"2026-09-08T04:00:11.402Z","last_run_id":"run_c07a41bb92","created_at":"2026-09-01T11:20:03.118Z","updated_at":"2026-09-08T04:00:11.402Z"},"change_report":{"id":"chg_2ac910f4d8","tracker_id":"trk_4b1e90c7aa","run_id":"run_c07a41bb92","cycle_key":"tiktok:creator:someone:2026-09-08","triggers":["new_videos","outlier"],"changes":{"new_videos":{"before":61,"after":62,"count":1,"videos":[{"id":"7300000000000000000","url":"https://www.tiktok.com/@someone/video/7300000000000000000","posted_at":"2026-09-05T06:32:11.000Z","views":1284000}]},"outliers":[{"id":"7300000000000000000","url":"https://www.tiktok.com/@someone/video/7300000000000000000","views":1284000,"outlier":4.21,"threshold":3}]},"summary":"1 new video, 1 outlier at 4.2x median","created_at":"2026-09-08T04:00:11.402Z"},"intelligence_run":null}},"estimate":{"summary":"With `estimate=true`: the cycle's floor price, nothing run or charged.","value":{"estimate_credits":6,"cached":false,"per_cycle":true}}}}}},"400":{"description":"`invalid_request` — a malformed body. Or `unsupported_platform`: an unknown platform, or a creator on YouTube (creator Trackers cycle on TikTok, Instagram and Facebook). Nothing is created or charged.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/unsupported_platform","title":"Unsupported platform","status":400,"code":"unsupported_platform","detail":"Tracking a creator on youtube is not available yet. Creator Trackers are supported on: tiktok, instagram, facebook.","retryable":false,"action":"Use a platform this operation lists as supported."}}}},"401":{"$ref":"#/components/responses/Problem401"},"402":{"description":"`insufficient_balance`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/insufficient_balance","title":"Insufficient balance","status":402,"code":"insufficient_balance","detail":"Your balance is 0 Credits and this operation needs 6 Credits. Nothing was charged.","retryable":false,"action":"Tell the Customer to top up the Balance, then repeat the same request.","balance_credits":0,"required_credits":6}}}},"404":{"description":"`not_found`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/not_found","title":"Not found","status":404,"code":"not_found","detail":"No Tracker with that id for this Customer, or the creator no longer exists.","retryable":false,"action":"Check the id or handle; list your resources to find the right one."}}}},"409":{"$ref":"#/components/responses/Problem409"},"422":{"description":"`unsupported_kind` — a Video Tracker, which has no cycle. Only creator, hashtag, sound, advertiser and keyword Trackers cycle; nothing is run or charged.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/unsupported_kind","title":"Unsupported kind","status":422,"code":"unsupported_kind","detail":"Tracking video targets is not available yet. Creator, hashtag, sound, advertiser and keyword tracking are supported today.","retryable":false,"action":"Do not repeat this request; nothing was charged. Use an operation that serves this kind.","supported_kinds":["creator","hashtag","sound","advertiser","keyword"]}}}},"429":{"$ref":"#/components/responses/Problem429_2"}},"x-price":{"credits":6,"unit":"cycle","max_credits":null}}},"/trackers/{id}/focus":{"put":{"operationId":"setTrackerFocus","summary":"Set or clear a tracker's focus","description":"Sets the Tracker's Focus and judges its latest Sample against it now, as a Run, so `sample` already shows the new verdicts. For a Creator, `sample` is `recent_videos`, its newest Videos.\n\n- **Versions:** each edit is a new version. Older Change Reports keep the verdicts they were built on, and going back to an earlier Focus reuses its verdicts.\n- **Clearing:** `null` clears it, and reads show every Video again.\n- **Unsupported kinds:** 422 `focus_unsupported_kind`, which lists the kinds that can.\n\n**Price:** +3 credits per Video the model judges, +1 credit per Video `must_mention` rules out; nothing for a Video already judged under this Focus (a preview included) or one that could not be judged. Clearing is free.","tags":["Trackers"],"parameters":[{"name":"id","in":"path","required":true,"description":"Tracker id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"},{"name":"estimate","in":"query","required":false,"description":"Return `{ estimate_credits, cached, videos, to_judge }`: every Video of the latest Sample not yet judged under this Focus at the model price. Nothing is judged or saved.","schema":{"type":"boolean"}},{"$ref":"#/components/parameters/MaxCredits"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"focus":{"type":["object","null"],"properties":{"text":{"type":"string","description":"Which Videos are relevant to you, in plain language, exclusions included, e.g. `Apple Inc. and its products (iPhone, Mac, AirPods, iOS). Not the fruit, recipes or orchards.` 1 to 1000 characters."},"must_mention":{"type":"array","items":{"type":"string"},"description":"Up to 20 terms of at most 60 characters. A Video that has captions or an analysis transcript, and whose caption, hashtags, captions and transcript name none of them (any case, whole term), is off focus without a model call; one with neither goes to the model, so a term said aloud still counts; one naming any is still judged against `text`."}},"required":["text"],"additionalProperties":false,"description":"The new Focus, or null to clear it (free)."},"estimate":{"type":"boolean","description":"`true` returns `{ estimate_credits, cached }`, creates no Run and charges nothing."}},"required":["focus"],"additionalProperties":false}}}},"responses":{"200":{"description":"`{ run, tracker, sample }`; `run` is null and `sample` absent when the Focus was cleared. A replayed Idempotency-Key returns the original Run and is not charged again. With `estimate=true`, the quote instead.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"tracker":{"$ref":"#/components/schemas/Tracker"},"sample":{"type":"object","properties":{"at":{"type":"string","description":"When the latest Sample's Snapshot was taken."},"stats":{"type":"object","properties":{"sampled_videos":{"type":"integer"},"views_total":{"type":"number"},"views_median":{"type":["number","null"]},"views_max":{"type":["number","null"]},"likes_total":{"type":"number"},"comments_total":{"type":"number"},"engagement_rate":{"type":["number","null"]}},"required":["sampled_videos","views_total","views_median","views_max","likes_total","comments_total","engagement_rate"],"description":"The full Sample's stats, unchanged by the Focus."},"videos":{"type":"array","items":{"description":"One normalised video, the same shape on every platform.","allOf":[{"$ref":"#/components/schemas/Video"},{"type":"object","properties":{"focus":{"type":"object","properties":{"verdict":{"type":"string","enum":["in_focus","off_focus","unjudged"],"description":"`unjudged`: the Video could not be judged (or is not judged yet) and is shown."},"reason":{"type":"string"}},"required":["verdict","reason"]}}}]},"description":"In-focus and unjudged Videos; with `include_off_focus=true` (and on a preview) every Video, each with `focus`."},"off_focus_count":{"type":"integer","description":"Videos hidden as off focus."},"focus":{"type":"object","properties":{"total":{"type":"integer","description":"Videos read."},"in_focus":{"type":"integer"},"unjudged":{"type":"integer","description":"Shown, but not counted in focus."},"summary":{"type":"string","description":"\"N of M in focus\"."},"stats":{"type":"object","properties":{"sampled_videos":{"type":"integer"},"views_total":{"type":"number"},"views_median":{"type":["number","null"]},"views_max":{"type":["number","null"]},"likes_total":{"type":"number"},"comments_total":{"type":"number"},"engagement_rate":{"type":["number","null"]}},"required":["sampled_videos","views_total","views_median","views_max","likes_total","comments_total","engagement_rate"],"description":"Stats over the in-focus Videos only."}},"required":["total","in_focus","unjudged","summary","stats"]}},"required":["at","stats","videos","off_focus_count","focus"],"description":"Only on a Tracker with a Focus: its latest Sample through the Focus."},"recent_videos":{"type":"object","properties":{"videos":{"type":"array","items":{"description":"One normalised video, the same shape on every platform.","allOf":[{"$ref":"#/components/schemas/Video"},{"type":"object","properties":{"focus":{"type":"object","properties":{"verdict":{"type":"string","enum":["in_focus","off_focus","unjudged"],"description":"`unjudged`: the Video could not be judged (or is not judged yet) and is shown."},"reason":{"type":"string"}},"required":["verdict","reason"]}}}]},"description":"The Creator's newest Videos, newest first: in-focus and unjudged ones; with `include_off_focus=true` every Video, each with `focus`."},"off_focus_count":{"type":"integer","description":"Videos hidden as off focus."},"focus":{"type":"object","properties":{"total":{"type":"integer","description":"Videos read."},"in_focus":{"type":"integer"},"unjudged":{"type":"integer","description":"Shown, but not counted in focus."},"summary":{"type":"string","description":"\"N of M in focus\"."},"stats":{"type":"object","properties":{"sampled_videos":{"type":"integer"},"views_total":{"type":"number"},"views_median":{"type":["number","null"]},"views_max":{"type":["number","null"]},"likes_total":{"type":"number"},"comments_total":{"type":"number"},"engagement_rate":{"type":["number","null"]}},"required":["sampled_videos","views_total","views_median","views_max","likes_total","comments_total","engagement_rate"],"description":"Stats over the in-focus Videos only."}},"required":["total","in_focus","unjudged","summary","stats"]}},"required":["videos","off_focus_count","focus"],"description":"Only on a Creator Tracker with a Focus: its newest Videos through the Focus."},"run":{"description":"The Run judging the latest Sample under the new Focus, charged per judgment. Null when the Focus was cleared.","anyOf":[{"$ref":"#/components/schemas/Run"},{"type":"null"}]}},"required":["tracker","run"]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"run":{"id":"run_8f2c1ad04b","kind":"focus_judgment","status":"completed","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":6,"list_price_credits":6,"cached":false},"tracker":{"id":"trk_4b1e90c7aa","kind":"keyword","platform":"tiktok","target":"ai video tools","intelligence":false,"state":"active","last_cycle_at":"2026-09-08T04:00:11.402Z","last_run_id":"run_c07a41bb92","created_at":"2026-09-01T11:20:03.118Z","updated_at":"2026-09-08T04:00:11.402Z","focus":{"text":"Hands-on tips for AI video tools. Not product comparisons.","must_mention":[]}}}},"estimate":{"summary":"With `estimate=true`: the quote, nothing judged or saved.","value":{"estimate_credits":6,"cached":false,"videos":2,"to_judge":2}}}}}},"401":{"$ref":"#/components/responses/Problem401"},"402":{"description":"`insufficient_balance` — the Balance cannot cover the quote. Nothing is judged or saved.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/insufficient_balance","title":"Insufficient balance","status":402,"code":"insufficient_balance","detail":"Your balance is 0 Credits and this operation needs 6 Credits. Nothing was charged.","retryable":false,"action":"Tell the Customer to top up the Balance, then repeat the same request.","balance_credits":0,"required_credits":6}}}},"404":{"$ref":"#/components/responses/Problem404_3"},"409":{"$ref":"#/components/responses/Problem409"},"422":{"description":"`focus_unsupported_kind` — this kind of Tracker cannot take a Focus.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/focus_unsupported_kind","title":"Focus not supported for this kind","status":422,"code":"focus_unsupported_kind","detail":"A Focus cannot be set on a advertiser Tracker.","retryable":false,"action":"Send the Tracker without `focus`, or pick a kind in `supported_kinds`.","supported_kinds":["keyword"]}}}},"429":{"$ref":"#/components/responses/Problem429_2"}},"x-price":{"credits":3,"unit":"video","max_credits":null}}},"/trackers/{id}/focus/preview":{"post":{"operationId":"previewTrackerFocus","summary":"Preview a focus on a tracker","description":"Judges a proposed Focus on the Tracker's latest Sample without saving it: every Video with its verdict and reason, and how many would be hidden.\n\n- **Setting it later:** its verdicts are kept under that Focus, so setting it afterwards with `PUT /v1/trackers/{id}/focus` costs nothing more.\n- **Unsupported kinds:** 422 `focus_unsupported_kind`, which lists the kinds that can.\n\n**Price:** As setting the Focus: +3 credits per Video the model judges, +1 credit per Video `must_mention` rules out, nothing for a Video already judged under it.","tags":["Trackers"],"parameters":[{"name":"id","in":"path","required":true,"description":"Tracker id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"},{"name":"estimate","in":"query","required":false,"description":"Return `{ estimate_credits, cached, videos, to_judge }` and judge nothing.","schema":{"type":"boolean"}},{"$ref":"#/components/parameters/MaxCredits"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"focus":{"type":"object","properties":{"text":{"type":"string","description":"Which Videos are relevant to you, in plain language, exclusions included, e.g. `Apple Inc. and its products (iPhone, Mac, AirPods, iOS). Not the fruit, recipes or orchards.` 1 to 1000 characters."},"must_mention":{"type":"array","items":{"type":"string"},"description":"Up to 20 terms of at most 60 characters. A Video that has captions or an analysis transcript, and whose caption, hashtags, captions and transcript name none of them (any case, whole term), is off focus without a model call; one with neither goes to the model, so a term said aloud still counts; one naming any is still judged against `text`."}},"required":["text"],"additionalProperties":false,"description":"The Focus to judge, not saved."},"estimate":{"type":"boolean","description":"`true` returns `{ estimate_credits, cached }`, creates no Run and charges nothing."}},"required":["focus"],"additionalProperties":false}}}},"responses":{"200":{"description":"`{ run, focus, sample }`; `sample` is null when the Tracker has no Sample yet. With `estimate=true`, the quote instead.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"run":{"$ref":"#/components/schemas/Run","description":"The Run judging the latest Sample, charged per judgment."},"focus":{"type":"object","properties":{"text":{"type":"string"},"must_mention":{"type":"array","items":{"type":"string"}}},"required":["text","must_mention"],"description":"The Focus previewed, as it would be stored."},"sample":{"type":["object","null"],"properties":{"at":{"type":"string","description":"When the latest Sample's Snapshot was taken."},"stats":{"type":"object","properties":{"sampled_videos":{"type":"integer"},"views_total":{"type":"number"},"views_median":{"type":["number","null"]},"views_max":{"type":["number","null"]},"likes_total":{"type":"number"},"comments_total":{"type":"number"},"engagement_rate":{"type":["number","null"]}},"required":["sampled_videos","views_total","views_median","views_max","likes_total","comments_total","engagement_rate"],"description":"The full Sample's stats, unchanged by the Focus."},"videos":{"type":"array","items":{"description":"One normalised video, the same shape on every platform.","allOf":[{"$ref":"#/components/schemas/Video"},{"type":"object","properties":{"focus":{"type":"object","properties":{"verdict":{"type":"string","enum":["in_focus","off_focus","unjudged"],"description":"`unjudged`: the Video could not be judged (or is not judged yet) and is shown."},"reason":{"type":"string"}},"required":["verdict","reason"]}}}]},"description":"In-focus and unjudged Videos; with `include_off_focus=true` (and on a preview) every Video, each with `focus`."},"off_focus_count":{"type":"integer","description":"Videos hidden as off focus."},"focus":{"type":"object","properties":{"total":{"type":"integer","description":"Videos read."},"in_focus":{"type":"integer"},"unjudged":{"type":"integer","description":"Shown, but not counted in focus."},"summary":{"type":"string","description":"\"N of M in focus\"."},"stats":{"type":"object","properties":{"sampled_videos":{"type":"integer"},"views_total":{"type":"number"},"views_median":{"type":["number","null"]},"views_max":{"type":["number","null"]},"likes_total":{"type":"number"},"comments_total":{"type":"number"},"engagement_rate":{"type":["number","null"]}},"required":["sampled_videos","views_total","views_median","views_max","likes_total","comments_total","engagement_rate"],"description":"Stats over the in-focus Videos only."}},"required":["total","in_focus","unjudged","summary","stats"]}},"required":["at","stats","videos","off_focus_count","focus"],"description":"Every Video of the latest Sample with `focus: { verdict, reason }`. Null when the Tracker has no Sample yet (always on a Creator Tracker)."},"recent_videos":{"type":"object","properties":{"videos":{"type":"array","items":{"description":"One normalised video, the same shape on every platform.","allOf":[{"$ref":"#/components/schemas/Video"},{"type":"object","properties":{"focus":{"type":"object","properties":{"verdict":{"type":"string","enum":["in_focus","off_focus","unjudged"],"description":"`unjudged`: the Video could not be judged (or is not judged yet) and is shown."},"reason":{"type":"string"}},"required":["verdict","reason"]}}}]},"description":"The Creator's newest Videos, newest first: in-focus and unjudged ones; with `include_off_focus=true` every Video, each with `focus`."},"off_focus_count":{"type":"integer","description":"Videos hidden as off focus."},"focus":{"type":"object","properties":{"total":{"type":"integer","description":"Videos read."},"in_focus":{"type":"integer"},"unjudged":{"type":"integer","description":"Shown, but not counted in focus."},"summary":{"type":"string","description":"\"N of M in focus\"."},"stats":{"type":"object","properties":{"sampled_videos":{"type":"integer"},"views_total":{"type":"number"},"views_median":{"type":["number","null"]},"views_max":{"type":["number","null"]},"likes_total":{"type":"number"},"comments_total":{"type":"number"},"engagement_rate":{"type":["number","null"]}},"required":["sampled_videos","views_total","views_median","views_max","likes_total","comments_total","engagement_rate"],"description":"Stats over the in-focus Videos only."}},"required":["total","in_focus","unjudged","summary","stats"]}},"required":["videos","off_focus_count","focus"],"description":"Only on a Creator Tracker: its newest Videos, every one with `focus: { verdict, reason }`."}},"required":["run","focus","sample"]},{"$ref":"#/components/schemas/Estimate"}]},"example":{"run":{"id":"run_8f2c1ad04b","kind":"focus_judgment","status":"completed","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":6,"list_price_credits":6,"cached":false},"focus":{"text":"Hands-on tips for AI video tools. Not product comparisons.","must_mention":[]},"sample":null}}}},"401":{"$ref":"#/components/responses/Problem401"},"402":{"description":"`insufficient_balance` — the Balance cannot cover the quote. Nothing is judged.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/insufficient_balance","title":"Insufficient balance","status":402,"code":"insufficient_balance","detail":"Your balance is 0 Credits and this operation needs 6 Credits. Nothing was charged.","retryable":false,"action":"Tell the Customer to top up the Balance, then repeat the same request.","balance_credits":0,"required_credits":6}}}},"404":{"$ref":"#/components/responses/Problem404_3"},"409":{"$ref":"#/components/responses/Problem409"},"429":{"$ref":"#/components/responses/Problem429_2"}},"x-price":{"credits":3,"unit":"video","max_credits":null}}},"/trackers/{id}/snapshots":{"get":{"operationId":"listTrackerSnapshots","summary":"Read a target's snapshots","description":"The shared Snapshots of this Tracker's target, newest first — not copies owned by this Tracker, so rows written by another Customer's cycle or by a plain lookup are all here. A Keyword Tracker on Instagram or Facebook marks each Snapshot `coverage: \"partial\"`: their search is a best-effort index.\n\n**Price:** Free.","tags":["Trackers"],"parameters":[{"name":"id","in":"path","required":true,"description":"Tracker id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit_5"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"`{ items, next_cursor }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string"},"views":{"type":["number","null"]},"followers":{"type":["number","null"]},"metrics":{"description":"The metrics recorded at `at`, as stored."},"source":{"type":"string","description":"`vendor` or `backfill`."},"coverage":{"type":"string","enum":["partial"],"description":"A Keyword Tracker's on Instagram or Facebook: their search is a best-effort index. Absent otherwise."}},"required":["at","views","followers","source"]}}},"required":["items"]}]},"example":{"items":[{"at":"2026-09-08T09:14:04.219Z","views":null,"followers":184300,"metrics":{"followers":184300,"videos":62},"source":"vendor"}],"next_cursor":null}}}},"400":{"$ref":"#/components/responses/Problem400_6"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/trackers/{id}/changes":{"get":{"operationId":"listTrackerChanges","summary":"List change reports","description":"This Tracker's Change Reports, newest first, readable after the Tracker is deleted. Quiet cycles are absent by design: no report means nothing tripped.\n\nEach item is `{ id, tracker_id, run_id, cycle_key, triggers, changes, summary, created_at }`. `changes` has one key per tripped trigger, with before/after numbers.\n\n**Creator changes**\n\n- `followers`: `{ before, after, change, change_pct }`\n- `new_videos`: `{ since, count, videos }`\n- `outliers` and `velocity`: lists whose entries carry `before` (null for a video new to the Tracker) and `after`. History is at `GET /v1/videos/{platform}/{id}/snapshots`.\n- `became_ad`: entries `{ id, url, before, after }`, each side the Video's `{ is_ad, paid_partnership }`. `before` is null when not reported.\n- `bio_link_changed`: `{ before, after }` link lists.\n- `verified_changed`: `{ before, after }` booleans.\n- **Firing:** `became_ad`, `bio_link_changed` and `verified_changed` fire once, on the transition, only when the Platform reported the value on both sides. `became_ad` also counts an unreported `before`.\n\n**Advertiser changes**\n\n- `new_ads`: `{ since, count, ads }`\n- `stopped_ads`: `{ count, ads }`. An Ad gone from Meta's library counts, with `removed_from_library: true`.\n- `variant_growth`: entries `{ before, after, added }`\n- `new_countries_or_placements`: entries `{ countries, placements }`, only what is new.\n- `truncated: true`: the cycle hit its page cap with Ads unread.\n- `incomplete: true`: the library failed part-way. The Run's result says so too.\n- **Ad entries:** every one carries `id`, `library_id` and its Ad Library `url`.\n- **TikTok `new_ads`:** entries add `targeting` `{ countries, ages, genders }`, `landing_page` and `cta` (null when not read).\n- **TikTok `reach_growth`:** `{ count, ads }`, each `{ before, after }` audience buckets.\n- **TikTok analysis:** a new Ad's analysis is read from its Ad lookup, as on Meta.\n\n**Hashtag and Keyword changes**\n\n- `median_views`: `{ before, after, change, change_pct, sample_based: true }`\n- `new_top_videos`: `{ since, count, videos }`, each `{ id, url, views }`\n- **Coverage:** a Keyword Tracker on Instagram or Facebook marks each report `coverage: \"partial\"`.\n\n**Sound changes**\n\n- `video_count`: `{ before, after, change, change_pct }`, rises only.\n- `new_top_video`: `{ since, before, after }`, each side `{ id, url, views }`\n\n**With a Focus**\n\n- **Filtered lists:** `changes` lists only in-focus and unjudged Videos and `off_focus_count` counts the rest. Stats stay full-Sample.\n- **Seeing the rest:** `include_off_focus=true` adds them as `off_focus_videos`, each with `focus: { verdict, reason }`.\n- **Off-focus-only cycles:** a cycle whose only news is off focus writes no report and sends no webhook. Its Run's result records `off_focus_unreported`, and those Videos count in the next report's `off_focus_count`.\n\n**Price:** Free.","tags":["Trackers"],"parameters":[{"name":"id","in":"path","required":true,"description":"Tracker id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit_5"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/IncludeOffFocus"}],"responses":{"200":{"description":"`{ items, next_cursor }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ChangeReport"}}},"required":["items"]}]},"example":{"items":[{"id":"chg_2ac910f4d8","tracker_id":"trk_4b1e90c7aa","run_id":"run_c07a41bb92","cycle_key":"tiktok:creator:someone:2026-09-08","triggers":["new_videos","outlier"],"changes":{"new_videos":{"before":61,"after":62,"count":1,"videos":[{"id":"7300000000000000000","url":"https://www.tiktok.com/@someone/video/7300000000000000000","posted_at":"2026-09-05T06:32:11.000Z","views":1284000}]},"outliers":[{"id":"7300000000000000000","url":"https://www.tiktok.com/@someone/video/7300000000000000000","views":1284000,"outlier":4.21,"threshold":3}]},"summary":"1 new video, 1 outlier at 4.2x median","created_at":"2026-09-08T04:00:11.402Z"}],"next_cursor":null}}}},"400":{"$ref":"#/components/responses/Problem400_6"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/collections":{"post":{"operationId":"createCollection","summary":"Create a collection of one kind","description":"Creates a named Collection of one kind, empty or with `tracker_ids` you already have (all or nothing). The kind is fixed; members may come from any Platform. At most 50 per Customer.\n\n**Price:** Free.","tags":["Collections"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"Unique among your Collections, regardless of case."},"kind":{"type":"string","enum":["creator","hashtag","sound","advertiser","keyword"],"description":"What every member will be. Fixed once created. `video` is deprecated and refused with 400 `kind_deprecated`."},"tracker_ids":{"type":"array","items":{"type":"string"},"maxItems":100,"description":"Trackers you already have to put in it at once, all of `kind`. Created with them or not at all."}},"required":["name","kind"],"additionalProperties":false}}}},"responses":{"201":{"description":"`{ collection }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"collection":{"$ref":"#/components/schemas/Collection"}},"required":["collection"]},"example":{"collection":{"id":"col_7d20e1b5c4","name":"Competitors","kind":"creator","member_count":0,"created_at":"2026-09-02T09:14:40.221Z","updated_at":"2026-09-02T09:14:40.221Z"}}}}},"400":{"description":"`kind_deprecated` — `video` is deprecated: no new Video Collections. Track the Creator, a Hashtag or a Sound instead. Nothing is created or charged. Or: `invalid_request` — a malformed body, an empty or over-long `name`, an unknown `kind`, or more than 100 `tracker_ids`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"kind_deprecated":{"summary":"`kind_deprecated` — `video` is deprecated: no new Video Collections. Track the Creator, a Hashtag or a Sound instead. Nothing is created or charged.","value":{"type":"https://www.shortsintel.com/docs/reference/errors/kind_deprecated","title":"Kind deprecated","status":400,"code":"kind_deprecated","detail":"Video Trackers and Collections can no longer be created. Track the Creator, a Hashtag or a Sound instead: their cycles re-snapshot the Videos they find every day.","retryable":false,"action":"Track the Creator, a Hashtag or a Sound instead of a Video.","supported_kinds":["creator","hashtag","sound","advertiser","keyword"]}},"invalid_request":{"summary":"`invalid_request` — a malformed body, an empty or over-long `name`, an unknown `kind`, or more than 100 `tracker_ids`.","value":{"type":"https://www.shortsintel.com/docs/reference/errors/invalid_request","title":"Invalid request","status":400,"code":"invalid_request","detail":"name must not be empty.","retryable":false,"action":"Fix the field named in `detail`, then send the corrected request."}}}}}},"401":{"$ref":"#/components/responses/Problem401"},"404":{"description":"`not_found`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/not_found","title":"Not found","status":404,"code":"not_found","detail":"A `tracker_ids` entry is not one of this Customer's Trackers.","retryable":false,"action":"Check the id or handle; list your resources to find the right one."}}}},"409":{"description":"`collection_name_taken` — you already have a Collection with that name, in any case. Carries `collection_id`. Or: `collection_limit_exceeded` at 50 Collections. Or: `collection_kind_mismatch` — the Tracker is not of the Collection's kind.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"collection_name_taken":{"summary":"`collection_name_taken` — you already have a Collection with that name, in any case. Carries `collection_id`.","value":{"type":"https://www.shortsintel.com/docs/reference/errors/collection_name_taken","title":"Collection name taken","status":409,"code":"collection_name_taken","detail":"You already have a Collection named \"Competitors\". Names are unique regardless of case.","retryable":false,"action":"Use the Collection in `collection_id`, or pick another name.","collection_id":"col_7d20e1b5c4"}},"collection_limit_exceeded":{"summary":"`collection_limit_exceeded` at 50 Collections.","value":{"type":"https://www.shortsintel.com/docs/reference/errors/collection_limit_exceeded","title":"Collection limit exceeded","status":409,"code":"collection_limit_exceeded","detail":"This Customer already has 50 Collections, the limit is 50. Delete one first.","retryable":false,"action":"Delete a Collection you no longer use, then retry.","limit":50,"count":50}},"collection_kind_mismatch":{"summary":"`collection_kind_mismatch` — the Tracker is not of the Collection's kind.","value":{"type":"https://www.shortsintel.com/docs/reference/errors/collection_kind_mismatch","title":"Collection kind mismatch","status":409,"code":"collection_kind_mismatch","detail":"\"Competitors\" is a Collection of creator Trackers and cannot hold a video.","retryable":false,"action":"Add this target to a Collection of its own kind.","collection_kind":"creator","kind":"video"}}}}}}},"x-price":{"credits":0,"unit":"call","max_credits":0}},"get":{"operationId":"listCollections","summary":"List your collections","description":"The Customer's Collections, newest first, with member counts.\n\n**Price:** Free.","tags":["Collections"],"parameters":[{"$ref":"#/components/parameters/Limit_5"},{"$ref":"#/components/parameters/Cursor"},{"name":"kind","in":"query","required":false,"description":"`creator`, `hashtag`, `sound` or `advertiser`; `video` (deprecated) lists any remaining Video Collections.","schema":{"type":"string","enum":["creator","hashtag","sound","advertiser","keyword","video"]}}],"responses":{"200":{"description":"`{ items, next_cursor }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Collection"}}},"required":["items"]}]},"example":{"items":[{"id":"col_7d20e1b5c4","name":"Competitors","kind":"creator","member_count":4,"created_at":"2026-09-02T09:14:40.221Z","updated_at":"2026-09-02T09:14:40.221Z"}],"next_cursor":null}}}},"400":{"description":"`invalid_request` for a `cursor` that is not a `next_cursor` this API issued. Nothing is charged. Or: `invalid_request` — an unknown `kind`, a bad `limit`, or a `cursor` that is not a previous `next_cursor`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"invalid_request":{"summary":"`invalid_request` — an unknown `kind`, a bad `limit`, or a `cursor` that is not a previous `next_cursor`.","value":{"type":"https://www.shortsintel.com/docs/reference/errors/invalid_request","title":"Invalid request","status":400,"code":"invalid_request","detail":"kind must be one of creator, video, hashtag, sound.","retryable":false,"action":"Fix the field named in `detail`, then send the corrected request."}}}}}},"401":{"$ref":"#/components/responses/Problem401"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/collections/{id}":{"get":{"operationId":"getCollection","summary":"Read one collection","description":"One Collection. Another Customer's id is a 404, never a 403.\n\n**Price:** Free.","tags":["Collections"],"parameters":[{"name":"id","in":"path","required":true,"description":"Collection id.","schema":{"type":"string"}}],"responses":{"200":{"description":"`{ collection }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"collection":{"$ref":"#/components/schemas/Collection"}},"required":["collection"]},"example":{"collection":{"id":"col_7d20e1b5c4","name":"Competitors","kind":"creator","member_count":4,"created_at":"2026-09-02T09:14:40.221Z","updated_at":"2026-09-02T09:14:40.221Z"}}}}},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404_4"}},"x-price":{"credits":0,"unit":"call","max_credits":0}},"patch":{"operationId":"renameCollection","summary":"Change a collection's name","description":"Renames the Collection. Its kind never changes.\n\n**Price:** Free.","tags":["Collections"],"parameters":[{"name":"id","in":"path","required":true,"description":"Collection id.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"The new name, 1 to 100 characters, unique among your Collections regardless of case (else 409 `collection_name_taken`)."}},"required":["name"],"additionalProperties":false}}}},"responses":{"200":{"description":"`{ collection }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"collection":{"$ref":"#/components/schemas/Collection"}},"required":["collection"]},"example":{"collection":{"id":"col_7d20e1b5c4","name":"Rivals","kind":"creator","member_count":4,"created_at":"2026-09-02T09:14:40.221Z","updated_at":"2026-09-02T09:14:40.221Z"}}}}},"400":{"description":"`invalid_request` — a malformed body, or an empty or over-long `name`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/invalid_request","title":"Invalid request","status":400,"code":"invalid_request","detail":"name must not be empty.","retryable":false,"action":"Fix the field named in `detail`, then send the corrected request."}}}},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404_4"},"409":{"description":"`collection_name_taken` — you already have a Collection with that name, in any case. Carries `collection_id`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/collection_name_taken","title":"Collection name taken","status":409,"code":"collection_name_taken","detail":"You already have a Collection named \"Competitors\". Names are unique regardless of case.","retryable":false,"action":"Use the Collection in `collection_id`, or pick another name.","collection_id":"col_7d20e1b5c4"}}}}},"x-price":{"credits":0,"unit":"call","max_credits":0}},"delete":{"operationId":"deleteCollection","summary":"Delete a collection, optionally its trackers","description":"Deletes the Collection. Its Trackers keep running unless `delete_trackers=true`, which deletes the members that sit in no other Collection. The response always lists the former members still active, which are still charged every cycle.\n\n**Price:** Free.","tags":["Collections"],"parameters":[{"name":"id","in":"path","required":true,"description":"Collection id.","schema":{"type":"string"}},{"name":"delete_trackers","in":"query","required":false,"description":"Also delete member Trackers that are in no other Collection. Default false.","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"`{ collection, deleted_trackers, trackers_still_active }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"collection":{"$ref":"#/components/schemas/Collection","description":"The Collection as it was."},"deleted_trackers":{"type":"array","items":{"$ref":"#/components/schemas/Tracker"},"description":"Deleted with it; only with `delete_trackers=true`."},"trackers_still_active":{"type":"array","items":{"$ref":"#/components/schemas/Tracker"},"description":"Former members still active, and so still charged each cycle."}},"required":["collection","deleted_trackers","trackers_still_active"]},"example":{"collection":{"id":"col_7d20e1b5c4","name":"Competitors","kind":"creator","member_count":4,"created_at":"2026-09-02T09:14:40.221Z","updated_at":"2026-09-02T09:14:40.221Z"},"deleted_trackers":[],"trackers_still_active":[{"id":"trk_4b1e90c7aa","kind":"creator","platform":"tiktok","target":"someone","intelligence":true,"state":"active","last_cycle_at":"2026-09-08T04:00:11.402Z","last_run_id":"run_c07a41bb92","created_at":"2026-09-01T11:20:03.118Z","updated_at":"2026-09-08T04:00:11.402Z"}]}}}},"400":{"description":"`invalid_request` — `delete_trackers` other than `true` or `false`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/invalid_request","title":"Invalid request","status":400,"code":"invalid_request","detail":"delete_trackers: Invalid enum value.","retryable":false,"action":"Fix the field named in `detail`, then send the corrected request."}}}},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404_4"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/collections/{id}/members":{"get":{"operationId":"listCollectionMembers","summary":"Rank the members","description":"The members ranked, highest first, on their latest Snapshot and Scores, with each member's Tracker and its state. Nothing is fetched: a member that has not cycled yet ranks last with nulls.\n\n**Price:** Free.","tags":["Collections"],"parameters":[{"name":"id","in":"path","required":true,"description":"Collection id.","schema":{"type":"string"}},{"name":"order_by","in":"query","required":false,"description":"`followers`, `median_views`, `outlier` or `views`. Defaults to `followers` for a creator Collection, `views` otherwise. Ties keep the order members were added.","schema":{"type":"string","enum":["followers","median_views","outlier","views"]}},{"name":"platforms","in":"query","required":false,"description":"Comma-separated, or repeated. Omit for every Platform.","schema":{"type":"string","example":"tiktok,instagram"}},{"$ref":"#/components/parameters/Limit_5"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"`{ order_by, items, next_cursor }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"rank":{"type":"integer","description":"1-based, across the whole filtered ranking rather than the page."},"tracker":{"$ref":"#/components/schemas/Tracker","description":"The member, state included."},"name":{"type":["string","null"],"description":"Creators: their display name. Null on other kinds and before a creator's first cycle."},"avatar_url":{"type":["string","null"],"description":"Creators: our archived avatar when there is one, else the platform's URL, which may expire. Null on other kinds and before a creator's first cycle."},"snapshot_at":{"type":["string","null"],"description":"When the numbers were taken. Null when it has not cycled yet."},"followers":{"type":["number","null"],"description":"Creators: followers at the latest Snapshot."},"views":{"type":["number","null"],"description":"Creators: views across their last 20 videos. Videos, hashtags and sounds: views at the latest Snapshot."},"median_views":{"type":["number","null"],"description":"The creator's baseline median; for a video, its creator's."},"outlier":{"type":["number","null"],"description":"Creators: the best `views / median_views` among their last 20 videos. Videos: their own."}},"required":["rank","tracker","name","avatar_url","snapshot_at","followers","views","median_views","outlier"]}},"order_by":{"type":"string","enum":["followers","median_views","outlier","views"],"description":"The metric the ranking used."}},"required":["items","order_by"]}]},"example":{"order_by":"followers","items":[{"rank":1,"tracker":{"id":"trk_4b1e90c7aa","kind":"creator","platform":"tiktok","target":"someone","intelligence":true,"state":"active","last_cycle_at":"2026-09-08T04:00:11.402Z","last_run_id":"run_c07a41bb92","created_at":"2026-09-01T11:20:03.118Z","updated_at":"2026-09-08T04:00:11.402Z"},"name":"Someone","avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","snapshot_at":"2026-09-08T04:00:11.402Z","followers":1284000,"views":9812400,"median_views":212000,"outlier":6.06}],"next_cursor":null}}}},"400":{"description":"`invalid_request` (or `unsupported_platform` for an unknown entry in `platforms`) — an unknown `order_by`, or a `cursor` that is not a previous `next_cursor`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/invalid_request","title":"Invalid request","status":400,"code":"invalid_request","detail":"`order_by` must be one of followers, median_views, outlier, views.","retryable":false,"action":"Fix the field named in `detail`, then send the corrected request."}}}},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404_4"}},"x-price":{"credits":0,"unit":"call","max_credits":0}},"post":{"operationId":"addCollectionMember","summary":"Add a member","description":"Puts a Tracker in the Collection: by `tracker_id`, or by `platform` and `target`.\n\n- **Existing Tracker:** attached as it is. A paused one stays paused, as the response shows.\n- **Untracked target:** gets a new Tracker whose first cycle runs now.\n- **Other kinds:** refused.\n- **Duplicates:** not an error.\n- **Video Collections:** Video is no longer a trackable kind, so a video Collection takes only Video Trackers you have, by `tracker_id`. A target is 400 `kind_deprecated`.\n- **Advertiser Collections:** they hold Meta and TikTok Advertisers. `platform` omitted or `meta` takes a Facebook Page id, Page URL or name. `tiktok` takes a TikTok ad library advertiser id, library URL or name, as on `POST /v1/trackers`.\n- **Ambiguous name:** 409 `advertiser_ambiguous` when several carry the name.\n\n**Price:** Free, except a target not tracked yet: its first cycle, 6 credits for a creator, 3 credits for a hashtag, 6 credits for a sound, 3 credits for a keyword, 30 credits for an advertiser.","tags":["Collections"],"parameters":[{"name":"id","in":"path","required":true,"description":"Collection id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Estimate_3"},{"$ref":"#/components/parameters/MaxCredits"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"tracker_id":{"type":"string","description":"A Tracker you already have. Or, instead, `platform` and `target` (plus optional `intelligence`) for a target of the Collection's kind; an explicit `kind` must match it."},"platform":{"type":"string","enum":["tiktok","instagram","youtube"],"description":"With `target`, instead of `tracker_id`: the platform the target lives on, as `POST /v1/trackers` takes it for the Collection's kind."},"target":{"type":"string","description":"With `platform`, instead of `tracker_id`: the handle, tag, sound id, search phrase or advertiser to track, as `POST /v1/trackers` takes it. A target you already track adds that Tracker, free; a new one is tracked and its first cycle charged."},"kind":{"type":"string","enum":["creator","hashtag","sound","advertiser","keyword","video"],"description":"Must match the Collection's kind. A new Video Tracker is refused with 400 `kind_deprecated`."},"intelligence":{"type":"boolean","description":"With `platform` and `target`: analyse each new video (or new Ad) the new Tracker's cycles find, charged per item. A target already tracked keeps its own setting."},"estimate":{"type":"boolean","description":"As in the query."}},"additionalProperties":false}}}},"responses":{"200":{"description":"Already a member: the same body with `added: false`. With `estimate=true`, `{ estimate_credits, cached, already_tracking, tracker_id, per_cycle }` instead.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"collection":{"$ref":"#/components/schemas/Collection","description":"Absent only with `collection_error`."},"tracker":{"$ref":"#/components/schemas/Tracker","description":"The member, as it now is, state included."},"added":{"type":"boolean","description":"False when the Tracker was already a member (200), or, with `collection_error`, when the Collection was deleted before the new Tracker could join (201)."},"created":{"type":"boolean","description":"True when this call started tracking the target."},"run":{"description":"The new Tracker's first cycle; null when nothing was created.","anyOf":[{"$ref":"#/components/schemas/Run"},{"type":"null"}]},"intelligence_run":{"description":"The Run analysing the first cycle's new Ads (an advertiser Tracker with `intelligence: true`); null otherwise.","anyOf":[{"$ref":"#/components/schemas/Run"},{"type":"null"}]},"collection_error":{"$ref":"#/components/schemas/Problem","description":"Only when the Collection was deleted while the new Tracker's first cycle ran: the Tracker stands, paid for, in no Collection."}},"required":["tracker","added","created","run","intelligence_run"]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"collection":{"id":"col_7d20e1b5c4","name":"Competitors","kind":"creator","member_count":4,"created_at":"2026-09-02T09:14:40.221Z","updated_at":"2026-09-02T09:14:40.221Z"},"tracker":{"id":"trk_4b1e90c7aa","kind":"creator","platform":"tiktok","target":"someone","intelligence":true,"state":"active","last_cycle_at":"2026-09-08T04:00:11.402Z","last_run_id":"run_c07a41bb92","created_at":"2026-09-01T11:20:03.118Z","updated_at":"2026-09-08T04:00:11.402Z"},"added":false,"created":false,"run":null,"intelligence_run":null}},"estimate":{"summary":"With `estimate=true`: the price of the first cycle, nothing created or charged.","value":{"estimate_credits":6,"cached":false,"already_tracking":false,"tracker_id":null,"per_cycle":true}}}}}},"201":{"description":"`{ collection, tracker, added: true, created, run, intelligence_run }` — `run` is the first cycle when this call started tracking the target; `intelligence_run` the Run analysing an opted-in advertiser's new Ads, or null. If the Collection was deleted while that first cycle ran, the paid Tracker still stands: `{ tracker, added: false, created: true, run, collection_error }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"collection":{"$ref":"#/components/schemas/Collection","description":"Absent only with `collection_error`."},"tracker":{"$ref":"#/components/schemas/Tracker","description":"The member, as it now is, state included."},"added":{"type":"boolean","description":"False when the Tracker was already a member (200), or, with `collection_error`, when the Collection was deleted before the new Tracker could join (201)."},"created":{"type":"boolean","description":"True when this call started tracking the target."},"run":{"description":"The new Tracker's first cycle; null when nothing was created.","anyOf":[{"$ref":"#/components/schemas/Run"},{"type":"null"}]},"intelligence_run":{"description":"The Run analysing the first cycle's new Ads (an advertiser Tracker with `intelligence: true`); null otherwise.","anyOf":[{"$ref":"#/components/schemas/Run"},{"type":"null"}]},"collection_error":{"$ref":"#/components/schemas/Problem","description":"Only when the Collection was deleted while the new Tracker's first cycle ran: the Tracker stands, paid for, in no Collection."}},"required":["tracker","added","created","run","intelligence_run"]},"example":{"collection":{"id":"col_7d20e1b5c4","name":"Competitors","kind":"creator","member_count":4,"created_at":"2026-09-02T09:14:40.221Z","updated_at":"2026-09-02T09:14:40.221Z"},"tracker":{"id":"trk_4b1e90c7aa","kind":"creator","platform":"tiktok","target":"someone","intelligence":true,"state":"paused","last_cycle_at":"2026-09-08T04:00:11.402Z","last_run_id":"run_c07a41bb92","created_at":"2026-09-01T11:20:03.118Z","updated_at":"2026-09-08T04:00:11.402Z"},"added":true,"created":false,"run":null,"intelligence_run":null}}}},"400":{"description":"`invalid_request` — a malformed body. Or `unsupported_platform`: an unknown platform, or a creator on YouTube (creator Trackers cycle on TikTok, Instagram and Facebook). Nothing is created or charged. Or: `kind_deprecated` — a target in a video Collection: no new Video Trackers. Add a Video Tracker you already have by `tracker_id`. Track the Creator, a Hashtag or a Sound instead. Nothing is created or charged.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"unsupported_platform":{"summary":"`invalid_request` — a malformed body. Or `unsupported_platform`: an unknown platform, or a creator on YouTube (creator Trackers cycle on TikTok, Instagram and Facebook). Nothing is created or charged.","value":{"type":"https://www.shortsintel.com/docs/reference/errors/unsupported_platform","title":"Unsupported platform","status":400,"code":"unsupported_platform","detail":"Tracking a creator on youtube is not available yet. Creator Trackers are supported on: tiktok, instagram, facebook.","retryable":false,"action":"Use a platform this operation lists as supported."}},"kind_deprecated":{"summary":"`kind_deprecated` — a target in a video Collection: no new Video Trackers. Add a Video Tracker you already have by `tracker_id`. Track the Creator, a Hashtag or a Sound instead. Nothing is created or charged.","value":{"type":"https://www.shortsintel.com/docs/reference/errors/kind_deprecated","title":"Kind deprecated","status":400,"code":"kind_deprecated","detail":"Video Trackers and Collections can no longer be created. Track the Creator, a Hashtag or a Sound instead: their cycles re-snapshot the Videos they find every day.","retryable":false,"action":"Track the Creator, a Hashtag or a Sound instead of a Video.","supported_kinds":["creator","hashtag","sound","advertiser","keyword"]}}}}}},"401":{"$ref":"#/components/responses/Problem401"},"402":{"description":"`insufficient_balance` — a new Tracker's first cycle is not covered. Nothing is created.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/insufficient_balance","title":"Insufficient balance","status":402,"code":"insufficient_balance","detail":"Your balance is 0 Credits and this operation needs 6 Credits. Nothing was charged.","retryable":false,"action":"Tell the Customer to top up the Balance, then repeat the same request.","balance_credits":0,"required_credits":6}}}},"404":{"description":"`not_found`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/not_found","title":"Not found","status":404,"code":"not_found","detail":"No Collection, or no Tracker, with that id for this Customer; or the Platform has no such creator. Nothing is created or charged.","retryable":false,"action":"Check the id or handle; list your resources to find the right one."}}}},"409":{"description":"`collection_kind_mismatch` — the Tracker is not of the Collection's kind. Or: `tracker_limit_exceeded` at 100 active Trackers. Paused Trackers do not count.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"collection_kind_mismatch":{"summary":"`collection_kind_mismatch` — the Tracker is not of the Collection's kind.","value":{"type":"https://www.shortsintel.com/docs/reference/errors/collection_kind_mismatch","title":"Collection kind mismatch","status":409,"code":"collection_kind_mismatch","detail":"\"Competitors\" is a Collection of creator Trackers and cannot hold a video.","retryable":false,"action":"Add this target to a Collection of its own kind.","collection_kind":"creator","kind":"video"}},"tracker_limit_exceeded":{"summary":"`tracker_limit_exceeded` at 100 active Trackers. Paused Trackers do not count.","value":{"type":"https://www.shortsintel.com/docs/reference/errors/tracker_limit_exceeded","title":"Tracker limit exceeded","status":409,"code":"tracker_limit_exceeded","detail":"You already have 100 active Trackers. Pause one before starting another.","retryable":false,"action":"Pause or delete a Tracker, then retry.","limit":100,"active":100}}}}}},"429":{"$ref":"#/components/responses/Problem429_2"}},"x-price":{"credits":0,"unit":"call","max_credits":null}}},"/collections/{id}/changes":{"get":{"operationId":"listCollectionChanges","summary":"Read members' change reports","description":"Every member's Change Reports in one feed, newest first, each naming its member's platform and target. A Tracker in several Collections appears in each one's feed. Quiet cycles are absent by design. `include_off_focus=true` lists each Focus report's hidden Videos, as on a Tracker's changes.\n\n**Price:** Free.","tags":["Collections"],"parameters":[{"name":"id","in":"path","required":true,"description":"Collection id.","schema":{"type":"string"}},{"name":"since","in":"query","required":false,"description":"Only reports written after this ISO 8601 instant.","schema":{"type":"string","format":"date-time"}},{"$ref":"#/components/parameters/Limit_5"},{"$ref":"#/components/parameters/Cursor"},{"$ref":"#/components/parameters/IncludeOffFocus"}],"responses":{"200":{"description":"`{ items, next_cursor }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"tracker_id":{"type":"string"},"run_id":{"type":["string","null"]},"cycle_key":{"type":"string","description":"One report per Tracker per cycle."},"triggers":{"type":"array","items":{"type":"string"},"description":"Creator: `new_videos`, `followers`, `outlier`, `velocity`, `became_ad`, `bio_link_changed`, `verified_changed`. Hashtag and Keyword: `median_views`, `new_top_videos`. Sound: `video_count`, `new_top_video`. Advertiser: `new_ads`, `stopped_ads`, `variant_growth`, `new_countries_or_placements`."},"changes":{"description":"The before/after numbers behind the triggers."},"summary":{"type":["string","null"]},"created_at":{"type":"string"},"coverage":{"type":"string","enum":["partial"],"description":"A Keyword Tracker's on Instagram or Facebook: their search is a best-effort index, so the numbers are too. Absent otherwise."},"off_focus_count":{"type":"integer","description":"A Tracker with a Focus only: how many off-focus Videos `changes` left out, including those hidden by quiet cycles since the previous report. `changes` lists in-focus and unjudged Videos; stats stay full-Sample. Absent without a Focus."},"off_focus_videos":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":["string","null"]},"focus":{"type":"object","properties":{"verdict":{"type":"string","enum":["in_focus","off_focus","unjudged"],"description":"`unjudged`: the Video could not be judged (or is not judged yet) and is shown."},"reason":{"type":"string"}},"required":["verdict","reason"]}},"required":["id","url","focus"]},"description":"Only with `include_off_focus=true`, on a report with a Focus: the Videos `off_focus_count` counts, each with `focus: { verdict, reason }`."},"platform":{"type":"string","description":"The member's Platform."},"target":{"type":"string","description":"The member's handle, video id, tag or sound id."}},"required":["id","tracker_id","run_id","cycle_key","triggers","summary","created_at","platform","target"],"description":"A member's Change Report, naming the member inline."}}},"required":["items"]}]},"example":{"items":[{"id":"chg_2ac910f4d8","tracker_id":"trk_4b1e90c7aa","run_id":"run_c07a41bb92","cycle_key":"tiktok:creator:someone:2026-09-08","triggers":["new_videos","outlier"],"changes":{"new_videos":{"before":61,"after":62,"count":1,"videos":[{"id":"7300000000000000000","url":"https://www.tiktok.com/@someone/video/7300000000000000000","posted_at":"2026-09-05T06:32:11.000Z","views":1284000}]},"outliers":[{"id":"7300000000000000000","url":"https://www.tiktok.com/@someone/video/7300000000000000000","views":1284000,"outlier":4.21,"threshold":3}]},"summary":"1 new video, 1 outlier at 4.2x median","created_at":"2026-09-08T04:00:11.402Z","platform":"tiktok","target":"someone"}],"next_cursor":null}}}},"400":{"description":"`invalid_request` for a `cursor` that is not a `next_cursor` this API issued. Nothing is charged. Or: `invalid_request` — a `since` that is not an ISO 8601 time, a bad `limit`, or a `cursor` that is not a previous `next_cursor`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"invalid_request":{"summary":"`invalid_request` — a `since` that is not an ISO 8601 time, a bad `limit`, or a `cursor` that is not a previous `next_cursor`.","value":{"type":"https://www.shortsintel.com/docs/reference/errors/invalid_request","title":"Invalid request","status":400,"code":"invalid_request","detail":"`since` must be an ISO 8601 date-time.","retryable":false,"action":"Fix the field named in `detail`, then send the corrected request."}}}}}},"401":{"$ref":"#/components/responses/Problem401"},"404":{"description":"`not_found` — no Collection with that id for this Customer.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/not_found","title":"Not found","status":404,"code":"not_found","detail":"No such resource for this Customer.","retryable":false,"action":"Check the id or handle; list your resources to find the right one."}}}}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/collections/{id}/members/{tracker_id}":{"delete":{"operationId":"removeCollectionMember","summary":"Remove a member","description":"Takes the Tracker out of the Collection. The Tracker itself is untouched: same state, same cycles, same other Collections. Delete the Tracker to stop tracking.\n\n**Price:** Free.","tags":["Collections"],"parameters":[{"name":"id","in":"path","required":true,"description":"Collection id.","schema":{"type":"string"}},{"name":"tracker_id","in":"path","required":true,"description":"The member Tracker's id.","schema":{"type":"string"}}],"responses":{"200":{"description":"`{ collection, tracker }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"collection":{"$ref":"#/components/schemas/Collection"},"tracker":{"$ref":"#/components/schemas/Tracker","description":"Untouched by the removal."}},"required":["collection","tracker"]},"example":{"collection":{"id":"col_7d20e1b5c4","name":"Competitors","kind":"creator","member_count":3,"created_at":"2026-09-02T09:14:40.221Z","updated_at":"2026-09-02T09:14:40.221Z"},"tracker":{"id":"trk_4b1e90c7aa","kind":"creator","platform":"tiktok","target":"someone","intelligence":true,"state":"active","last_cycle_at":"2026-09-08T04:00:11.402Z","last_run_id":"run_c07a41bb92","created_at":"2026-09-01T11:20:03.118Z","updated_at":"2026-09-08T04:00:11.402Z"}}}}},"401":{"$ref":"#/components/responses/Problem401"},"404":{"description":"`not_found`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/not_found","title":"Not found","status":404,"code":"not_found","detail":"That Tracker is not in this Collection.","retryable":false,"action":"Check the id or handle; list your resources to find the right one."}}}}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/collections/{id}/actions":{"post":{"operationId":"actOnCollection","summary":"Act on every member","description":"Pause, resume, refresh or switch analysis for every live member Tracker at once.\n\n- **Shared members:** a Collection holds no state, so the action writes through to each Tracker, for all its Collections. Pausing \"Competitors\" also pauses a creator you track for \"Influencers\".\n- **Finding them:** every answer lists them in `trackers_in_other_collections` (for `refresh`, in the Run result and the estimate).\n- **Free actions:** `pause`, `resume` and `intelligence` are free, answer at once and are not Runs.\n- **Active limit:** `resume` resumes nothing when the batch would pass the active-Tracker limit.\n- **Refresh:** `refresh` runs every member's cycle now, paused ones included, as one Run with one item per member.\n- **Refresh failures:** failed members are uncharged, some failing makes the Run partial, all failing makes it failed and free.\n\n**Price:** Free, except `refresh`: one cycle per member refreshed, 6 credits for a creator, 30 credits for an advertiser, plus 20 credits per new video on members with analysis on.","tags":["Collections"],"parameters":[{"name":"id","in":"path","required":true,"description":"Collection id.","schema":{"type":"string"}},{"name":"wait","in":"query","required":false,"description":"Seconds to hold the response open before handing back a running Run to poll. Default 30, max 120. A POST may send it in the body instead; different values in both places are a 400. Only `refresh` waits; the other actions answer at once.","schema":{"type":"integer","minimum":0,"maximum":120,"default":30}},{"$ref":"#/components/parameters/Estimate"},{"$ref":"#/components/parameters/MaxCredits"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["pause","resume","refresh","intelligence"],"description":"`pause` or `resume` every member; `refresh` runs every member's cycle now (a paid Run); `intelligence` switches analysis of new videos on or off for every member."},"intelligence":{"type":"boolean","description":"Required with `intelligence`: true switches analysis on, false off."},"wait":{"type":"number","minimum":0,"maximum":120,"default":30,"description":"Seconds to hold the response open before returning a running Run to poll. Default 30, max 120."},"estimate":{"type":"boolean","description":"`true` returns `{ estimate_credits, cached }`, creates no Run and charges nothing."}},"required":["action"],"additionalProperties":false}}}},"responses":{"200":{"description":"`pause`, `resume`, `intelligence`: `{ action, collection, trackers, changed_tracker_ids, trackers_in_other_collections }`. `refresh`: the Run envelope `{ run, result, trackers_in_other_collections }`; with `estimate=true`, `{ estimate_credits, trackers, per_tracker_credits, trackers_in_other_collections }`. With `estimate=true` the free actions answer `{ estimate_credits: 0, cached, trackers_in_other_collections }` and change nothing: the way to see what a pause would reach before making it.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"action":{"type":"string","enum":["pause","resume","intelligence"]},"collection":{"$ref":"#/components/schemas/Collection"},"trackers":{"type":"array","items":{"$ref":"#/components/schemas/Tracker"},"description":"Every live member, as it now is."},"changed_tracker_ids":{"type":"array","items":{"type":"string"},"description":"Members this call changed. One already in the asked-for state is left alone."},"trackers_in_other_collections":{"type":"array","items":{"type":"object","properties":{"tracker_id":{"type":"string"},"platform":{"type":"string"},"target":{"type":"string"},"state":{"type":"string","enum":["active","paused"]},"collections":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"description":"The other Collections it sits in. This one is left out."}},"required":["tracker_id","platform","target","state","collections"],"description":"An affected member that also sits in other Collections: the action changed it for those too."}}},"required":["action","collection","trackers","changed_tracker_ids","trackers_in_other_collections"]},{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{"type":"object","properties":{"collection_id":{"type":"string"},"collection_name":{"type":"string"},"requested":{"type":"integer","description":"Live members when the refresh started."},"refreshed":{"type":"integer","description":"Members whose cycle completed, and the only ones charged."},"failed":{"type":"integer"},"change_reports":{"type":"integer","description":"Change Reports the refresh produced; read them per Tracker."},"trackers_in_other_collections":{"type":"array","items":{"type":"object","properties":{"tracker_id":{"type":"string"},"platform":{"type":"string"},"target":{"type":"string"},"state":{"type":"string","enum":["active","paused"]},"collections":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"description":"The other Collections it sits in. This one is left out."}},"required":["tracker_id","platform","target","state","collections"],"description":"An affected member that also sits in other Collections: the action changed it for those too."}},"waived_credits":{"type":"number","description":"Only when analysis surcharges passed the Balance: the part not charged. The charge stops at the Balance."}},"required":["collection_id","collection_name","requested","refreshed","failed","change_reports","trackers_in_other_collections"],"description":"What a Collection refresh did. One item per member at `GET /v1/runs/{id}/items`."},"trackers_in_other_collections":{"type":"array","items":{"type":"object","properties":{"tracker_id":{"type":"string"},"platform":{"type":"string"},"target":{"type":"string"},"state":{"type":"string","enum":["active","paused"]},"collections":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"description":"The other Collections it sits in. This one is left out."}},"required":["tracker_id","platform","target","state","collections"],"description":"An affected member that also sits in other Collections: the action changed it for those too."}}},"required":["result","trackers_in_other_collections"]}]},{"$ref":"#/components/schemas/Estimate"}]},"examples":{"default":{"summary":"The operation's own result.","value":{"action":"pause","collection":{"id":"col_7d20e1b5c4","name":"Competitors","kind":"creator","member_count":4,"created_at":"2026-09-02T09:14:40.221Z","updated_at":"2026-09-02T09:14:40.221Z"},"trackers":[{"id":"trk_4b1e90c7aa","kind":"creator","platform":"tiktok","target":"someone","intelligence":true,"state":"paused","last_cycle_at":"2026-09-08T04:00:11.402Z","last_run_id":"run_c07a41bb92","created_at":"2026-09-01T11:20:03.118Z","updated_at":"2026-09-08T04:00:11.402Z"}],"changed_tracker_ids":["trk_4b1e90c7aa"],"trackers_in_other_collections":[{"tracker_id":"trk_4b1e90c7aa","platform":"tiktok","target":"someone","state":"paused","collections":[{"id":"col_51b0a9e2f7","name":"Influencers"}]}]}},"refresh":{"summary":"`refresh`, finished inside the wait budget. Partial: one of four members could not be fetched and was not charged.","value":{"run":{"id":"run_8f2c1ad04b","kind":"collection_refresh","status":"partial","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":150,"list_price_credits":150,"cached":false},"result":{"collection_id":"col_7d20e1b5c4","collection_name":"Competitors","requested":4,"refreshed":3,"failed":1,"change_reports":1,"trackers_in_other_collections":[{"tracker_id":"trk_4b1e90c7aa","platform":"tiktok","target":"someone","state":"active","collections":[{"id":"col_51b0a9e2f7","name":"Influencers"}]}]},"trackers_in_other_collections":[{"tracker_id":"trk_4b1e90c7aa","platform":"tiktok","target":"someone","state":"active","collections":[{"id":"col_51b0a9e2f7","name":"Influencers"}]}]}},"estimate":{"summary":"`refresh` with `estimate=true`: the price, no Run, no charge.","value":{"estimate_credits":24,"cached":false,"trackers":4,"per_tracker_credits":6,"trackers_with_analysis":0,"note":"A member that cannot be refreshed is not charged, so the final charge is at or below this quote.","trackers_in_other_collections":[{"tracker_id":"trk_4b1e90c7aa","platform":"tiktok","target":"someone","state":"active","collections":[{"id":"col_51b0a9e2f7","name":"Influencers"}]}]}}}}}},"202":{"description":"`refresh` still running: `{ run, trackers_in_other_collections }`. Poll `GET /v1/runs/{id}`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"description":"Still running. Poll `poll_url` (`GET /v1/runs/{id}`), waiting the 202's `Retry-After` seconds between polls.","allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"poll_url":{"type":"string","format":"uri","description":"Absolute URL of `GET /v1/runs/{id}` for this Run, the body's copy of the 202's `Location` header for callers that never see headers (MCP). Present only while the Run is `running`."},"trackers_in_other_collections":{"type":"array","items":{"type":"object","properties":{"tracker_id":{"type":"string"},"platform":{"type":"string"},"target":{"type":"string"},"state":{"type":"string","enum":["active","paused"]},"collections":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"description":"The other Collections it sits in. This one is left out."}},"required":["tracker_id","platform","target","state","collections"],"description":"An affected member that also sits in other Collections: the action changed it for those too."}}},"required":["poll_url","trackers_in_other_collections"]}]},"example":{"run":{"id":"run_8f2c1ad04b","kind":"collection_refresh","status":"running","created_at":"2026-09-08T09:14:02.418Z","completed_at":null,"charge_credits":0,"list_price_credits":0,"cached":false},"poll_url":"https://www.shortsintel.com/v1/runs/run_8f2c1ad04b","trackers_in_other_collections":[{"tracker_id":"trk_4b1e90c7aa","platform":"tiktok","target":"someone","state":"active","collections":[{"id":"col_51b0a9e2f7","name":"Influencers"}]}]}}}},"400":{"description":"`invalid_request` — an unknown `action`, `intelligence` without `intelligence: true|false`, or `refresh` on a Collection with no members.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/invalid_request","title":"Invalid request","status":400,"code":"invalid_request","detail":"The Collection \"Competitors\" has no members to refresh.","retryable":false,"action":"Fix the field named in `detail`, then send the corrected request."}}}},"401":{"$ref":"#/components/responses/Problem401"},"402":{"description":"`insufficient_balance` — `refresh` only, checked against one cycle per member before any work starts.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/insufficient_balance","title":"Insufficient balance","status":402,"code":"insufficient_balance","detail":"Your balance is 0 Credits and this operation needs 24 Credits. Nothing was charged.","retryable":false,"action":"Tell the Customer to top up the Balance, then repeat the same request.","balance_credits":0,"required_credits":24}}}},"404":{"$ref":"#/components/responses/Problem404_4"},"409":{"description":"`tracker_limit_exceeded` — `resume` would pass the active-Tracker limit. Nothing is resumed. Or: `idempotency_conflict` — the same Idempotency-Key with a different payload.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"examples":{"tracker_limit_exceeded":{"summary":"`tracker_limit_exceeded` — `resume` would pass the active-Tracker limit. Nothing is resumed.","value":{"type":"https://www.shortsintel.com/docs/reference/errors/tracker_limit_exceeded","title":"Tracker limit exceeded","status":409,"code":"tracker_limit_exceeded","detail":"Resuming 4 Trackers would take this Customer to 102 active, the limit is 100. Nothing was resumed. Pause or delete some first.","retryable":false,"action":"Pause or delete a Tracker, then retry.","limit":100,"active":98,"requested":4}},"idempotency_conflict":{"summary":"`idempotency_conflict` — the same Idempotency-Key with a different payload.","value":{"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.","retryable":false,"action":"Resend the original payload with this key, or use a new key for the new payload.","run_id":"run_8f2c1ad04b"}}}}}},"422":{"description":"`unsupported_kind` — `refresh` on a Collection of a kind with no cycle yet (video). Nothing is run or charged.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/unsupported_kind","title":"Unsupported kind","status":422,"code":"unsupported_kind","detail":"Tracking video targets is not available yet. Creator tracking is supported today.","retryable":false,"action":"Do not repeat this request; nothing was charged. Use an operation that serves this kind.","supported_kinds":["creator"]}}}},"429":{"$ref":"#/components/responses/Problem429"}},"x-price":{"credits":0,"unit":"call","max_credits":null}}},"/runs":{"get":{"operationId":"listRuns","summary":"List your recent runs","description":"The Customer's recent Runs with their charges, newest first.\n\n**Price:** Free.","tags":["Runs"],"parameters":[{"$ref":"#/components/parameters/Limit_5"},{"$ref":"#/components/parameters/Cursor"},{"name":"status","in":"query","required":false,"description":"`running`, `completed`, `partial` or `failed`.","schema":{"type":"string","enum":["running","completed","partial","failed"]}},{"name":"kind","in":"query","required":false,"description":"Filter by run kind, as `run.kind` carries it: `video_lookup`, `video_search`, `video_intelligence`, `video_score`, `video_comments`, `video_comment_replies`, `creator_lookup`, `hashtag_lookup`, `keyword_lookup`, `sound_lookup`, `ads_search`, `ad_lookup`, `advertiser_lookup`, `research`, `research_refresh`, `tracker_cycle`, `collection_refresh`, `creator_videos`, `focus_judgment`.","schema":{"type":"string"}}],"responses":{"200":{"description":"`{ items, next_cursor }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Run"}}},"required":["items"]}]},"example":{"items":[{"id":"run_8f2c1ad04b","kind":"video_lookup","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":true},{"id":"run_c07a41bb92","kind":"research","status":"partial","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":1036,"list_price_credits":1036,"cached":false}],"next_cursor":null}}}},"400":{"$ref":"#/components/responses/Problem400_6"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/runs/{id}":{"get":{"operationId":"getRun","summary":"Poll or re-read a run","description":"Re-reads one Run in the same envelope the original call returned. This is both the poll endpoint for a Run that outlived its wait budget and the permanent free re-read; it never charges and never re-runs the work. Another Customer's Run id is a 404, not a 403.\n\n**Price:** Free.","tags":["Runs"],"parameters":[{"name":"id","in":"path","required":true,"description":"Run id.","schema":{"type":"string"}},{"name":"wait","in":"query","required":false,"description":"Seconds to hold the response while the Run runs: 200 once it settles, else 202 with poll hints. Default 0 (answer at once), max 120; out of range is a 400 `invalid_request`, as on a paid call.","schema":{"type":"integer","minimum":0,"maximum":120,"default":0}}],"responses":{"200":{"description":"`{ run, result }` for a completed or partial Run.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/RunEnvelope"},{"type":"object","properties":{"result":{}}}]},"example":{"run":{"id":"run_123","kind":"video_lookup","status":"completed","created_at":"2026-09-08T09:14:02.418Z","completed_at":"2026-09-08T09:14:04.930Z","charge_credits":5,"list_price_credits":5,"cached":false},"result":{"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","author":"someone","is_original":true},"creator":{"id":"cre_9d4b2a7f1c","handle":"someone","name":"Someone","follower_count":184300,"avatar_url":"https://p16-sign.tiktokcdn.com/obj/tos-avatar-someone.jpeg","verified":false},"region":"US","language":"en","title":null,"commerce":{"is_ad":false,"paid_partnership":null,"affiliate":null,"shop_url":null,"anchors":[{"kind":"54","label":"CapCut · Editing made easy"}]},"people":{"mentions":["coldplungeco"],"collaborators":[]},"location":null,"topics":{"keywords":[],"genre":null,"labels":["Fitness","Health"]},"chapters":null,"ai_generated":false,"snapshot":{"at":"2026-09-08T09:14:04.219Z","views":1284000,"likes":143200,"comments":2810,"shares":9040,"saves":21600},"scores":{"outlier":4.21,"outlier_p90":1.6,"percentile":95,"velocity":{"views_per_hour":6698.6,"window":"snapshot"},"reason":null,"baseline":{"median_views":305000,"p90_views":802000,"engagement_rate":0.1342,"posts_per_week":4.1,"sample":20,"confidence":"high","source":"videos","computed_at":"2026-09-08T09:14:03.902Z","stale":false}}}}}}},"202":{"description":"`{ run }` while the Run is still running.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"Location":{"$ref":"#/components/headers/PollLocation"},"Retry-After":{"$ref":"#/components/headers/PollRetryAfter"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningEnvelope"},"example":{"run":{"id":"run_123","kind":"video_lookup","status":"running","created_at":"2026-09-08T09:14:02.418Z","completed_at":null,"charge_credits":0,"list_price_credits":0,"cached":false},"poll_url":"https://www.shortsintel.com/v1/runs/run_123"}}}},"401":{"$ref":"#/components/responses/Problem401"},"404":{"description":"`not_found`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/not_found","title":"Not found","status":404,"code":"not_found","detail":"No Run with that id for this Customer.","retryable":false,"action":"Check the id or handle; list your resources to find the right one."}}}},"502":{"description":"A Run that itself failed is answered as `application/problem+json` with its problem's status (404, 502, ...), the problem members beside the unchanged Run envelope.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"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.","retryable":true,"action":"Retry with a backoff; nothing was charged.","run":{"id":"run_123","kind":"video_lookup","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}}}}}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/runs/{id}/items":{"get":{"operationId":"listRunItems","summary":"List what a run delivered","description":"The items a Run delivered, each with its own status, charge and — when it failed — the problem body explaining why. This is how a `partial` Run says what did and did not arrive.\n\n**Price:** Free: the charge happened once, when the work did.","tags":["Runs"],"parameters":[{"name":"id","in":"path","required":true,"description":"Run id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit_5"},{"$ref":"#/components/parameters/Cursor"},{"name":"type","in":"query","required":false,"description":"`videos`, `creators`, `hashtags`, `sounds` or `ads` (singular accepted too). A Meta ad search has one `ad` item per Ad delivered, with the Ad as its `payload`.","schema":{"type":"string","enum":["videos","creators","hashtags","sounds","ads"]}}],"responses":{"200":{"description":"`{ items, next_cursor }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","description":"`video`, `creator`, `hashtag` or `sound`."},"status":{"type":"string","enum":["pending","completed","failed"]},"position":{"type":"integer"},"charge_credits":{"type":"integer"},"cached":{"type":"boolean"},"video":{"type":["object","null"],"properties":{"platform":{"type":"string"},"id":{"type":"string"},"url":{"type":["string","null"]},"description":{"type":"string"}},"required":["platform","id","url","description"]},"subject_id":{"type":["string","null"]},"payload":{},"error":{"$ref":"#/components/schemas/Problem","description":"Why this one item failed."}},"required":["id","type","status","position","charge_credits","cached","video"]}}},"required":["items"]}]},"example":{"items":[{"id":"itm_0a91cc37e2","type":"video","status":"completed","position":0,"charge_credits":0,"cached":false,"video":{"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"}},{"id":"itm_0a91cc37f5","type":"video","status":"failed","position":37,"charge_credits":0,"cached":false,"video":{"platform":"tiktok","id":"7300000000000000077","url":"https://www.tiktok.com/@thirdone/video/7300000000000000077","description":"cold plunge fails compilation"},"error":{"type":"https://www.shortsintel.com/docs/reference/errors/media_unavailable","title":"Media unavailable","status":502,"code":"media_unavailable","detail":"The video file could not be fetched, so it was not analysed and not charged for.","retryable":false,"action":"Tell the Customer the video is deleted, private or blocked; pick another."}}],"next_cursor":"eyJwIjozOH0"}}}},"400":{"$ref":"#/components/responses/Problem400_6"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/account/balance":{"get":{"operationId":"getBalance","summary":"Read your Credit balance","description":"The Customer's prepaid Balance in Credits, and each unexpired Grant (such as the Starter Grant) with its remaining Credits and expiry. Grants are part of the Balance and are spent first.\n\n**Price:** Free.","tags":["Account"],"responses":{"200":{"description":"`{ balance_credits, grants }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"balance_credits":{"type":"integer","description":"The spendable Balance in Credits: active Grants included, an expired Grant's leftover never."},"grants":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string","enum":["starter","bonus"],"description":"`starter` for the Starter Grant, `bonus` for any other."},"amount_credits":{"type":"integer","description":"Credits granted."},"remaining_credits":{"type":"integer","description":"Credits of this Grant not yet spent."},"expires_at":{"type":"string","description":"When any remainder leaves the Balance."}},"required":["source","amount_credits","remaining_credits","expires_at"]},"description":"Unexpired Grants with Credits left, soonest expiry first. Their Credits are part of the Balance and are spent before purchased Credits, which never expire."}},"required":["balance_credits","grants"]},"example":{"balance_credits":42310,"grants":[{"source":"starter","amount_credits":100,"remaining_credits":64,"expires_at":"2026-10-01T00:00:00.000Z"}]}}}},"401":{"$ref":"#/components/responses/Problem401"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/account/usage":{"get":{"operationId":"getUsage","summary":"Read your spend log","description":"The spend log, newest first: one row per charged Run (its `charge` ledger entry). Top-ups and other credits are not spend and are not listed. The Balance is `GET /v1/account/balance`.\n\nEach row is `{ id, kind, amount_credits, balance_after_credits, created_at, run }`.\n\n- `amount_credits`: signed as stored, so a charge is negative.\n- `balance_after_credits`: the Balance once it applied.\n- `run`: `{ id, kind, status, charge_credits, list_price_credits, cached }`, to audit list against charged price per Run.\n- `total_charged_credits`: every charge on the account, not just this page.\n- **Amounts:** whole numbers of Credits.\n\n**Price:** Free.","tags":["Account"],"parameters":[{"$ref":"#/components/parameters/Limit_5"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"`{ items, next_cursor, total_charged_credits }`, one item per charge with the Run behind it.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","description":"Always `charge`: top-ups and other credits are not spend."},"amount_credits":{"type":"integer","description":"Signed as stored: a charge is negative."},"balance_after_credits":{"type":"integer"},"created_at":{"type":"string"},"run":{"type":["object","null"],"properties":{"id":{"type":"string"},"kind":{"type":"string"},"status":{"type":"string"},"charge_credits":{"type":"integer"},"list_price_credits":{"type":"integer"},"cached":{"type":"boolean"}},"required":["id","kind","status","charge_credits","list_price_credits","cached"]}},"required":["id","kind","amount_credits","balance_after_credits","created_at","run"]}},"next_cursor":{"type":["string","null"]},"total_charged_credits":{"type":"integer","description":"Every charge on the account, not just this page."}},"required":["items","next_cursor","total_charged_credits"]},"example":{"items":[{"id":"led_71b0c93f4a","kind":"charge","amount_credits":-3,"balance_after_credits":42310,"created_at":"2026-09-08T09:14:04.930Z","run":{"id":"run_8f2c1ad04b","kind":"video_lookup","status":"completed","charge_credits":3,"list_price_credits":3,"cached":true}},{"id":"led_71b0c93e18","kind":"charge","amount_credits":-6,"balance_after_credits":42313,"created_at":"2026-09-07T16:40:12.207Z","run":{"id":"run_7d1e0bc3a2","kind":"creator_lookup","status":"completed","charge_credits":6,"list_price_credits":6,"cached":false}}],"next_cursor":null,"total_charged_credits":7689}}}},"400":{"description":"`invalid_request` for a `limit` out of range or a `cursor` this API did not issue.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/invalid_request","title":"Invalid request","status":400,"code":"invalid_request","detail":"`cursor` is not a cursor this API issued. Pass back the `next_cursor` from the previous page.","retryable":false,"action":"Fix the field named in `detail`, then send the corrected request."}}}},"401":{"$ref":"#/components/responses/Problem401"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/webhooks":{"post":{"operationId":"createWebhook","summary":"Register a webhook endpoint","description":"Registers an endpoint and immediately proves it with a signed `webhook.test` event.\n\n- **Status:** `active` when the test got a 2xx, else `failed`. A failed endpoint receives no events until deleted and re-registered.\n- **Secret:** the `secret` appears in this response and nowhere else, ever.\n- **Access:** Owner or admin only: a MEMBER's key or connection gets 403 `forbidden`.\n\n**Price:** Free.","tags":["Webhooks"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"HTTPS only; private ranges are refused."},"description":{"type":"string","description":"A label of your own for the endpoint, returned on reads; trimmed and cut to 200 characters. Events do not carry it."}},"required":["url"],"additionalProperties":false}}}},"responses":{"201":{"description":"`{ webhook, secret, test_delivery }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"webhook":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"status":{"type":"string","enum":["pending","active","failed","disabled"]},"description":{"type":["string","null"]},"secret_prefix":{"type":"string","description":"The first characters of the signing secret, to tell two apart."},"previous_secret_expires_at":{"type":["string","null"]},"created_at":{"type":"string"},"activated_at":{"type":["string","null"]},"last_delivery_at":{"type":["string","null"]}},"required":["id","url","status","description","secret_prefix","previous_secret_expires_at","created_at","activated_at","last_delivery_at"]},"secret":{"type":"string","description":"Shown once, here and nowhere else. Store it now."},"test_delivery":{"type":"object","properties":{"id":{"type":"string"},"event_id":{"type":"string","description":"Stable across replays, so a receiver can de-duplicate."},"event_type":{"type":"string","enum":["run.completed","tracker.changed","webhook.test"]},"status":{"type":"string","enum":["pending","delivered","failed"]},"attempts":{"type":"integer"},"response_status":{"type":["integer","null"]},"error":{"type":["string","null"]},"run_id":{"type":["string","null"]},"tracker_id":{"type":["string","null"]},"change_report_id":{"type":["string","null"]},"replay_of":{"type":["string","null"]},"created_at":{"type":"string"},"last_attempt_at":{"type":["string","null"]},"delivered_at":{"type":["string","null"]},"failed_at":{"type":["string","null"]}},"required":["id","event_id","event_type","status","attempts","response_status","error","run_id","tracker_id","change_report_id","replay_of","created_at","last_attempt_at","delivered_at","failed_at"],"description":"The signed `webhook.test` event that decided activation."}},"required":["webhook","secret","test_delivery"]},"example":{"webhook":{"id":"whe_6d2f10ab44","url":"https://hooks.example.com/shortsintel","status":"active","description":"production receiver","secret_prefix":"whsec_a1b2c3","previous_secret_expires_at":null,"created_at":"2026-09-08T09:14:02.418Z","activated_at":"2026-09-08T09:14:03.006Z","last_delivery_at":"2026-09-08T09:14:03.006Z"},"secret":"whsec_9Qk3Tn7f2xLd0aZmVbYpRc8sHu6WjEg4","test_delivery":{"id":"whd_51c8b0f7e3","event_id":"evt_kZ8Qw3n1TfLd0aZmVbYpRc","event_type":"webhook.test","status":"delivered","attempts":1,"response_status":200,"error":null,"run_id":null,"tracker_id":null,"change_report_id":null,"replay_of":null,"created_at":"2026-09-08T09:14:02.911Z","last_attempt_at":"2026-09-08T09:14:03.006Z","delivered_at":"2026-09-08T09:14:03.006Z","failed_at":null}}}}},"400":{"description":"`invalid_request` for http, private ranges or an unresolvable host.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/invalid_request","title":"Invalid request","status":400,"code":"invalid_request","detail":"`url` must be https and must not resolve to a private address.","retryable":false,"action":"Fix the field named in `detail`, then send the corrected request."}}}},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"409":{"description":"`webhook_limit_exceeded` at 5 endpoints.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/webhook_limit_exceeded","title":"Webhook limit exceeded","status":409,"code":"webhook_limit_exceeded","detail":"You already have 5 endpoints. Delete one before registering another.","retryable":false,"action":"Delete an endpoint you no longer deliver to, then retry.","limit":5,"active":5}}}}},"x-price":{"credits":0,"unit":"call","max_credits":0}},"get":{"operationId":"listWebhooks","summary":"List webhook endpoints","description":"The Customer's endpoints, newest first. Secrets are never included.\n\n**Price:** Free.","tags":["Webhooks"],"parameters":[{"$ref":"#/components/parameters/Limit_5"},{"$ref":"#/components/parameters/Cursor"}],"responses":{"200":{"description":"`{ items, next_cursor }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"status":{"type":"string","enum":["pending","active","failed","disabled"]},"description":{"type":["string","null"]},"secret_prefix":{"type":"string","description":"The first characters of the signing secret, to tell two apart."},"previous_secret_expires_at":{"type":["string","null"]},"created_at":{"type":"string"},"activated_at":{"type":["string","null"]},"last_delivery_at":{"type":["string","null"]}},"required":["id","url","status","description","secret_prefix","previous_secret_expires_at","created_at","activated_at","last_delivery_at"]}}},"required":["items"]}]},"example":{"items":[{"id":"whe_6d2f10ab44","url":"https://hooks.example.com/shortsintel","status":"active","description":"production receiver","secret_prefix":"whsec_a1b2c3","previous_secret_expires_at":null,"created_at":"2026-09-08T09:14:02.418Z","activated_at":"2026-09-08T09:14:03.006Z","last_delivery_at":"2026-09-08T09:14:03.006Z"}],"next_cursor":null}}}},"400":{"$ref":"#/components/responses/Problem400_6"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/webhooks/{id}":{"get":{"operationId":"getWebhook","summary":"Get a webhook endpoint","description":"One endpoint.\n\n**Price:** Free.","tags":["Webhooks"],"parameters":[{"name":"id","in":"path","required":true,"description":"Webhook endpoint id.","schema":{"type":"string"}}],"responses":{"200":{"description":"`{ webhook }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"webhook":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"status":{"type":"string","enum":["pending","active","failed","disabled"]},"description":{"type":["string","null"]},"secret_prefix":{"type":"string","description":"The first characters of the signing secret, to tell two apart."},"previous_secret_expires_at":{"type":["string","null"]},"created_at":{"type":"string"},"activated_at":{"type":["string","null"]},"last_delivery_at":{"type":["string","null"]}},"required":["id","url","status","description","secret_prefix","previous_secret_expires_at","created_at","activated_at","last_delivery_at"]}},"required":["webhook"]},"example":{"webhook":{"id":"whe_6d2f10ab44","url":"https://hooks.example.com/shortsintel","status":"active","description":"production receiver","secret_prefix":"whsec_a1b2c3","previous_secret_expires_at":null,"created_at":"2026-09-08T09:14:02.418Z","activated_at":"2026-09-08T09:14:03.006Z","last_delivery_at":"2026-09-08T09:14:03.006Z"}}}}},"401":{"$ref":"#/components/responses/Problem401"},"404":{"description":"`not_found`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/not_found","title":"Not found","status":404,"code":"not_found","detail":"No webhook endpoint with that id for this Customer.","retryable":false,"action":"Check the id or handle; list your resources to find the right one."}}}}},"x-price":{"credits":0,"unit":"call","max_credits":0}},"delete":{"operationId":"deleteWebhook","summary":"Delete a webhook endpoint","description":"Stops delivering and frees a slot. The endpoint is tombstoned rather than removed, so the delivery history stays readable afterwards. Owner or admin only: a MEMBER's key or connection gets 403 `forbidden`.\n\n**Price:** Free.","tags":["Webhooks"],"parameters":[{"name":"id","in":"path","required":true,"description":"Webhook endpoint id.","schema":{"type":"string"}}],"responses":{"200":{"description":"`{ webhook }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"webhook":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"status":{"type":"string","enum":["pending","active","failed","disabled"]},"description":{"type":["string","null"]},"secret_prefix":{"type":"string","description":"The first characters of the signing secret, to tell two apart."},"previous_secret_expires_at":{"type":["string","null"]},"created_at":{"type":"string"},"activated_at":{"type":["string","null"]},"last_delivery_at":{"type":["string","null"]}},"required":["id","url","status","description","secret_prefix","previous_secret_expires_at","created_at","activated_at","last_delivery_at"]}},"required":["webhook"]},"example":{"webhook":{"id":"whe_6d2f10ab44","url":"https://hooks.example.com/shortsintel","status":"disabled","description":"production receiver","secret_prefix":"whsec_a1b2c3","previous_secret_expires_at":null,"created_at":"2026-09-08T09:14:02.418Z","activated_at":"2026-09-08T09:14:03.006Z","last_delivery_at":"2026-09-08T09:14:03.006Z"}}}}},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/webhooks/{id}/rotate":{"post":{"operationId":"rotateWebhookSecret","summary":"Rotate a signing secret","description":"Mints a new signing secret. The old one keeps working for 24 h.\n\n- **Overlap:** during that window every delivery is signed with both. The header carries two `v1=` values over the same `t` and body.\n- **Verifiers:** a verifier written the documented way (does any `v1` match?) needs no change at all.\n- **Access:** Owner or admin only: a MEMBER's key or connection gets 403 `forbidden`.\n\n**Price:** Free.","tags":["Webhooks"],"parameters":[{"name":"id","in":"path","required":true,"description":"Webhook endpoint id.","schema":{"type":"string"}}],"responses":{"200":{"description":"`{ webhook, secret, overlap_expires_at }` — `secret` shown once.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"webhook":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"status":{"type":"string","enum":["pending","active","failed","disabled"]},"description":{"type":["string","null"]},"secret_prefix":{"type":"string","description":"The first characters of the signing secret, to tell two apart."},"previous_secret_expires_at":{"type":["string","null"]},"created_at":{"type":"string"},"activated_at":{"type":["string","null"]},"last_delivery_at":{"type":["string","null"]}},"required":["id","url","status","description","secret_prefix","previous_secret_expires_at","created_at","activated_at","last_delivery_at"]},"secret":{"type":"string"},"overlap_expires_at":{"type":["string","null"],"description":"Until then, every delivery is signed with both secrets."}},"required":["webhook","secret","overlap_expires_at"]},"example":{"webhook":{"id":"whe_6d2f10ab44","url":"https://hooks.example.com/shortsintel","status":"active","description":"production receiver","secret_prefix":"whsec_d4e5f6","previous_secret_expires_at":"2026-09-09T09:14:02.418Z","created_at":"2026-09-08T09:14:02.418Z","activated_at":"2026-09-08T09:14:03.006Z","last_delivery_at":"2026-09-08T09:14:03.006Z"},"secret":"whsec_Lm2Rv8ZaQe5tYb1nXc7pKd3sWu9jHg6F","overlap_expires_at":"2026-09-09T09:14:02.418Z"}}}},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"409":{"description":"`webhook_rotation_in_progress` while a previous overlap is open.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/webhook_rotation_in_progress","title":"Webhook rotation in progress","status":409,"code":"webhook_rotation_in_progress","detail":"The previous secret is still valid. Rotate again after the overlap closes.","retryable":true,"action":"Wait until `overlap_expires_at`, then rotate again.","overlap_expires_at":"2026-09-09T09:14:02.418Z"}}}}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/webhooks/{id}/deliveries":{"get":{"operationId":"listWebhookDeliveries","summary":"List deliveries","description":"What we sent and how it went, newest first. The row carries the response status and error text but not the payload — the payload is reachable through the event's own `links`.\n\n**Price:** Free.","tags":["Webhooks"],"parameters":[{"name":"id","in":"path","required":true,"description":"Webhook endpoint id.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit_5"},{"$ref":"#/components/parameters/Cursor"},{"name":"status","in":"query","required":false,"description":"`pending`, `delivered` or `failed`.","schema":{"type":"string","enum":["pending","delivered","failed"]}}],"responses":{"200":{"description":"`{ items, next_cursor }`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"event_id":{"type":"string","description":"Stable across replays, so a receiver can de-duplicate."},"event_type":{"type":"string","enum":["run.completed","tracker.changed","webhook.test"]},"status":{"type":"string","enum":["pending","delivered","failed"]},"attempts":{"type":"integer"},"response_status":{"type":["integer","null"]},"error":{"type":["string","null"]},"run_id":{"type":["string","null"]},"tracker_id":{"type":["string","null"]},"change_report_id":{"type":["string","null"]},"replay_of":{"type":["string","null"]},"created_at":{"type":"string"},"last_attempt_at":{"type":["string","null"]},"delivered_at":{"type":["string","null"]},"failed_at":{"type":["string","null"]}},"required":["id","event_id","event_type","status","attempts","response_status","error","run_id","tracker_id","change_report_id","replay_of","created_at","last_attempt_at","delivered_at","failed_at"]}}},"required":["items"]}]},"example":{"items":[{"id":"whd_51c8b0f81a","event_id":"evt_pR4Vm8s2XqNb7cTfKdYw1E","event_type":"run.completed","status":"failed","attempts":3,"response_status":503,"error":"receiver returned 503","run_id":"run_8f2c1ad04b","tracker_id":null,"change_report_id":null,"replay_of":null,"created_at":"2026-09-08T09:14:02.911Z","last_attempt_at":"2026-09-08T09:14:03.006Z","delivered_at":null,"failed_at":"2026-09-08T09:41:10.220Z"},{"id":"whd_51c8b0f7e3","event_id":"evt_kZ8Qw3n1TfLd0aZmVbYpRc","event_type":"webhook.test","status":"delivered","attempts":1,"response_status":200,"error":null,"run_id":null,"tracker_id":null,"change_report_id":null,"replay_of":null,"created_at":"2026-09-08T09:14:02.911Z","last_attempt_at":"2026-09-08T09:14:03.006Z","delivered_at":"2026-09-08T09:14:03.006Z","failed_at":null}],"next_cursor":null}}}},"400":{"$ref":"#/components/responses/Problem400_6"},"401":{"$ref":"#/components/responses/Problem401"},"404":{"$ref":"#/components/responses/Problem404_2"}},"x-price":{"credits":0,"unit":"call","max_credits":0}}},"/webhooks/{id}/deliveries/{deliveryId}/replay":{"post":{"operationId":"replayWebhookDelivery","summary":"Replay a delivery","description":"Queues a new delivery row carrying the same event id and the same body.\n\n- **Duplicates:** the stable event id lets a receiver that did eventually process the original recognise the replay as a duplicate.\n- **Log:** the new row keeps \"we failed on Tuesday, you replayed on Thursday\" visible in the log.\n- **Access:** Owner or admin only: a MEMBER's key or connection gets 403 `forbidden`.\n\n**Price:** Free.","tags":["Webhooks"],"parameters":[{"name":"id","in":"path","required":true,"description":"Webhook endpoint id.","schema":{"type":"string"}},{"name":"deliveryId","in":"path","required":true,"description":"Delivery id to replay.","schema":{"type":"string"}}],"responses":{"202":{"description":"`{ delivery }` — queued.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/json":{"schema":{"type":"object","properties":{"delivery":{"type":"object","properties":{"id":{"type":"string"},"event_id":{"type":"string","description":"Stable across replays, so a receiver can de-duplicate."},"event_type":{"type":"string","enum":["run.completed","tracker.changed","webhook.test"]},"status":{"type":"string","enum":["pending","delivered","failed"]},"attempts":{"type":"integer"},"response_status":{"type":["integer","null"]},"error":{"type":["string","null"]},"run_id":{"type":["string","null"]},"tracker_id":{"type":["string","null"]},"change_report_id":{"type":["string","null"]},"replay_of":{"type":["string","null"]},"created_at":{"type":"string"},"last_attempt_at":{"type":["string","null"]},"delivered_at":{"type":["string","null"]},"failed_at":{"type":["string","null"]}},"required":["id","event_id","event_type","status","attempts","response_status","error","run_id","tracker_id","change_report_id","replay_of","created_at","last_attempt_at","delivered_at","failed_at"]}},"required":["delivery"]},"example":{"delivery":{"id":"whd_51c8b0f9c0","event_id":"evt_pR4Vm8s2XqNb7cTfKdYw1E","event_type":"run.completed","status":"pending","attempts":0,"response_status":null,"error":null,"run_id":"run_8f2c1ad04b","tracker_id":null,"change_report_id":null,"replay_of":"whd_51c8b0f81a","created_at":"2026-09-08T10:02:00.000Z","last_attempt_at":null,"delivered_at":null,"failed_at":null}}}}},"400":{"description":"`invalid_request` if the original is still being attempted, or the endpoint is not active.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/invalid_request","title":"Invalid request","status":400,"code":"invalid_request","detail":"That delivery is still being attempted. Wait for it to settle before replaying it.","retryable":false,"action":"Fix the field named in `detail`, then send the corrected request."}}}},"401":{"$ref":"#/components/responses/Problem401"},"403":{"$ref":"#/components/responses/Problem403"},"404":{"description":"`not_found`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/XRequestId"},"Cache-Control":{"$ref":"#/components/headers/CacheControl"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"},"example":{"type":"https://www.shortsintel.com/docs/reference/errors/not_found","title":"Not found","status":404,"code":"not_found","detail":"No such delivery on that endpoint.","retryable":false,"action":"Check the id or handle; list your resources to find the right one."}}}}},"x-price":{"credits":0,"unit":"call","max_credits":0}}}},"webhooks":{"run.completed":{"post":{"summary":"run.completed","description":"A Run reached a terminal state: completed, partial or failed. The type is `run.completed` for all three; branch on `status` in the payload.\n\n- Each delivery is a `POST` with `Content-Type: application/json` and `User-Agent: ShortsIntel-Webhooks/1`.\n- `X-ShortsIntel-Signature: t=<unix seconds>,v1=<hex>` — `v1` is HMAC-SHA256, keyed with your endpoint secret (`whsec_...`), over the string `\"<t>.<raw body>\"`. Verify against the raw bytes before parsing JSON.\n- Accept the delivery when ANY `v1` matches: during the 24 h after a secret rotation the header carries two `v1` values (new first), one per secret. Reject a `t` more than 300 s from your clock to refuse replays.\n- `X-ShortsIntel-Event-Id` repeats the event id and `X-ShortsIntel-Event-Type` the dotted event type, so you can route and dedupe without parsing the body.\n- The payload is thin: identifiers and links, never a Run's result. Fetch the detail with `links`.\n- Only a 2xx acknowledges. Each attempt has a 10 s timeout and redirects are not followed. Three attempts in all: immediately, then about 10 minutes and about 60 minutes after the first. After that the delivery is `failed` and can be replayed with `POST /v1/webhooks/{id}/deliveries/{deliveryId}/replay`, which re-sends the same event id and body with a fresh signature.","tags":["Webhooks"],"parameters":[{"name":"X-ShortsIntel-Signature","in":"header","required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 over \"<t>.<body>\">`; two `v1` during a rotation overlap.","schema":{"type":"string"}},{"name":"X-ShortsIntel-Event-Id","in":"header","required":true,"description":"The event id, `evt_...`, same as the body's `id`.","schema":{"type":"string"}},{"name":"X-ShortsIntel-Event-Type","in":"header","required":true,"description":"The dotted event type, same as the body's `type`.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"},"example":{"id":"evt_Xq3bN7tLw2RkV9pMdC4sYe","type":"run.completed","created_at":"2026-09-12T08:00:41.000Z","run_id":"run_c07a41bb92","kind":"research","status":"completed","charge_credits":120,"tracker_id":null,"change_report_id":null,"links":{"run":"https://www.shortsintel.com/v1/runs/run_c07a41bb92"}}}}},"responses":{"2XX":{"description":"Acknowledged. Anything else is retried."}}}},"tracker.changed":{"post":{"summary":"tracker.changed","description":"A Tracker cycle produced a Change Report. Quiet cycles send nothing. The report's `triggers` name what tripped: on a Creator Tracker `new_videos`, `followers`, `outlier`, `velocity`, `became_ad`, `bio_link_changed` and `verified_changed`; on Hashtag and Keyword Trackers `median_views` and `new_top_videos`; on Sound Trackers `video_count` and `new_top_video`; on Advertiser Trackers `new_ads`, `stopped_ads`, `variant_growth`, `new_countries_or_placements` and, on TikTok, `reach_growth`.\n\n- Each delivery is a `POST` with `Content-Type: application/json` and `User-Agent: ShortsIntel-Webhooks/1`.\n- `X-ShortsIntel-Signature: t=<unix seconds>,v1=<hex>` — `v1` is HMAC-SHA256, keyed with your endpoint secret (`whsec_...`), over the string `\"<t>.<raw body>\"`. Verify against the raw bytes before parsing JSON.\n- Accept the delivery when ANY `v1` matches: during the 24 h after a secret rotation the header carries two `v1` values (new first), one per secret. Reject a `t` more than 300 s from your clock to refuse replays.\n- `X-ShortsIntel-Event-Id` repeats the event id and `X-ShortsIntel-Event-Type` the dotted event type, so you can route and dedupe without parsing the body.\n- The payload is thin: identifiers and links, never a Run's result. Fetch the detail with `links`.\n- Only a 2xx acknowledges. Each attempt has a 10 s timeout and redirects are not followed. Three attempts in all: immediately, then about 10 minutes and about 60 minutes after the first. After that the delivery is `failed` and can be replayed with `POST /v1/webhooks/{id}/deliveries/{deliveryId}/replay`, which re-sends the same event id and body with a fresh signature.","tags":["Webhooks"],"parameters":[{"name":"X-ShortsIntel-Signature","in":"header","required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 over \"<t>.<body>\">`; two `v1` during a rotation overlap.","schema":{"type":"string"}},{"name":"X-ShortsIntel-Event-Id","in":"header","required":true,"description":"The event id, `evt_...`, same as the body's `id`.","schema":{"type":"string"}},{"name":"X-ShortsIntel-Event-Type","in":"header","required":true,"description":"The dotted event type, same as the body's `type`.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"},"example":{"id":"evt_9tR2kPq7wXsL4mVbZf6HaQ","type":"tracker.changed","created_at":"2026-09-12T06:00:12.000Z","run_id":"run_5e8d13a0f7","kind":"tracker_cycle","status":"completed","charge_credits":10,"tracker_id":"trk_4b1e90c7aa","change_report_id":"chg_2ac910f4d8","collections":[{"id":"col_7d20e1b5c4","name":"Competitors"}],"links":{"run":"https://www.shortsintel.com/v1/runs/run_5e8d13a0f7","tracker":"https://www.shortsintel.com/v1/trackers/trk_4b1e90c7aa","changes":"https://www.shortsintel.com/v1/trackers/trk_4b1e90c7aa/changes"}}}}},"responses":{"2XX":{"description":"Acknowledged. Anything else is retried."}}}},"webhook.test":{"post":{"summary":"webhook.test","description":"Sent once when an endpoint is registered, to prove it. A 2xx makes the endpoint `active`.\n\n- Each delivery is a `POST` with `Content-Type: application/json` and `User-Agent: ShortsIntel-Webhooks/1`.\n- `X-ShortsIntel-Signature: t=<unix seconds>,v1=<hex>` — `v1` is HMAC-SHA256, keyed with your endpoint secret (`whsec_...`), over the string `\"<t>.<raw body>\"`. Verify against the raw bytes before parsing JSON.\n- Accept the delivery when ANY `v1` matches: during the 24 h after a secret rotation the header carries two `v1` values (new first), one per secret. Reject a `t` more than 300 s from your clock to refuse replays.\n- `X-ShortsIntel-Event-Id` repeats the event id and `X-ShortsIntel-Event-Type` the dotted event type, so you can route and dedupe without parsing the body.\n- The payload is thin: identifiers and links, never a Run's result. Fetch the detail with `links`.\n- Only a 2xx acknowledges. Each attempt has a 10 s timeout and redirects are not followed. Three attempts in all: immediately, then about 10 minutes and about 60 minutes after the first. After that the delivery is `failed` and can be replayed with `POST /v1/webhooks/{id}/deliveries/{deliveryId}/replay`, which re-sends the same event id and body with a fresh signature.","tags":["Webhooks"],"parameters":[{"name":"X-ShortsIntel-Signature","in":"header","required":true,"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 over \"<t>.<body>\">`; two `v1` during a rotation overlap.","schema":{"type":"string"}},{"name":"X-ShortsIntel-Event-Id","in":"header","required":true,"description":"The event id, `evt_...`, same as the body's `id`.","schema":{"type":"string"}},{"name":"X-ShortsIntel-Event-Type","in":"header","required":true,"description":"The dotted event type, same as the body's `type`.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"},"example":{"id":"evt_kZ8Qw3n1TfLd0aZmVbYpRc","type":"webhook.test","created_at":"2026-09-08T09:14:02.911Z","run_id":null,"kind":null,"status":null,"charge_credits":null,"tracker_id":null,"change_report_id":null,"links":{"webhook":"https://www.shortsintel.com/v1/webhooks/whe_6d2f10ab44"}}}}},"responses":{"2XX":{"description":"Acknowledged. Anything else is retried."}}}}}}
