Skip to content
For AI agents: a documentation index is available at /llms.txt. Every docs page is also available as markdown: add .md to its URL. To connect, read /agents.md.

API referenceAds

Look up a Google Ad

GET /v1/ads/google/{creative_id}

One Google Ad by creative id or Transparency URL, with variations and any YouTube id.

  • Storage: images archived. Served from our copy within 24 hours, or with removed_from_library: true once dropped, same price.
  • Errors: no advertiser_id for an unseen Ad is 400 invalid_request, an unknown Ad 404 not_found, both free.
  • Analysis: a refused Ad fails the Run and returns no Ad, for free.

Open in Playground (no API Key needed)

Price

3 credits, plus 20 credits with analyze=true.

Supports estimate=true: the reply is the price in Credits and whether it would be cached, with no Run created and nothing charged.

A cached result costs the same as a fresh one; cached says which you got.

Parameters

NameInTypeRequiredDefaultDescription
creative_idpathstring Required—The CR id, or the URL-encoded Transparency URL.
advertiser_idquerystring Optional—The Ad's Advertiser, as its AR id. Required unless the URL names it or we already hold the Ad.
analyzequerystring one of true, falseOptional—true to add Ad analysis.
waitqueryinteger min 0; max 120Optional30Seconds 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.
max_creditsqueryinteger min 0Optional—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.
estimatequeryboolean Optional—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.
Idempotency-Keyheaderstring Optional—1-255 printable ASCII characters. Replaying this key with the same payload returns the original Run (202 while it is still running); a different payload, or a different operation, is a 409 idempotency_conflict.

Responses

200 OK

The Run finished inside the wait budget: { run, result }.

