Skip to content

API referenceResearch

List a research's hashtags

GET/v1/research/{id}/hashtags

The hashtags a research surfaced, past the 25 it carries inline. Ordered by video_count by default, or by views. One rollup spans every platform the tag was seen on rather than splitting into a row per platform — a research searches several platforms precisely to find what carries across — so platforms=tiktok means "tags that appeared on TikTok" and the row still counts every video carrying the tag anywhere. video_ids are platform:id if you want the split. Paging, total and as_of work exactly as they do on the videos read. A research that has not finished answers 409 run_not_ready.

Open in Playground(no API Key needed)

Price

Free, forever, filtered or not. Collection is the only thing charged.

Parameters

NameInTypeRequiredDefaultDescription
idpathstringRequired—Research id — the id of the Run that collected it.
platformsquerystringOptional—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.
order_byquerystringone of video_count, viewsOptionalvideo_countvideo_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.
sortquerystringone of asc, descOptionaldescDirection. 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.
limitqueryintegermin 1; max 100Optional25Hashtags per page. Over the maximum, or negative, is a 400 rather than a silent clamp.
offsetqueryintegermin 0Optional0Hashtags to skip. Past the end returns an empty page with the true total.
as_ofquerystringone of run, latestOptionalrunWhich snapshots to read. run (the default) is what the research itself saw, frozen, so the list always agrees with the digest. latest serves the newest snapshot this API holds for each video instead, and the filters and ordering then run over those numbers — a min_ filter under latest means "over that many now". Under latest, outlier and outlier_p90 are recomputed against the research's baseline; velocity and percentile stay as the research measured them. Be aware that latest is uneven until you refresh: a video is only as fresh as the last time anything looked at it, and a video nothing has looked at since keeps the numbers the research recorded rather than coming back empty. POST /research/{id}/refresh brings its refreshable videos (TikTok today) up to date; the rest keep what the research recorded. Every response states the basis it served.

Responses

200 OK

{ items, total, limit, offset, as_of }.

object

  • itemsarray of objectrequired
    • valuestringrequired
    • titlestringnullable
    • platformsarray of stringrequiredEvery platform this tag was observed on in the shortlist. One rollup spans platforms; video_ids are platform:id if you want the split.
    • video_countintegerrequired
    • total_viewsnumberrequired
    • video_idsarray of stringrequired
  • totalintegerrequiredRows matching the filters, before limit and offset.
  • limitintegerrequired
  • offsetintegerrequired
  • as_ofstringrequiredone of run, latestWhich 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.

200 · `{ items, total, limit, offset, as_of }`.

{
  "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"
}

400 Bad Request

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.

object

RFC 9457 problem document, served as application/problem+json. Branch on code, never on the prose.

  • typestringrequired
  • titlestringrequired
  • statusintegerrequired
  • codestringrequiredone of missing_authorization, invalid_key, key_revoked, invalid_token, organization_not_selected, organization_access_revoked, connection_revoked, forbidden, invalid_request, unsupported_platform, unsupported_kind, kind_deprecated, not_found, video_too_long, idempotency_conflict, run_not_ready, advertiser_ambiguous, insufficient_balance, rate_limit_exceeded, concurrency_limit_exceeded, tracker_limit_exceeded, webhook_limit_exceeded, webhook_rotation_in_progress, collection_limit_exceeded, collection_name_taken, collection_kind_mismatch, media_unavailable, vendor_error, source_unavailable, service_unavailable, internal_errorStable machine-readable code.
  • detailstring

400 · Example

{
  "type": "https://www.shortsintel.com/docs/reference/errors/invalid_request",
  "title": "Invalid request",
  "status": 400,
  "code": "invalid_request",
  "detail": "`limit` must be an integer between 1 and 100, and `offset` a non-negative integer."
}

401 Unauthorized

missing_authorization, invalid_key, key_revoked or invalid_token.

object

RFC 9457 problem document, served as application/problem+json. Branch on code, never on the prose.

  • typestringrequired
  • titlestringrequired
  • statusintegerrequired
  • codestringrequiredone of missing_authorization, invalid_key, key_revoked, invalid_token, organization_not_selected, organization_access_revoked, connection_revoked, forbidden, invalid_request, unsupported_platform, unsupported_kind, kind_deprecated, not_found, video_too_long, idempotency_conflict, run_not_ready, advertiser_ambiguous, insufficient_balance, rate_limit_exceeded, concurrency_limit_exceeded, tracker_limit_exceeded, webhook_limit_exceeded, webhook_rotation_in_progress, collection_limit_exceeded, collection_name_taken, collection_kind_mismatch, media_unavailable, vendor_error, source_unavailable, service_unavailable, internal_errorStable machine-readable code.
  • detailstring

401 · Example

{
  "type": "https://www.shortsintel.com/docs/reference/errors/invalid_key",
  "title": "Invalid key",
  "status": 401,
  "code": "invalid_key",
  "detail": "That API key does not exist. Keys look like `sk_live_...` and are created in the console."
}

404 Not Found

not_found.

object

RFC 9457 problem document, served as application/problem+json. Branch on code, never on the prose.

  • typestringrequired
  • titlestringrequired
  • statusintegerrequired
  • codestringrequiredone of missing_authorization, invalid_key, key_revoked, invalid_token, organization_not_selected, organization_access_revoked, connection_revoked, forbidden, invalid_request, unsupported_platform, unsupported_kind, kind_deprecated, not_found, video_too_long, idempotency_conflict, run_not_ready, advertiser_ambiguous, insufficient_balance, rate_limit_exceeded, concurrency_limit_exceeded, tracker_limit_exceeded, webhook_limit_exceeded, webhook_rotation_in_progress, collection_limit_exceeded, collection_name_taken, collection_kind_mismatch, media_unavailable, vendor_error, source_unavailable, service_unavailable, internal_errorStable machine-readable code.
  • detailstring

404 · 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."
}

409 Conflict

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.

object

RFC 9457 problem document, served as application/problem+json. Branch on code, never on the prose.

  • typestringrequired
  • titlestringrequired
  • statusintegerrequired
  • codestringrequiredone of missing_authorization, invalid_key, key_revoked, invalid_token, organization_not_selected, organization_access_revoked, connection_revoked, forbidden, invalid_request, unsupported_platform, unsupported_kind, kind_deprecated, not_found, video_too_long, idempotency_conflict, run_not_ready, advertiser_ambiguous, insufficient_balance, rate_limit_exceeded, concurrency_limit_exceeded, tracker_limit_exceeded, webhook_limit_exceeded, webhook_rotation_in_progress, collection_limit_exceeded, collection_name_taken, collection_kind_mismatch, media_unavailable, vendor_error, source_unavailable, service_unavailable, internal_errorStable machine-readable code.
  • detailstring

409 · Example

{
  "type": "https://www.shortsintel.com/docs/reference/errors/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."
}

Request samples

curl "https://www.shortsintel.com/v1/research/id_example/hashtags?platforms=tiktok%2Cyoutube&order_by=video_count&sort=desc&limit=25&offset=0&as_of=run" \
  -H "Authorization: Bearer sk_live_YOUR_KEY"
  • Research: How an intent becomes a digest, why a research id is a run id, and how to re-slice what you collected for free instead of paying for it twice.