Set or clear a tracker's focus
/v1/trackers/{id}/focusSets the Tracker's Focus and judges its latest Sample against it now, as a Run, so sample (a Creator: recent_videos, its newest Videos) already shows the new verdicts. 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. null clears the Focus: reads show every Video again. A kind that cannot take a Focus is 422 focus_unsupported_kind, which lists the kinds that can.
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.
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
| Name | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
id | path | string | Required | — | Tracker id. |
Idempotency-Key | header | string | Optional | — | 1-255 printable ASCII characters. Replaying this key with the same payload returns the original Run (202 while it is still running); a different payload, or a different operation, is a 409 idempotency_conflict. |
estimate | query | boolean | Optional | — | 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. |
Request body
application/json
object
focusobjectrequirednullableThe new Focus, or null to clear it (free).textstringrequiredWhich 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_mentionarray of stringUp 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 againsttext.
Responses
200 OK
{ 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.
any of 2 shapes
Option 1object
trackerobjectrequiredidstringrequiredkindstringrequiredone ofcreator,hashtag,sound,advertiser,keyword,videovideois deprecated (ADR 0024): existing Video Trackers keep working, new ones are refused with 400kind_deprecated.platformstringrequiredmetaortiktokfor an advertiser Tracker.targetstringrequiredintelligencebooleanrequiredWhether each new video (or Ad) the cycle finds is analysed.statestringrequiredone ofactive,paused,deletedlast_cycle_atstringrequirednullablelast_run_idstringrequirednullablecreated_atstringrequiredupdated_atstringrequiredcoveragestringone oflibrary_regions_only,partialGET /v1/trackers/{id}. TikTok advertiser:library_regions_onlywhen 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_notestringThe regions the TikTok ad library covers, besidecoverage.focusobjectThe Tracker's Focus: which Videos are relevant to you. Terms are stored lowercased. Absent when it has none.textstringrequiredmust_mentionarray of stringrequired
sampleobjectOnly on a Tracker with a Focus: its latest Sample through the Focus.atstringrequiredWhen the latest Sample's Snapshot was taken.statsobjectrequiredThe full Sample's stats, unchanged by the Focus.sampled_videosintegerrequiredviews_totalnumberrequiredviews_mediannumberrequirednullableviews_maxnumberrequirednullablelikes_totalnumberrequiredcomments_totalnumberrequiredengagement_ratenumberrequirednullable
videosarray of objectrequiredIn-focus and unjudged Videos; withinclude_off_focus=true(and on a preview) every Video, each withfocus.platformstringrequiredidstringrequiredurlstringrequirednullabledescriptionstringrequiredposted_atstringrequirednullableduration_secondsnumberrequirednullablethumbnail_urlstringrequirednullablesoundobjectrequirednullableidstringrequiredtitlestringrequirednullable
creatorobjectrequirednullableidstringrequiredhandlestringrequirednullablenamestringrequiredfollower_countnumberrequirednullable
snapshotobjectrequirednullableatstringrequiredviewsnumberrequiredlikesnumberrequiredcommentsnumberrequiredsavesnumberrequired
scoresobjectrequirednullableNull when the creator has no baseline yet.outliernumberrequirednullableViews over the creator's median views.outlier_p90numberrequirednullablepercentilenumberrequirednullableWhere this video sits in the creator's own sample, 0-100.velocityobjectrequirednullableviews_per_hournumberrequiredwindowstringrequired
reasonstringrequirednullablealwaysaged_outaged_outwhen the video is over 30 days old and Scores are null.baselineobjectrequiredThe yardstick every Score on this creator is measured against.median_viewsnumberrequiredp90_viewsnumberrequiredengagement_ratenumberrequirednullableposts_per_weeknumberrequirednullablesampleintegerrequiredconfidencestringrequiredone ofhigh,lowsourcestringrequiredone ofvideos,follower_tiercomputed_atstringrequirednullablestalebooleanrequiredTrue past 7 days; the next lookup refreshes it.
coveragestringalwayspartialPresent only where the platform's index is best-effort.focusobjectverdictstringrequiredone ofin_focus,off_focus,unjudgedunjudged: the Video could not be judged (or is not judged yet) and is shown.reasonstringrequired
off_focus_countintegerrequiredVideos hidden as off focus.focusobjectrequiredtotalintegerrequiredVideos read.in_focusintegerrequiredunjudgedintegerrequiredShown, but not counted in focus.summarystringrequired"N of M in focus".statsobjectrequiredStats over the in-focus Videos only.sampled_videosintegerrequiredviews_totalnumberrequiredviews_mediannumberrequirednullableviews_maxnumberrequirednullablelikes_totalnumberrequiredcomments_totalnumberrequiredengagement_ratenumberrequirednullable
recent_videosobjectOnly on a Creator Tracker with a Focus: its newest Videos through the Focus.videosarray of objectrequiredThe Creator's newest Videos, newest first: in-focus and unjudged ones; withinclude_off_focus=trueevery Video, each withfocus.platformstringrequiredidstringrequiredurlstringrequirednullabledescriptionstringrequiredposted_atstringrequirednullableduration_secondsnumberrequirednullablethumbnail_urlstringrequirednullablesoundobjectrequirednullableidstringrequiredtitlestringrequirednullable
creatorobjectrequirednullableidstringrequiredhandlestringrequirednullablenamestringrequiredfollower_countnumberrequirednullable
snapshotobjectrequirednullableatstringrequiredviewsnumberrequiredlikesnumberrequiredcommentsnumberrequiredsavesnumberrequired
scoresobjectrequirednullableNull when the creator has no baseline yet.outliernumberrequirednullableViews over the creator's median views.outlier_p90numberrequirednullablepercentilenumberrequirednullableWhere this video sits in the creator's own sample, 0-100.velocityobjectrequirednullableviews_per_hournumberrequiredwindowstringrequired
reasonstringrequirednullablealwaysaged_outaged_outwhen the video is over 30 days old and Scores are null.baselineobjectrequiredThe yardstick every Score on this creator is measured against.median_viewsnumberrequiredp90_viewsnumberrequiredengagement_ratenumberrequirednullableposts_per_weeknumberrequirednullablesampleintegerrequiredconfidencestringrequiredone ofhigh,lowsourcestringrequiredone ofvideos,follower_tiercomputed_atstringrequirednullablestalebooleanrequiredTrue past 7 days; the next lookup refreshes it.
coveragestringalwayspartialPresent only where the platform's index is best-effort.focusobjectverdictstringrequiredone ofin_focus,off_focus,unjudgedunjudged: the Video could not be judged (or is not judged yet) and is shown.reasonstringrequired
off_focus_countintegerrequiredVideos hidden as off focus.focusobjectrequiredtotalintegerrequiredVideos read.in_focusintegerrequiredunjudgedintegerrequiredShown, but not counted in focus.summarystringrequired"N of M in focus".statsobjectrequiredStats over the in-focus Videos only.sampled_videosintegerrequiredviews_totalnumberrequiredviews_mediannumberrequirednullableviews_maxnumberrequirednullablelikes_totalnumberrequiredcomments_totalnumberrequiredengagement_ratenumberrequirednullable
runobjectrequirednullableThe Run judging the latest Sample under the new Focus, charged per judgment. Null when the Focus was cleared.idstringrequiredkindstringrequiredWhat was run, e.g.video_lookup.statusstringrequiredone ofrunning,completed,partial,failedpartialkeeps the completed items and charges for them, up to what the Balance covers;failedcharges nothing.created_atstringrequiredRFC 3339.completed_atstringrequirednullableNull while the Run is still running.charge_creditsintegerrequiredWhat this Run actually cost, in Credits. A stored answer costs the same as a fresh one.list_price_creditsintegerrequiredThe full price of the work asked for, in Credits. Equal tocharge_creditsunless the Run charged for only part of it.cachedbooleanrequiredTrue when a stored result answered without paying the vendor.progressobjectWhat a running Research has done so far, refreshed as it works:stage(keywords,searching,filtering,analysing,writing_digest) and the counts known by then —keywords,found,kept,dropped_off_topic, andanalysedofshortlisted. A count is absent until its stage produced it. Absent once the Run settles, and on every other kind.stagestringrequiredone ofkeywords,searching,filtering,analysing,writing_digestkeywordsintegervalue at least 0searchesintegervalue at least 0foundintegervalue at least 0judgedintegervalue at least 0keptintegervalue at least 0dropped_off_topicintegervalue at least 0dropped_unsureintegervalue at least 0shortlistedintegervalue at least 0analysedintegervalue at least 0updated_atstringrequired
Option 2objectReturned instead of a Run when
estimate=true. Nothing is charged. Operations with more to say about a quote add members; the two above are always present.estimate_creditsintegerrequiredWhat the call would be charged, in Credits.cachedbooleanrequiredWhether a stored result can already answer. It does not change the price.
200 · `{ 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.
{
"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": []
}
}
}200 · With `estimate=true`: the quote, nothing judged or saved.
{
"estimate_credits": 6,
"cached": false,
"videos": 2,
"to_judge": 2
}401 Unauthorized
missing_authorization, invalid_key, key_revoked or invalid_token.
object
RFC 9457 problem document, served as application/problem+json. Branch on code, never on the prose.
typestringrequiredtitlestringrequiredstatusintegerrequiredcodestringrequiredone ofmissing_authorization,invalid_key,key_revoked,invalid_token,organization_not_selected,organization_access_revoked,connection_revoked,forbidden,invalid_request,unsupported_platform,unsupported_kind,kind_deprecated,focus_unsupported_kind,not_found,video_too_long,idempotency_conflict,run_not_ready,advertiser_ambiguous,insufficient_balance,rate_limit_exceeded,concurrency_limit_exceeded,tracker_limit_exceeded,webhook_limit_exceeded,webhook_rotation_in_progress,collection_limit_exceeded,collection_name_taken,collection_kind_mismatch,media_unavailable,vendor_error,source_unavailable,service_unavailable,internal_errorStable machine-readable code.detailstring
401 · Example
{
"type": "https://www.shortsintel.com/docs/reference/errors/invalid_key",
"title": "Invalid key",
"status": 401,
"code": "invalid_key",
"detail": "That API key does not exist. Keys look like `sk_live_...` and are created in the console."
}402 Payment Required
insufficient_balance — the Balance cannot cover the quote. Nothing is judged or saved.
object
RFC 9457 problem document, served as application/problem+json. Branch on code, never on the prose.
typestringrequiredtitlestringrequiredstatusintegerrequiredcodestringrequiredone ofmissing_authorization,invalid_key,key_revoked,invalid_token,organization_not_selected,organization_access_revoked,connection_revoked,forbidden,invalid_request,unsupported_platform,unsupported_kind,kind_deprecated,focus_unsupported_kind,not_found,video_too_long,idempotency_conflict,run_not_ready,advertiser_ambiguous,insufficient_balance,rate_limit_exceeded,concurrency_limit_exceeded,tracker_limit_exceeded,webhook_limit_exceeded,webhook_rotation_in_progress,collection_limit_exceeded,collection_name_taken,collection_kind_mismatch,media_unavailable,vendor_error,source_unavailable,service_unavailable,internal_errorStable machine-readable code.detailstring
402 · Example
{
"type": "https://www.shortsintel.com/docs/reference/errors/insufficient_balance",
"title": "Insufficient balance",
"status": 402,
"code": "insufficient_balance",
"detail": "Your balance is 0 Credits and this operation needs 6 Credits. Nothing was charged.",
"balance_credits": 0,
"required_credits": 6
}404 Not Found
not_found.
object
RFC 9457 problem document, served as application/problem+json. Branch on code, never on the prose.
typestringrequiredtitlestringrequiredstatusintegerrequiredcodestringrequiredone ofmissing_authorization,invalid_key,key_revoked,invalid_token,organization_not_selected,organization_access_revoked,connection_revoked,forbidden,invalid_request,unsupported_platform,unsupported_kind,kind_deprecated,focus_unsupported_kind,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 Tracker with that id for this Customer."
}409 Conflict
idempotency_conflict — the same Idempotency-Key with a different payload.
object
RFC 9457 problem document, served as application/problem+json. Branch on code, never on the prose.
typestringrequiredtitlestringrequiredstatusintegerrequiredcodestringrequiredone ofmissing_authorization,invalid_key,key_revoked,invalid_token,organization_not_selected,organization_access_revoked,connection_revoked,forbidden,invalid_request,unsupported_platform,unsupported_kind,kind_deprecated,focus_unsupported_kind,not_found,video_too_long,idempotency_conflict,run_not_ready,advertiser_ambiguous,insufficient_balance,rate_limit_exceeded,concurrency_limit_exceeded,tracker_limit_exceeded,webhook_limit_exceeded,webhook_rotation_in_progress,collection_limit_exceeded,collection_name_taken,collection_kind_mismatch,media_unavailable,vendor_error,source_unavailable,service_unavailable,internal_errorStable machine-readable code.detailstring
409 · Example
{
"type": "https://www.shortsintel.com/docs/reference/errors/idempotency_conflict",
"title": "Idempotency conflict",
"status": 409,
"code": "idempotency_conflict",
"detail": "This Idempotency-Key was used with a different payload.",
"run_id": "run_8f2c1ad04b"
}422 Unprocessable Content
focus_unsupported_kind — this kind of Tracker cannot take a Focus.
object
RFC 9457 problem document, served as application/problem+json. Branch on code, never on the prose.
typestringrequiredtitlestringrequiredstatusintegerrequiredcodestringrequiredone ofmissing_authorization,invalid_key,key_revoked,invalid_token,organization_not_selected,organization_access_revoked,connection_revoked,forbidden,invalid_request,unsupported_platform,unsupported_kind,kind_deprecated,focus_unsupported_kind,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
422 · 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.",
"supported_kinds": [
"keyword"
]
}429 Too Many Requests
rate_limit_exceeded, with Retry-After.
object
RFC 9457 problem document, served as application/problem+json. Branch on code, never on the prose.
typestringrequiredtitlestringrequiredstatusintegerrequiredcodestringrequiredone ofmissing_authorization,invalid_key,key_revoked,invalid_token,organization_not_selected,organization_access_revoked,connection_revoked,forbidden,invalid_request,unsupported_platform,unsupported_kind,kind_deprecated,focus_unsupported_kind,not_found,video_too_long,idempotency_conflict,run_not_ready,advertiser_ambiguous,insufficient_balance,rate_limit_exceeded,concurrency_limit_exceeded,tracker_limit_exceeded,webhook_limit_exceeded,webhook_rotation_in_progress,collection_limit_exceeded,collection_name_taken,collection_kind_mismatch,media_unavailable,vendor_error,source_unavailable,service_unavailable,internal_errorStable machine-readable code.detailstring
429 · Example
{
"type": "https://www.shortsintel.com/docs/reference/errors/rate_limit_exceeded",
"title": "Rate limit exceeded",
"status": 429,
"code": "rate_limit_exceeded",
"detail": "60 requests per minute per key. Retry after the number of seconds in `Retry-After`.",
"limit": 60
}Request samples
Use ShortsIntel to set or clear a tracker's focus.
- id: trk_4b1e90c7aa
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: tell me to connect it first. Add the MCP server https://www.shortsintel.com/api/mcp (or install the ShortsIntel plugin), sign in, and retry. Setup guide: https://www.shortsintel.com/docs/mcpcurl -X PUT "https://www.shortsintel.com/v1/trackers/trk_4b1e90c7aa/focus" \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"focus":{"text":"text","must_mention":["must_mention"]}}'const response = await fetch(
"https://www.shortsintel.com/v1/trackers/trk_4b1e90c7aa/focus",
{
method: "PUT",
headers: {
"Authorization": "Bearer sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
"focus": {
"text": "text",
"must_mention": [
"must_mention"
]
}
}),
},
);
if (!response.ok) {
throw new Error(`ShortsIntel ${response.status}`);
}
const data = await response.json();import requests
response = requests.put(
"https://www.shortsintel.com/v1/trackers/trk_4b1e90c7aa/focus",
headers={
"Authorization": "Bearer sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
json={
"focus": {
"text": "text",
"must_mention": [
"must_mention",
],
},
},
)
response.raise_for_status()
data = response.json()Related guides
- Pricing and estimates: Credits, estimates and why a cached result costs the same as a fresh one.
- Trackers: Standing watches on a creator or a Meta or TikTok Advertiser: how a cycle runs, when it reports a change, and how to pause one.