any of 2 shapes

  • Option 1 object 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.
    • run object required Every charged operation creates a Run. The envelope is identical whether the result came back inline or was polled.
      • id string required
      • kind string required What was run, e.g. video_lookup.
      • status string required one of running, completed, partial, failed partial keeps the completed items and charges for them, up to what the Balance covers; failed charges nothing.
      • created_at string required RFC 3339.
      • completed_at string required nullable Null while the Run is still running.
      • charge_credits integer required What this Run actually cost, in Credits. A stored answer costs the same as a fresh one.
      • list_price_credits integer required The full price of the work asked for, in Credits. Equal to charge_credits unless the Run charged for only part of it.
      • cached boolean required True when a stored result answered without a fresh fetch.
      • progress object 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.
        • stage string required one of keywords, searching, reading_creators, filtering, analysing, writing_digest
        • keywords integer value at least 0
        • creators integer value at least 0
        • creators_read integer value at least 0
        • searches integer value at least 0
        • found integer value at least 0
        • judged integer value at least 0
        • kept integer value at least 0
        • dropped_off_topic integer value at least 0
        • dropped_unsure integer value at least 0
        • shortlisted integer value at least 0
        • analysed integer value at least 0
        • updated_at string required
    • result object required
      • ad object required
        • library string required one of meta, tiktok, google
        • id string required
        • url string required nullable
        • advertiser object required
          • id string required nullable
          • name string required nullable
        • is_active boolean required nullable
        • first_shown string required nullable
        • last_shown string required nullable
        • placements array of string required
        • creative object required
          • title string required nullable
          • body string required nullable
          • cta string required nullable
          • format string required nullable
          • image_urls array of string required
          • video_urls array of string required
          • thumbnail_urls array of string required
        • reach object required 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.
          • impressions string required nullable
          • spend string required nullable
          • currency string required nullable
          • audience string required nullable
        • kind string nullable one of commercial, political, issue Meta and Google.
        • media_type string nullable one of video, image, carousel, text Meta and Google (video, image, text).
        • countries array of string nullable Countries reached, when the library discloses them: Meta and Google search and lookup, and the TikTok single-Ad lookup.
        • variant_count number nullable Meta only. How many Ads share this Ad's media; null for a single Ad.
        • days_running number nullable Meta only. Whole days from start to stop, or to now while running.
        • variations array of object Google only. Each version of the Ad's copy and media. A video Ad's YouTube id sits here when Google shows one, which not every video Ad has; creative.video_urls stays empty.
          • headline string required nullable
          • description string required nullable
          • all_text string required nullable
          • destination_url string required nullable
          • visible_url string required nullable
          • image_urls array of string required
          • video_id string required nullable
          • youtube_url string required nullable
        • details_failed boolean Google search only. True when this Ad's details could not be read: it holds only the list row and is not charged or stored.
        • archived boolean 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 object nullable 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.
          • score number required nullable
          • confidence string required one of high, low
          • inputs object required
            • days_running number required nullable
            • variants_added number required
            • snapshots number required
            • advertiser_ads number required Dated Ads of this Advertiser stored so far, this one included.
          • reason string required nullable one of single_snapshot, few_advertiser_ads, no_start_date
        • intelligence any of 2 shapes nullable Present when already computed for this Ad, or asked for with analyze; null under analyze when it could not be computed.
          • Option 1 object Video Ads: the full video analysis, read from the archived video with the ad copy as context, plus offer, copy, and detected shots, the product's first appearance and the opening frame under structure.
            • version integer required
            • model string required
            • computed_at string required
            • source string required
            • content object required
              • summary string required
              • niche string required
              • languages array of string required
              • content_styles array of string required
              • keywords array of object required
                • keyword string required
                • category string required
                • sentiment number required
              • transcript string required nullable What is said, one line per line: the Platform's captions or speech-to-text, never the scene breakdown. Empty with no speech; null when it could not be read.
              • transcript_source string required nullable one of caption, whisper caption: the Platform's caption track. whisper: speech-to-text on the audio. Null when transcript is null, and on analysis stored before 2026-11-09.
              • transcript_segments array of object required nullable Timed transcript lines (ms from the start), to see when the hook lands. From the Platform's timed captions when it has them, otherwise measured from the video's audio with speech-to-text. Spoken timing here is measured; times in structure.scenes are approximate. Empty when the video has no speech, music-only videos included. Null when the timing could not be measured, on a YouTube Video with no captions, and on older analyses.
                • start_ms integer required
                • end_ms integer required
                • text string required
            • hook object required
              • opening_line string required nullable
              • type string required
              • visual_hook string required nullable
              • rationale string required nullable
            • persuasion object required
              • call_to_action object required
                • type string required
                • text string required nullable
              • sponsored boolean required Whether the video is plausibly a paid promotion. Always true when the Platform labels it an ad or a paid partnership.
              • sponsorship_signals array of string required
              • brands_and_products array of object required
                • name string required
                • kind string required
                • prominence string required
              • trend_references array of object required
                • name string required
                • kind string required
            • tone object required
              • sentiment_label string required
              • sentiment_score number required
              • primary_emotion string required
              • emotion_intensity number required nullable
              • emotion_rationale string required nullable
              • speaking_style string required
              • speaking_style_notes string required nullable
            • visual object required
              • format string required
              • setting string required
              • face_visibility string required
              • on_screen_text array of string required
              • has_on_screen_captions boolean required
              • camera_notes string required nullable
              • lighting_notes string required nullable
              • elements any
            • safety object required
              • brand_safety_tier string required
              • reasons array of string required
              • notes string required nullable
            • structure object required When things happen inside the creative: the timed scenes every analysis carries, plus the shots detected, when the product is first seen and the opening frame on a video Ad.
              • scenes array of object required The timed scenes, read from the stored scene breakdown. Times are approximate, to about a second. Empty when the breakdown has no timed scenes, as on a photo carousel.
                • start_ms integer required Approximate scene start, ms from the start.
                • end_ms integer required Approximate scene end, ms from the start.
                • visual string required nullable
                • text_overlay string required nullable Text shown in this scene, listed at its first appearance: text repeated from an earlier scene is left out.
                • speech string required nullable
                • audio string required nullable Notable sound effects or music.
              • shots array of object required nullable The detected shots in order, each from one cut to the next. A cut is a frame whose ffmpeg scene score is over 0.2. On 29 labelled Ads this found 86% of hard cuts within 500 ms (median error 67 ms) and 61% of jump cuts overall, but none on UGC Ads. Null when detection failed, and on analysis stored before shots.
                • start_ms integer required Shot start: the cut before it, or 0.
                • end_ms integer required Shot end: the next cut, or the video's end.
              • cuts_per_minute number required nullable Detected cuts per minute of video, to two decimals. Null whenever shots is.
              • avg_shot_ms integer required nullable The video's length over its number of shots, in ms. Null whenever shots is.
              • product_first_seen_ms integer required nullable When the promoted product first appears (the item, its packaging or logo, or an app's screen), as the start of that scene in ms, so approximate to one scene. On 26 labelled Ads that show one, it was within 3 s of the labelled time on 23 (88%). Null when no product is shown, and on analysis stored before it.
              • first_frame string required nullable What the video's opening frame shows, as text: a description, not a time. Read from the first scene's **Opening Frame:** line in the scene breakdown. Checked against the video on 10 Ads, it was accurate on all 10. Null when the breakdown has no opening frame, and on analysis stored before it.
            • pipeline string required always video
            • offer object required nullable The offer, in the same types as an image Ad's offer. Null when the extraction failed and on analysis stored before this field.
              • type string required
              • text string required nullable
            • copy object required nullable The persuasion angle, in the same values as an image Ad's copy.angle. Null when the extraction failed and on analysis stored before this field.
              • angle string required
              • rationale string required nullable
          • Option 2 object Image and carousel Ads: the analysis an image can carry, read from the archived images with the ad copy as context.
            • pipeline string required always image
            • version integer required
            • model string required
            • computed_at string required
            • images_analyzed integer required
            • summary string required
            • copy object required
              • angle string required
              • rationale string required nullable
              • headline string required nullable
            • offer object required
              • type string required
              • text string required nullable
            • call_to_action object required
              • type string required
              • text string required nullable
            • visual object required
              • format string required
              • on_image_text array of string required
            • topics array of string required
            • tone object required
              • sentiment_label string required
              • sentiment_score number required
        • intelligence_error object Why analyze left intelligence null: no analysis charge. Its fields are on Errors.
        • advertiser_account object nullable TikTok lookup only. The TikTok account the Ad ran from.
          • username string required
          • display_name string required nullable
          • followers string required nullable As TikTok shows it (9.3M), not a number.
          • verified boolean required nullable
          • url string required nullable
        • targeting object nullable 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.
          • countries array of string required
          • impressions string required nullable
          • audience_size string required nullable
          • ages array of string required Age ranges targeted (18-24).
          • genders array of string required Genders targeted (female, male, unknown).
          • by_country array of object required
            • country string required
            • impressions string required nullable
            • breakdown array of object required
              • age string required
              • gender string required
              • impressions string required nullable
        • performance object nullable 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.
          • ctr number required nullable Click-through rate as a fraction (0.46 is 46%).
          • likes number required nullable
          • comments number required nullable
          • shares number required nullable
        • objective string nullable TikTok lookup only. The Ad's objective (Traffic).
        • removed_from_library boolean required True when the library no longer shows the Ad and it was served from our stored copy.
        • removed_at string required nullable When this API first found the Ad gone from the library.
      • as_of string required nullable When the Ad was last observed in the library.
  • Option 2 object 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.
    • estimate_credits integer required What the call would be charged, in Credits.
    • cached boolean required Whether a stored result can already answer. It does not change the price.

202 Accepted

Still running: { run }. Poll GET /v1/runs/{id}.

object

Still running. Poll poll_url (GET /v1/runs/{id}), waiting the 202's Retry-After seconds between polls.

  • run object required Every charged operation creates a Run. The envelope is identical whether the result came back inline or was polled. Its fields are on Poll or re-read a run.
  • poll_url string required format uri 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.

202 · 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"
}

400 Bad Request

invalid_request (a malformed id, wait, estimate or Idempotency-Key) or unsupported_platform, refused before any Run opens. Nothing is charged.

Codes: invalid_request, unsupported_platform. The problem body and every code are on Errors.

object

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.

  • type string required
  • title string required
  • status integer required
  • code string required one of 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 Stable machine-readable code.
  • detail string
  • errors array of object 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.
    • path string required 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 string required What is wrong with that field.
  • request_id string The request this problem answers, the same as its X-Request-Id header. Quote it to support.
  • retryable boolean required 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 string required The next step, in one sentence.
  • remedy string 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 integer value at least 0 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 string When the key expired. On key_expired.
  • resets_at string When the request window (rate_limit_exceeded) or the key's month (key_spend_cap_exceeded) resets.
  • limit integer The limit that was hit, on the *_limit_exceeded codes.
  • running integer Runs in flight. On concurrency_limit_exceeded.
  • active integer Active Trackers or webhook endpoints. On tracker_limit_exceeded and webhook_limit_exceeded.
  • requested integer Trackers the request would resume. On tracker_limit_exceeded from a Collection action.
  • count integer Collections held. On collection_limit_exceeded.
  • balance_credits integer The Balance, in Credits. On insufficient_balance.
  • required_credits integer What the call needs, in Credits (the worst case where quoted). On insufficient_balance.
  • max_credits integer The cap the call sent. On max_credits_exceeded.
  • estimate_credits integer The call's worst-case quote, in Credits. On max_credits_exceeded and key_spend_cap_exceeded.
  • cap_credits integer The key's monthly cap. On key_spend_cap_exceeded.
  • spent_credits integer The key's Charges this UTC month. On key_spend_cap_exceeded.
  • reserved_credits integer What the key's Runs in flight hold. On key_spend_cap_exceeded.
  • endpoints array of string The sources that could not answer. On source_unavailable.
  • endpoint string The source that could not answer. On source_unavailable.
  • candidates array of object The advertisers that carry the name, to ask again with. On advertiser_ambiguous.
  • supported_kinds array of string The kinds that are accepted. On kind_deprecated and focus_unsupported_kind.
  • duration_seconds number The video's length. On video_too_long.
  • max_duration_seconds number The longest video accepted. On video_too_long.
  • overlap_expires_at string When the previous secret stops working. On webhook_rotation_in_progress.
  • scope string always read_only The key's scope. On key_scope_insufficient.
  • required string always full The scope the call needs. On key_scope_insufficient.
  • collection_id string The Collection that already has the name. On collection_name_taken.
  • collection_kind string The Collection's kind. On collection_kind_mismatch.
  • kind string The kind that was offered. On collection_kind_mismatch.
  • run_id string The Run the Idempotency-Key already belongs to. On idempotency_conflict.
  • reason string A short machine-readable reason, where a code has several.
  • reference_id string Our reference for an unexpected failure, the same as request_id; quote it when reporting it.
  • run object The Run, on a failed Run's body, so its id is kept.
    • id string required
    • kind string required What was run, e.g. video_lookup.
    • status string required one of running, completed, partial, failed partial keeps the completed items and charges for them, up to what the Balance covers; failed charges nothing.
    • created_at string required RFC 3339.
    • completed_at string required nullable Null while the Run is still running.
    • charge_credits integer required What this Run actually cost, in Credits. A stored answer costs the same as a fresh one.
    • list_price_credits integer required The full price of the work asked for, in Credits. Equal to charge_credits unless the Run charged for only part of it.
    • cached boolean required True when a stored result answered without a fresh fetch.
    • progress object 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.
      • stage string required one of keywords, searching, reading_creators, filtering, analysing, writing_digest
      • keywords integer value at least 0
      • creators integer value at least 0
      • creators_read integer value at least 0
      • searches integer value at least 0
      • found integer value at least 0
      • judged integer value at least 0
      • kept integer value at least 0
      • dropped_off_topic integer value at least 0
      • dropped_unsure integer value at least 0
      • shortlisted integer value at least 0
      • analysed integer value at least 0
      • updated_at string required
  • error object The same problem, nested, on a failed Run's body.

400 · Example

{
  "type": "https://www.shortsintel.com/docs/reference/errors/invalid_request",
  "title": "Invalid request",
  "status": 400,
  "code": "invalid_request",
  "detail": "`estimate` must be `true` or `false`.",
  "retryable": false,
  "action": "Fix the field named in `detail`, then send the corrected request."
}

401 Unauthorized

missing_authorization, invalid_key, key_revoked, key_expired or invalid_token.

Codes: missing_authorization, invalid_key, key_revoked, key_expired, invalid_token. The problem body and every code are on Errors.

object

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.

  • type string required
  • title string required
  • status integer required
  • code string required one of 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 Stable machine-readable code.
  • detail string
  • errors array of object 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.
    • path string required 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 string required What is wrong with that field.
  • request_id string The request this problem answers, the same as its X-Request-Id header. Quote it to support.
  • retryable boolean required 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 string required The next step, in one sentence.
  • remedy string 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 integer value at least 0 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 string When the key expired. On key_expired.
  • resets_at string When the request window (rate_limit_exceeded) or the key's month (key_spend_cap_exceeded) resets.
  • limit integer The limit that was hit, on the *_limit_exceeded codes.
  • running integer Runs in flight. On concurrency_limit_exceeded.
  • active integer Active Trackers or webhook endpoints. On tracker_limit_exceeded and webhook_limit_exceeded.
  • requested integer Trackers the request would resume. On tracker_limit_exceeded from a Collection action.
  • count integer Collections held. On collection_limit_exceeded.
  • balance_credits integer The Balance, in Credits. On insufficient_balance.
  • required_credits integer What the call needs, in Credits (the worst case where quoted). On insufficient_balance.
  • max_credits integer The cap the call sent. On max_credits_exceeded.
  • estimate_credits integer The call's worst-case quote, in Credits. On max_credits_exceeded and key_spend_cap_exceeded.
  • cap_credits integer The key's monthly cap. On key_spend_cap_exceeded.
  • spent_credits integer The key's Charges this UTC month. On key_spend_cap_exceeded.
  • reserved_credits integer What the key's Runs in flight hold. On key_spend_cap_exceeded.
  • endpoints array of string The sources that could not answer. On source_unavailable.
  • endpoint string The source that could not answer. On source_unavailable.
  • candidates array of object The advertisers that carry the name, to ask again with. On advertiser_ambiguous.
  • supported_kinds array of string The kinds that are accepted. On kind_deprecated and focus_unsupported_kind.
  • duration_seconds number The video's length. On video_too_long.
  • max_duration_seconds number The longest video accepted. On video_too_long.
  • overlap_expires_at string When the previous secret stops working. On webhook_rotation_in_progress.
  • scope string always read_only The key's scope. On key_scope_insufficient.
  • required string always full The scope the call needs. On key_scope_insufficient.
  • collection_id string The Collection that already has the name. On collection_name_taken.
  • collection_kind string The Collection's kind. On collection_kind_mismatch.
  • kind string The kind that was offered. On collection_kind_mismatch.
  • run_id string The Run the Idempotency-Key already belongs to. On idempotency_conflict.
  • reason string A short machine-readable reason, where a code has several.
  • reference_id string Our reference for an unexpected failure, the same as request_id; quote it when reporting it.
  • run object The Run, on a failed Run's body, so its id is kept.
    • id string required
    • kind string required What was run, e.g. video_lookup.
    • status string required one of running, completed, partial, failed partial keeps the completed items and charges for them, up to what the Balance covers; failed charges nothing.
    • created_at string required RFC 3339.
    • completed_at string required nullable Null while the Run is still running.
    • charge_credits integer required What this Run actually cost, in Credits. A stored answer costs the same as a fresh one.
    • list_price_credits integer required The full price of the work asked for, in Credits. Equal to charge_credits unless the Run charged for only part of it.
    • cached boolean required True when a stored result answered without a fresh fetch.
    • progress object 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.
      • stage string required one of keywords, searching, reading_creators, filtering, analysing, writing_digest
      • keywords integer value at least 0
      • creators integer value at least 0
      • creators_read integer value at least 0
      • searches integer value at least 0
      • found integer value at least 0
      • judged integer value at least 0
      • kept integer value at least 0
      • dropped_off_topic integer value at least 0
      • dropped_unsure integer value at least 0
      • shortlisted integer value at least 0
      • analysed integer value at least 0
      • updated_at string required
  • error object The same problem, nested, on a failed Run's body.

401 · Example

{
  "type": "https://www.shortsintel.com/docs/reference/errors/invalid_key",
  "title": "Invalid key",
  "status": 401,
  "code": "invalid_key",
  "detail": "That API key does not exist. Keys look like `sk_live_...` and are created in the console.",
  "retryable": false,
  "action": "Check the whole key was copied, or create a new key in the console."
}

402 Payment Required

insufficient_balance — the Balance cannot cover the quoted price (the worst case for Research and enriched search). No Run is created and nothing is charged. A multi-item Run whose Balance runs short later charges its completed items up to the Balance and ends partial.

Code: insufficient_balance. The problem body and every code are on Errors.

object

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.

  • type string required
  • title string required
  • status integer required
  • code string required one of 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 Stable machine-readable code.
  • detail string
  • errors array of object 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.
    • path string required 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 string required What is wrong with that field.
  • request_id string The request this problem answers, the same as its X-Request-Id header. Quote it to support.
  • retryable boolean required 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 string required The next step, in one sentence.
  • remedy string 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 integer value at least 0 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 string When the key expired. On key_expired.
  • resets_at string When the request window (rate_limit_exceeded) or the key's month (key_spend_cap_exceeded) resets.
  • limit integer The limit that was hit, on the *_limit_exceeded codes.
  • running integer Runs in flight. On concurrency_limit_exceeded.
  • active integer Active Trackers or webhook endpoints. On tracker_limit_exceeded and webhook_limit_exceeded.
  • requested integer Trackers the request would resume. On tracker_limit_exceeded from a Collection action.
  • count integer Collections held. On collection_limit_exceeded.
  • balance_credits integer The Balance, in Credits. On insufficient_balance.
  • required_credits integer What the call needs, in Credits (the worst case where quoted). On insufficient_balance.
  • max_credits integer The cap the call sent. On max_credits_exceeded.
  • estimate_credits integer The call's worst-case quote, in Credits. On max_credits_exceeded and key_spend_cap_exceeded.
  • cap_credits integer The key's monthly cap. On key_spend_cap_exceeded.
  • spent_credits integer The key's Charges this UTC month. On key_spend_cap_exceeded.
  • reserved_credits integer What the key's Runs in flight hold. On key_spend_cap_exceeded.
  • endpoints array of string The sources that could not answer. On source_unavailable.
  • endpoint string The source that could not answer. On source_unavailable.
  • candidates array of object The advertisers that carry the name, to ask again with. On advertiser_ambiguous.
  • supported_kinds array of string The kinds that are accepted. On kind_deprecated and focus_unsupported_kind.
  • duration_seconds number The video's length. On video_too_long.
  • max_duration_seconds number The longest video accepted. On video_too_long.
  • overlap_expires_at string When the previous secret stops working. On webhook_rotation_in_progress.
  • scope string always read_only The key's scope. On key_scope_insufficient.
  • required string always full The scope the call needs. On key_scope_insufficient.
  • collection_id string The Collection that already has the name. On collection_name_taken.
  • collection_kind string The Collection's kind. On collection_kind_mismatch.
  • kind string The kind that was offered. On collection_kind_mismatch.
  • run_id string The Run the Idempotency-Key already belongs to. On idempotency_conflict.
  • reason string A short machine-readable reason, where a code has several.
  • reference_id string Our reference for an unexpected failure, the same as request_id; quote it when reporting it.
  • run object The Run, on a failed Run's body, so its id is kept.
    • id string required
    • kind string required What was run, e.g. video_lookup.
    • status string required one of running, completed, partial, failed partial keeps the completed items and charges for them, up to what the Balance covers; failed charges nothing.
    • created_at string required RFC 3339.
    • completed_at string required nullable Null while the Run is still running.
    • charge_credits integer required What this Run actually cost, in Credits. A stored answer costs the same as a fresh one.
    • list_price_credits integer required The full price of the work asked for, in Credits. Equal to charge_credits unless the Run charged for only part of it.
    • cached boolean required True when a stored result answered without a fresh fetch.
    • progress object 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.
      • stage string required one of keywords, searching, reading_creators, filtering, analysing, writing_digest
      • keywords integer value at least 0
      • creators integer value at least 0
      • creators_read integer value at least 0
      • searches integer value at least 0
      • found integer value at least 0
      • judged integer value at least 0
      • kept integer value at least 0
      • dropped_off_topic integer value at least 0
      • dropped_unsure integer value at least 0
      • shortlisted integer value at least 0
      • analysed integer value at least 0
      • updated_at string required
  • error object The same problem, nested, on a failed Run's body.

402 · 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
}

409 Conflict

idempotency_conflict — the same Idempotency-Key with a different payload.

Code: idempotency_conflict. The problem body and every code are on Errors.

object

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.

  • type string required
  • title string required
  • status integer required
  • code string required one of 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 Stable machine-readable code.
  • detail string
  • errors array of object 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.
    • path string required 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 string required What is wrong with that field.
  • request_id string The request this problem answers, the same as its X-Request-Id header. Quote it to support.
  • retryable boolean required 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 string required The next step, in one sentence.
  • remedy string 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 integer value at least 0 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 string When the key expired. On key_expired.
  • resets_at string When the request window (rate_limit_exceeded) or the key's month (key_spend_cap_exceeded) resets.
  • limit integer The limit that was hit, on the *_limit_exceeded codes.
  • running integer Runs in flight. On concurrency_limit_exceeded.
  • active integer Active Trackers or webhook endpoints. On tracker_limit_exceeded and webhook_limit_exceeded.
  • requested integer Trackers the request would resume. On tracker_limit_exceeded from a Collection action.
  • count integer Collections held. On collection_limit_exceeded.
  • balance_credits integer The Balance, in Credits. On insufficient_balance.
  • required_credits integer What the call needs, in Credits (the worst case where quoted). On insufficient_balance.
  • max_credits integer The cap the call sent. On max_credits_exceeded.
  • estimate_credits integer The call's worst-case quote, in Credits. On max_credits_exceeded and key_spend_cap_exceeded.
  • cap_credits integer The key's monthly cap. On key_spend_cap_exceeded.
  • spent_credits integer The key's Charges this UTC month. On key_spend_cap_exceeded.
  • reserved_credits integer What the key's Runs in flight hold. On key_spend_cap_exceeded.
  • endpoints array of string The sources that could not answer. On source_unavailable.
  • endpoint string The source that could not answer. On source_unavailable.
  • candidates array of object The advertisers that carry the name, to ask again with. On advertiser_ambiguous.
  • supported_kinds array of string The kinds that are accepted. On kind_deprecated and focus_unsupported_kind.
  • duration_seconds number The video's length. On video_too_long.
  • max_duration_seconds number The longest video accepted. On video_too_long.
  • overlap_expires_at string When the previous secret stops working. On webhook_rotation_in_progress.
  • scope string always read_only The key's scope. On key_scope_insufficient.
  • required string always full The scope the call needs. On key_scope_insufficient.
  • collection_id string The Collection that already has the name. On collection_name_taken.
  • collection_kind string The Collection's kind. On collection_kind_mismatch.
  • kind string The kind that was offered. On collection_kind_mismatch.
  • run_id string The Run the Idempotency-Key already belongs to. On idempotency_conflict.
  • reason string A short machine-readable reason, where a code has several.
  • reference_id string Our reference for an unexpected failure, the same as request_id; quote it when reporting it.
  • run object The Run, on a failed Run's body, so its id is kept.
    • id string required
    • kind string required What was run, e.g. video_lookup.
    • status string required one of running, completed, partial, failed partial keeps the completed items and charges for them, up to what the Balance covers; failed charges nothing.
    • created_at string required RFC 3339.
    • completed_at string required nullable Null while the Run is still running.
    • charge_credits integer required What this Run actually cost, in Credits. A stored answer costs the same as a fresh one.
    • list_price_credits integer required The full price of the work asked for, in Credits. Equal to charge_credits unless the Run charged for only part of it.
    • cached boolean required True when a stored result answered without a fresh fetch.
    • progress object 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.
      • stage string required one of keywords, searching, reading_creators, filtering, analysing, writing_digest
      • keywords integer value at least 0
      • creators integer value at least 0
      • creators_read integer value at least 0
      • searches integer value at least 0
      • found integer value at least 0
      • judged integer value at least 0
      • kept integer value at least 0
      • dropped_off_topic integer value at least 0
      • dropped_unsure integer value at least 0
      • shortlisted integer value at least 0
      • analysed integer value at least 0
      • updated_at string required
  • error object The same problem, nested, on a failed Run's body.

409 · Example

{
  "type": "https://www.shortsintel.com/docs/reference/errors/idempotency_conflict",
  "title": "Idempotency conflict",
  "status": 409,
  "code": "idempotency_conflict",
  "detail": "This Idempotency-Key was used with a different payload.",
  "retryable": false,
  "action": "Resend the original payload with this key, or use a new key for the new payload.",
  "run_id": "run_8f2c1ad04b"
}

429 Too Many Requests

rate_limit_exceeded or concurrency_limit_exceeded, with Retry-After.

Codes: rate_limit_exceeded, concurrency_limit_exceeded. The problem body and every code are on Errors.

object

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.

  • type string required
  • title string required
  • status integer required
  • code string required one of 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 Stable machine-readable code.
  • detail string
  • errors array of object 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.
    • path string required 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 string required What is wrong with that field.
  • request_id string The request this problem answers, the same as its X-Request-Id header. Quote it to support.
  • retryable boolean required 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 string required The next step, in one sentence.
  • remedy string 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 integer value at least 0 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 string When the key expired. On key_expired.
  • resets_at string When the request window (rate_limit_exceeded) or the key's month (key_spend_cap_exceeded) resets.
  • limit integer The limit that was hit, on the *_limit_exceeded codes.
  • running integer Runs in flight. On concurrency_limit_exceeded.
  • active integer Active Trackers or webhook endpoints. On tracker_limit_exceeded and webhook_limit_exceeded.
  • requested integer Trackers the request would resume. On tracker_limit_exceeded from a Collection action.
  • count integer Collections held. On collection_limit_exceeded.
  • balance_credits integer The Balance, in Credits. On insufficient_balance.
  • required_credits integer What the call needs, in Credits (the worst case where quoted). On insufficient_balance.
  • max_credits integer The cap the call sent. On max_credits_exceeded.
  • estimate_credits integer The call's worst-case quote, in Credits. On max_credits_exceeded and key_spend_cap_exceeded.
  • cap_credits integer The key's monthly cap. On key_spend_cap_exceeded.
  • spent_credits integer The key's Charges this UTC month. On key_spend_cap_exceeded.
  • reserved_credits integer What the key's Runs in flight hold. On key_spend_cap_exceeded.
  • endpoints array of string The sources that could not answer. On source_unavailable.
  • endpoint string The source that could not answer. On source_unavailable.
  • candidates array of object The advertisers that carry the name, to ask again with. On advertiser_ambiguous.
  • supported_kinds array of string The kinds that are accepted. On kind_deprecated and focus_unsupported_kind.
  • duration_seconds number The video's length. On video_too_long.
  • max_duration_seconds number The longest video accepted. On video_too_long.
  • overlap_expires_at string When the previous secret stops working. On webhook_rotation_in_progress.
  • scope string always read_only The key's scope. On key_scope_insufficient.
  • required string always full The scope the call needs. On key_scope_insufficient.
  • collection_id string The Collection that already has the name. On collection_name_taken.
  • collection_kind string The Collection's kind. On collection_kind_mismatch.
  • kind string The kind that was offered. On collection_kind_mismatch.
  • run_id string The Run the Idempotency-Key already belongs to. On idempotency_conflict.
  • reason string A short machine-readable reason, where a code has several.
  • reference_id string Our reference for an unexpected failure, the same as request_id; quote it when reporting it.
  • run object The Run, on a failed Run's body, so its id is kept.
    • id string required
    • kind string required What was run, e.g. video_lookup.
    • status string required one of running, completed, partial, failed partial keeps the completed items and charges for them, up to what the Balance covers; failed charges nothing.
    • created_at string required RFC 3339.
    • completed_at string required nullable Null while the Run is still running.
    • charge_credits integer required What this Run actually cost, in Credits. A stored answer costs the same as a fresh one.
    • list_price_credits integer required The full price of the work asked for, in Credits. Equal to charge_credits unless the Run charged for only part of it.
    • cached boolean required True when a stored result answered without a fresh fetch.
    • progress object 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.
      • stage string required one of keywords, searching, reading_creators, filtering, analysing, writing_digest
      • keywords integer value at least 0
      • creators integer value at least 0
      • creators_read integer value at least 0
      • searches integer value at least 0
      • found integer value at least 0
      • judged integer value at least 0
      • kept integer value at least 0
      • dropped_off_topic integer value at least 0
      • dropped_unsure integer value at least 0
      • shortlisted integer value at least 0
      • analysed integer value at least 0
      • updated_at string required
  • error object The same problem, nested, on a failed Run's body.

429 · Example

{
  "type": "https://www.shortsintel.com/docs/reference/errors/rate_limit_exceeded",
  "title": "Rate limit exceeded",
  "status": 429,
  "code": "rate_limit_exceeded",
  "detail": "60 requests per minute per key. Retry after the number of seconds in `Retry-After`.",
  "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"
}

502 Bad Gateway

A Run that opened and then failed is answered as application/problem+json with its problem's status — vendor_error here, not_found as 404 — and the Run envelope alongside, so the Run id is kept. A failed Run is never charged.

Code: vendor_error. The problem body and every code are on Errors.

object

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.

  • type string required
  • title string required
  • status integer required
  • code string required one of 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 Stable machine-readable code.
  • detail string
  • errors array of object 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.
    • path string required 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 string required What is wrong with that field.
  • request_id string The request this problem answers, the same as its X-Request-Id header. Quote it to support.
  • retryable boolean required 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 string required The next step, in one sentence.
  • remedy string 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 integer value at least 0 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 string When the key expired. On key_expired.
  • resets_at string When the request window (rate_limit_exceeded) or the key's month (key_spend_cap_exceeded) resets.
  • limit integer The limit that was hit, on the *_limit_exceeded codes.
  • running integer Runs in flight. On concurrency_limit_exceeded.
  • active integer Active Trackers or webhook endpoints. On tracker_limit_exceeded and webhook_limit_exceeded.
  • requested integer Trackers the request would resume. On tracker_limit_exceeded from a Collection action.
  • count integer Collections held. On collection_limit_exceeded.
  • balance_credits integer The Balance, in Credits. On insufficient_balance.
  • required_credits integer What the call needs, in Credits (the worst case where quoted). On insufficient_balance.
  • max_credits integer The cap the call sent. On max_credits_exceeded.
  • estimate_credits integer The call's worst-case quote, in Credits. On max_credits_exceeded and key_spend_cap_exceeded.
  • cap_credits integer The key's monthly cap. On key_spend_cap_exceeded.
  • spent_credits integer The key's Charges this UTC month. On key_spend_cap_exceeded.
  • reserved_credits integer What the key's Runs in flight hold. On key_spend_cap_exceeded.
  • endpoints array of string The sources that could not answer. On source_unavailable.
  • endpoint string The source that could not answer. On source_unavailable.
  • candidates array of object The advertisers that carry the name, to ask again with. On advertiser_ambiguous.
  • supported_kinds array of string The kinds that are accepted. On kind_deprecated and focus_unsupported_kind.
  • duration_seconds number The video's length. On video_too_long.
  • max_duration_seconds number The longest video accepted. On video_too_long.
  • overlap_expires_at string When the previous secret stops working. On webhook_rotation_in_progress.
  • scope string always read_only The key's scope. On key_scope_insufficient.
  • required string always full The scope the call needs. On key_scope_insufficient.
  • collection_id string The Collection that already has the name. On collection_name_taken.
  • collection_kind string The Collection's kind. On collection_kind_mismatch.
  • kind string The kind that was offered. On collection_kind_mismatch.
  • run_id string The Run the Idempotency-Key already belongs to. On idempotency_conflict.
  • reason string A short machine-readable reason, where a code has several.
  • reference_id string Our reference for an unexpected failure, the same as request_id; quote it when reporting it.
  • run object The Run, on a failed Run's body, so its id is kept.
    • id string required
    • kind string required What was run, e.g. video_lookup.
    • status string required one of running, completed, partial, failed partial keeps the completed items and charges for them, up to what the Balance covers; failed charges nothing.
    • created_at string required RFC 3339.
    • completed_at string required nullable Null while the Run is still running.
    • charge_credits integer required What this Run actually cost, in Credits. A stored answer costs the same as a fresh one.
    • list_price_credits integer required The full price of the work asked for, in Credits. Equal to charge_credits unless the Run charged for only part of it.
    • cached boolean required True when a stored result answered without a fresh fetch.
    • progress object 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.
      • stage string required one of keywords, searching, reading_creators, filtering, analysing, writing_digest
      • keywords integer value at least 0
      • creators integer value at least 0
      • creators_read integer value at least 0
      • searches integer value at least 0
      • found integer value at least 0
      • judged integer value at least 0
      • kept integer value at least 0
      • dropped_off_topic integer value at least 0
      • dropped_unsure integer value at least 0
      • shortlisted integer value at least 0
      • analysed integer value at least 0
      • updated_at string required
  • error object The same problem, nested, on a failed Run's body.

502 · Example

{
  "type": "https://www.shortsintel.com/docs/reference/errors/vendor_error",
  "title": "Vendor error",
  "status": 502,
  "code": "vendor_error",
  "detail": "The upstream data provider could not be reached.",
  "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
  }
}

503 Service Unavailable

source_unavailable: every source this Run reads failed or is switched off. The Run fails uncharged, with its envelope alongside; endpoints names the source. Wait retry_after_seconds (also sent as Retry-After) and retry rather than treating it as empty.

Code: source_unavailable. The problem body and every code are on Errors.

object

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.

  • type string required
  • title string required
  • status integer required
  • code string required one of 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 Stable machine-readable code.
  • detail string
  • errors array of object 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.
    • path string required 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 string required What is wrong with that field.
  • request_id string The request this problem answers, the same as its X-Request-Id header. Quote it to support.
  • retryable boolean required 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 string required The next step, in one sentence.
  • remedy string 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 integer value at least 0 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 string When the key expired. On key_expired.
  • resets_at string When the request window (rate_limit_exceeded) or the key's month (key_spend_cap_exceeded) resets.
  • limit integer The limit that was hit, on the *_limit_exceeded codes.
  • running integer Runs in flight. On concurrency_limit_exceeded.
  • active integer Active Trackers or webhook endpoints. On tracker_limit_exceeded and webhook_limit_exceeded.
  • requested integer Trackers the request would resume. On tracker_limit_exceeded from a Collection action.
  • count integer Collections held. On collection_limit_exceeded.
  • balance_credits integer The Balance, in Credits. On insufficient_balance.
  • required_credits integer What the call needs, in Credits (the worst case where quoted). On insufficient_balance.
  • max_credits integer The cap the call sent. On max_credits_exceeded.
  • estimate_credits integer The call's worst-case quote, in Credits. On max_credits_exceeded and key_spend_cap_exceeded.
  • cap_credits integer The key's monthly cap. On key_spend_cap_exceeded.
  • spent_credits integer The key's Charges this UTC month. On key_spend_cap_exceeded.
  • reserved_credits integer What the key's Runs in flight hold. On key_spend_cap_exceeded.
  • endpoints array of string The sources that could not answer. On source_unavailable.
  • endpoint string The source that could not answer. On source_unavailable.
  • candidates array of object The advertisers that carry the name, to ask again with. On advertiser_ambiguous.
  • supported_kinds array of string The kinds that are accepted. On kind_deprecated and focus_unsupported_kind.
  • duration_seconds number The video's length. On video_too_long.
  • max_duration_seconds number The longest video accepted. On video_too_long.
  • overlap_expires_at string When the previous secret stops working. On webhook_rotation_in_progress.
  • scope string always read_only The key's scope. On key_scope_insufficient.
  • required string always full The scope the call needs. On key_scope_insufficient.
  • collection_id string The Collection that already has the name. On collection_name_taken.
  • collection_kind string The Collection's kind. On collection_kind_mismatch.
  • kind string The kind that was offered. On collection_kind_mismatch.
  • run_id string The Run the Idempotency-Key already belongs to. On idempotency_conflict.
  • reason string A short machine-readable reason, where a code has several.
  • reference_id string Our reference for an unexpected failure, the same as request_id; quote it when reporting it.
  • run object The Run, on a failed Run's body, so its id is kept.
    • id string required
    • kind string required What was run, e.g. video_lookup.
    • status string required one of running, completed, partial, failed partial keeps the completed items and charges for them, up to what the Balance covers; failed charges nothing.
    • created_at string required RFC 3339.
    • completed_at string required nullable Null while the Run is still running.
    • charge_credits integer required What this Run actually cost, in Credits. A stored answer costs the same as a fresh one.
    • list_price_credits integer required The full price of the work asked for, in Credits. Equal to charge_credits unless the Run charged for only part of it.
    • cached boolean required True when a stored result answered without a fresh fetch.
    • progress object 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.
      • stage string required one of keywords, searching, reading_creators, filtering, analysing, writing_digest
      • keywords integer value at least 0
      • creators integer value at least 0
      • creators_read integer value at least 0
      • searches integer value at least 0
      • found integer value at least 0
      • judged integer value at least 0
      • kept integer value at least 0
      • dropped_off_topic integer value at least 0
      • dropped_unsure integer value at least 0
      • shortlisted integer value at least 0
      • analysed integer value at least 0
      • updated_at string required
  • error object The same problem, nested, on a failed Run's body.

503 · Example

{
  "type": "https://www.shortsintel.com/docs/reference/errors/source_unavailable",
  "title": "Source unavailable",
  "status": 503,
  "code": "source_unavailable",
  "detail": "The tiktok/video source is unavailable right now.",
  "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
}

This call creates a Run. With wait it holds the response open until the Run finishes or the wait runs out, then answers with the finished result or 202 and the running Run. Poll GET /v1/runs/{id} until it settles; re-reading a Run is free.

  • Runs: How a call becomes a Run, waiting inline, polling and free re-reads.
  • Pricing and estimates: Credits, estimates and why a cached result costs the same as a fresh one.
  • Ads: Search Meta's, TikTok's and Google's ad libraries: the filters, what each Ad carries, the winner Score, Ad analysis, what is stored, and what a search costs.

Request samples

Use ShortsIntel to look up a Google Ad.

- creative_id: creative_id_example
- analyze: true

Tell me what it will cost before you run it, then summarise what you find.

If you don't have ShortsIntel tools, don't guess: read https://www.shortsintel.com/agents.md, follow it to connect, then retry this request.

200 · The Run finished inside the wait budget: `{ run, result }`.

{
  "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": "google",
      "id": "CR12688769706757193729",
      "url": "https://adstransparency.google.com/advertiser/AR18378488041124659201/creative/CR12688769706757193729",
      "advertiser": {
        "id": "AR18378488041124659201",
        "name": "Northpeak Outdoor GmbH"
      },
      "is_active": true,
      "first_shown": "2026-06-20T18:21:31.000Z",
      "last_shown": "2026-11-06T22:14:25.000Z",
      "placements": [
        "youtube"
      ],
      "creative": {
        "title": "New winter gear, in store now.",
        "body": "Free returns on every order.",
        "cta": null,
        "link_url": "https://www.example.com/winter",
        "format": "video",
        "image_urls": [],
        "video_urls": [],
        "thumbnail_urls": []
      },
      "reach": {
        "impressions": "10000-15000",
        "spend": null,
        "currency": null,
        "audience": null
      },
      "kind": "commercial",
      "media_type": "video",
      "countries": [
        "DE"
      ],
      "variations": [
        {
          "headline": "New winter gear, in store now.",
          "description": "Free returns on every order.",
          "all_text": null,
          "destination_url": "https://www.example.com/winter",
          "visible_url": "example.com",
          "image_urls": [],
          "video_id": "dQw4w9WgXcQ",
          "youtube_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
        }
      ],
      "archived": true,
      "removed_from_library": false,
      "removed_at": null
    },
    "as_of": "2026-11-07T09:12:58.104Z"
  }
}

200 · With `estimate=true`: the price, no Run, no charge.

{
  "estimate_credits": 3,
  "cached": false
}