{"openapi":"3.1.0","info":{"title":"Kontext Video API","version":"2.8.0","description":"Analyze long-form video and serve ads over it: upload a video, read its time-aware analysis, and fetch the ad slots to render."},"servers":[{"url":"https://whaletv.develop.kontext.ai"}],"security":[{"bearerAuth":[]}],"paths":{"/v1/ads":{"get":{"summary":"Video ads as a VMAP/VAST ad tag","operationId":"getAds","tags":["Ads"],"description":"The ad tag: returns the ads to render over a video, addressed by `title_id`.\n\n- **Response** — a standard VMAP playlist: one ad break per slot, each scheduled at its offset on the video timeline, embedding inline VAST 4.2. Currently every break is a non-linear overlay delivered as an `<IFrameResource>` iframe URL; further ad kinds arrive as their VMAP break types.\n- **Request** — fields ride in the query string, named after the IAB's standardized VAST 4.x macros, so an existing player tag drops in.\n- **Extension** — the one non-standard part. Each overlay carries the facts VAST can't express natively, as attributes on a `<kontext:Overlay>` element (namespace `urn:kontext:vast-ext:1.0`) inside the creative's `<CreativeExtensions>` — co-located with the inline VAST creative it describes, so everything for a slot is in one node:\n\n```xml\n<CreativeExtension type=\"kontext-overlay\">\n  <kontext:Overlay xmlns:kontext=\"urn:kontext:vast-ext:1.0\"\n    sessionId=\"a665c4c1-2825-4ba7-a924-8abd136045d1\" index=\"0\"\n    position=\"bottom\" endMs=\"57200\"/>\n</CreativeExtension>\n```\n\n  - `position` — pin the overlay to this edge of the player: `top` or `bottom`.\n  - `endMs` — remove the overlay at this timeline offset (hard stop, in ms). VAST's own `minSuggestedDuration` is only a display floor — `endMs` is authoritative.\n  - `sessionId`, `index` — this ad's address within the playback session (already baked into the iframe URL; useful for logging and debugging).\n\n#### Overlay iframe lifecycle\n\nThe `<IFrameResource>` URL serves a creative only once it is ready. Because the ad tag is returned immediately, before creative generation completes, the URL responds with `404` and an empty body while a slot is still generating or has resolved to no ad. Embedders should render the iframe hidden and reveal it on its `load` event: a ready creative is displayed, while an empty `404` remains invisible. This prevents a not-yet-ready slot from briefly flashing over the video.\n\nAn empty playlist (no ad breaks) means there are no ads for this playback.","parameters":[{"name":"title_id","in":"query","required":true,"schema":{"type":"string"},"description":"The video to serve ads over: the title id returned by POST /v1/upload. Not the publisher's own content id — pass that in content_id."},{"name":"ifa","in":"query","required":false,"schema":{"type":"string"},"description":"Device advertising id — the VAST [IFA] macro. The identity used when no first-party user_id is sent. One of ifa / user_id is required."},{"name":"user_id","in":"query","required":false,"schema":{"type":"string"},"description":"First-party end-user id — the preferred identity for personalized selection (a viewer, where the ifa is a device). One of ifa / user_id is required."},{"name":"sz","in":"query","required":false,"schema":{"type":"string"},"example":"1280,720","description":"Player size as WxH or W,H (the comma form the VAST [PLAYERSIZE] macro expands to). An unparseable value is ignored."},{"name":"cta_mode","in":"query","required":false,"schema":{"type":"string","enum":["button","qr"]},"description":"How the overlay renders its CTA. \"qr\" (default) for TV/cast surfaces; \"button\" posts a click to the player."},{"name":"max_slots","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":7},"description":"Cap on the number of ad breaks returned (keeps the safest, then longest). Absent → 7."},{"name":"ifatype","in":"query","required":false,"schema":{"type":"string"},"description":"IFA type — the VAST [IFATYPE] macro. Accepted as pass-through (recorded, not yet used by selection)."},{"name":"content_id","in":"query","required":false,"schema":{"type":"string"},"description":"Publisher content id — the VAST [CONTENTID] macro. Pass-through."},{"name":"gdpr","in":"query","required":false,"schema":{"type":"string"},"description":"Whether GDPR applies (1/0). Pass-through consent signal."},{"name":"gdpr_consent","in":"query","required":false,"schema":{"type":"string"},"description":"IAB TCF consent string — the VAST [GDPRCONSENT] macro. Pass-through."},{"name":"us_privacy","in":"query","required":false,"schema":{"type":"string"},"description":"IAB US Privacy (CCPA) string. Pass-through."},{"name":"gpp","in":"query","required":false,"schema":{"type":"string"},"description":"IAB Global Privacy Platform string — the VAST [GPPSTRING] macro. Pass-through."},{"name":"gpp_sid","in":"query","required":false,"schema":{"type":"string"},"description":"GPP section ids. Pass-through."},{"name":"limit_ad_tracking","in":"query","required":false,"schema":{"type":"string"},"description":"Limit-ad-tracking flag (1/0) — the VAST [LIMITADTRACKING] macro. Pass-through."}],"responses":{"200":{"description":"VMAP playlist with inline VAST 4.2","content":{"application/xml":{"schema":{"type":"string"},"examples":{"one-ad-break":{"summary":"One overlay ad break","value":"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<vmap:VMAP xmlns:vmap=\"http://www.iab.net/videosuite/vmap\" version=\"1.0\">\n  <vmap:AdBreak breakType=\"nonlinear\" breakId=\"slot-0\" timeOffset=\"00:00:47.200\">\n    <vmap:AdSource id=\"0\" allowMultipleAds=\"false\" followRedirects=\"false\">\n      <vmap:VASTAdData>\n        <VAST version=\"4.2\" xmlns=\"http://www.iab.com/VAST\">\n          <Ad id=\"slot-0\">\n            <InLine>\n              <AdSystem version=\"1.0\">Kontext</AdSystem>\n              <Impression/>\n              <AdServingId>a665c4c1-2825-4ba7-a924-8abd136045d1-0</AdServingId>\n              <AdTitle>Kontext overlay 0</AdTitle>\n              <Creatives>\n                <Creative id=\"slot-0-creative\">\n                  <CreativeExtensions>\n                    <CreativeExtension type=\"kontext-overlay\">\n                      <kontext:Overlay xmlns:kontext=\"urn:kontext:vast-ext:1.0\" sessionId=\"a665c4c1-2825-4ba7-a924-8abd136045d1\" index=\"0\" position=\"bottom\" endMs=\"57200\"/>\n                    </CreativeExtension>\n                  </CreativeExtensions>\n                  <NonLinearAds>\n                    <NonLinear width=\"1200\" height=\"130\" minSuggestedDuration=\"00:00:10.000\" scalable=\"false\" maintainAspectRatio=\"false\">\n                      <IFrameResource><![CDATA[https://whaletv.develop.kontext.ai/overlay/demo-123/a665c4c1-2825-4ba7-a924-8abd136045d1/0]]></IFrameResource>\n                    </NonLinear>\n                  </NonLinearAds>\n                  <UniversalAdId idRegistry=\"unknown\">unknown</UniversalAdId>\n                </Creative>\n              </Creatives>\n            </InLine>\n          </Ad>\n        </VAST>\n      </vmap:VASTAdData>\n    </vmap:AdSource>\n  </vmap:AdBreak>\n</vmap:VMAP>"},"empty-playlist":{"summary":"No ads this playback","value":"<?xml version=\"1.0\" encoding=\"UTF-8\"?><vmap:VMAP xmlns:vmap=\"http://www.iab.net/videosuite/vmap\" version=\"1.0\"/>"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/ValidationError"}}}},"/v1/upload":{"post":{"tags":["Titles"],"summary":"Upload a video for analysis","description":"Queue analysis of a video by URL. The video is fetched server-side and processed asynchronously — poll `result_url` until `status` is `ready`.\n\nAccepted container formats: M4V, MKV, MOV, MP4, WEBM","operationId":"upload_upload_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/titles/{title_id}":{"get":{"tags":["Titles"],"summary":"Get Title","description":"Read a title: a lean status while pending/failed, the full result once ready.","operationId":"get_title_titles__title_id__get","parameters":[{"name":"title_id","in":"path","required":true,"schema":{"type":"string","title":"Title Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/TitleResult"},{"$ref":"#/components/schemas/TitleStatus"}],"title":"Response Get Title Titles  Title Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["invalid_request","unauthorized","not_found"]},"message":{"type":"string"}}}}},"BrandSafetyFinding":{"properties":{"category":{"$ref":"#/components/schemas/GarmCategoryLabel","description":"GARM brand-safety category present."},"tier":{"$ref":"#/components/schemas/GarmTier","description":"Severity tier (treatment x context)."},"evidence":{"type":"string","title":"Evidence","description":"Auditable support: a spoken quote or concrete visible content."}},"type":"object","required":["category","tier","evidence"],"title":"BrandSafetyFinding","description":"One GARM brand-safety category found in a scene, with evidence."},"BrandSafetyRollup":{"properties":{"scene_count":{"type":"integer","title":"Scene Count","description":"Total scenes in the title."},"safe_scenes":{"type":"integer","title":"Safe Scenes"},"unsafe_scenes":{"type":"integer","title":"Unsafe Scenes"},"unrated_scenes":{"type":"integer","title":"Unrated Scenes","description":"Scenes with no brand-safety rating (excluded from the safety share)."},"safe_runtime_ms":{"type":"integer","title":"Safe Runtime Ms","description":"Brand-safe screen-time, in ms."},"rated_runtime_ms":{"type":"integer","title":"Rated Runtime Ms","description":"Screen-time that has a brand-safety rating, in ms."},"safety_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Safety Pct","description":"Screen-time-weighted brand-safe share, 0-100; null if unrated."},"tier_counts":{"items":{"$ref":"#/components/schemas/TierCount"},"type":"array","title":"Tier Counts","description":"Unsafe scenes by worst tier, largest screen-time first."},"categories":{"items":{"$ref":"#/components/schemas/CategoryCount"},"type":"array","title":"Categories","description":"All GARM categories summarized; flagged ones first."}},"type":"object","required":["scene_count","safe_scenes","unsafe_scenes","unrated_scenes","safe_runtime_ms","rated_runtime_ms","safety_pct"],"title":"BrandSafetyRollup","description":"Title-level brand-safety (GARM) summary across the title's scenes."},"CategoryCount":{"properties":{"category":{"$ref":"#/components/schemas/GarmCategoryLabel"},"scene_count":{"type":"integer","title":"Scene Count","description":"Scenes flagging this category (0 = clear)."},"runtime_ms":{"type":"integer","title":"Runtime Ms","description":"Screen-time of the flagging scenes, in ms."},"worst_tier":{"anyOf":[{"$ref":"#/components/schemas/GarmTier"},{"type":"null"}],"description":"Worst tier across flagging scenes; null when never flagged."}},"type":"object","required":["category","scene_count","runtime_ms","worst_tier"],"title":"CategoryCount","description":"One GARM category summarized across the title (per-scene detail is in `scenes`)."},"Certainty":{"type":"string","enum":["clear","borderline"],"title":"Certainty","description":"Confidence in a label: 'clear' is unambiguous, 'borderline' is uncertain."},"DialogueLine":{"properties":{"speaker":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Speaker","description":"Speaker label, if known."},"quote":{"type":"string","title":"Quote","description":"Verbatim subtitle text."},"t_ms":{"type":"integer","title":"T Ms","description":"Absolute start time of the line on the title timeline, in ms."}},"type":"object","required":["quote","t_ms"],"title":"DialogueLine","description":"One subtitle line spoken during a scene."},"Emotion":{"properties":{"label":{"type":"string","title":"Label","description":"Emotion label."},"runtime_ms":{"type":"integer","title":"Runtime Ms","description":"On-screen time carrying this emotion, in ms."}},"type":"object","required":["label","runtime_ms"],"title":"Emotion","description":"One dominant emotion of the title, ranked by on-screen time."},"Entity":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Proper name if shown/spoken, else null."},"type":{"$ref":"#/components/schemas/EntityType","description":"Coarse entity kind."},"description":{"type":"string","title":"Description","description":"What it is and any salient attributes."}},"type":"object","required":["type","description"],"title":"Entity","description":"A person/object/brand/etc. present in a scene."},"EntityType":{"type":"string","enum":["person","group","animal","vehicle","product","brand","organization","object","place","text","other"],"title":"EntityType","description":"Kind of on-screen entity."},"Environment":{"type":"string","enum":["indoor","outdoor","other"],"title":"Environment","description":"Whether the scene is set indoors or outdoors."},"GarmCategoryLabel":{"type":"string","enum":["Adult & Explicit Sexual Content","Arms & Ammunition","Crime & Harmful Acts to Individuals and Society, Human Right Violations","Death, Injury or Military Conflict","Online Piracy","Hate Speech & Acts of Aggression","Obscenity and Profanity","Illegal Drugs / Tobacco / e-cigarettes / Vaping / Alcohol","Spam or Harmful Content","Terrorism","Debated Sensitive Social Issue","Misinformation"],"title":"GarmCategoryLabel","description":"Brand-safety category, per the GARM framework."},"GarmTier":{"type":"string","enum":["low_risk","medium_risk","high_risk","floor"],"title":"GarmTier","description":"Brand-safety risk tier (GARM): 'floor', then low / medium / high suitability risk."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"IabGroup":{"properties":{"name":{"type":"string","title":"Name","description":"Tier-1 taxonomy segment."},"sensitive":{"type":"boolean","title":"Sensitive","description":"Whether this whole segment is brand-sensitive."},"coverage_ms":{"type":"integer","title":"Coverage Ms","description":"Screen-time touching any topic in the group."},"topics":{"items":{"$ref":"#/components/schemas/IabTopic"},"type":"array","title":"Topics"}},"type":"object","required":["name","sensitive","coverage_ms"],"title":"IabGroup","description":"A tier-1 taxonomy segment and the topics grouped under it."},"IabRollup":{"properties":{"groups":{"items":{"$ref":"#/components/schemas/IabGroup"},"type":"array","title":"Groups","description":"Tier-1 groups, largest coverage first."},"topic_count":{"type":"integer","title":"Topic Count","description":"Distinct topics across the title."},"tagged_scenes":{"type":"integer","title":"Tagged Scenes","description":"Scenes carrying at least one topic."},"total_scenes":{"type":"integer","title":"Total Scenes","description":"Total scenes considered."}},"type":"object","required":["topic_count","tagged_scenes","total_scenes"],"title":"IabRollup","description":"Title-level IAB topic coverage, grouped by tier-1 segment."},"IabTopic":{"properties":{"id":{"type":"string","title":"Id","description":"IAB Content Taxonomy id."},"name":{"type":"string","title":"Name","description":"Topic name."},"path":{"type":"string","title":"Path","description":"Full ' > '-delimited taxonomy path."},"group":{"type":"string","title":"Group","description":"Tier-1 taxonomy segment the topic groups under."},"sensitive":{"type":"boolean","title":"Sensitive","description":"Brand-sensitive topic (sensitive branch)."},"scene_count":{"type":"integer","title":"Scene Count","description":"Scenes carrying this topic."},"coverage_ms":{"type":"integer","title":"Coverage Ms","description":"Screen-time of those scenes, in ms."},"certainty":{"$ref":"#/components/schemas/Certainty","description":"'clear' if confidently present in at least one scene, else 'borderline'."}},"type":"object","required":["id","name","path","group","sensitive","scene_count","coverage_ms","certainty"],"title":"IabTopic","description":"One IAB topic summarized across the title (per-scene detail is in `scenes`)."},"Scene":{"properties":{"scene_index":{"type":"integer","title":"Scene Index","description":"0-based scene index on the title timeline."},"start_ms":{"type":"integer","title":"Start Ms","description":"Scene start on the title timeline, in ms."},"end_ms":{"type":"integer","title":"End Ms","description":"Scene end on the title timeline, in ms."},"label":{"type":"string","title":"Label","description":"Short scene label."},"description":{"type":"string","title":"Description","description":"What happens in the scene."},"setting":{"anyOf":[{"$ref":"#/components/schemas/Setting"},{"type":"null"}]},"entities":{"items":{"$ref":"#/components/schemas/Entity"},"type":"array","title":"Entities"},"dialogue":{"items":{"$ref":"#/components/schemas/DialogueLine"},"type":"array","title":"Dialogue","description":"Subtitle lines spoken during the scene."},"topics":{"items":{"type":"string"},"type":"array","title":"Topics","description":"Free-text topic keywords for the scene."},"mood":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mood","description":"Dominant mood, if discernible."},"safe":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Safe","description":"Whether the scene is brand-safe (GARM); null if not rated."},"brand_safety_findings":{"items":{"$ref":"#/components/schemas/BrandSafetyFinding"},"type":"array","title":"Brand Safety Findings","description":"GARM findings for the scene (empty if safe)."},"iab_topics":{"items":{"$ref":"#/components/schemas/TopicLabel"},"type":"array","title":"Iab Topics","description":"IAB taxonomy topics detected in the scene."}},"type":"object","required":["scene_index","start_ms","end_ms","label","description"],"title":"Scene","description":"One scene of the title with its description and per-scene classifications."},"Sentiment":{"type":"string","enum":["positive","neutral","negative","mixed"],"title":"Sentiment","description":"Overall emotional lean of the title."},"Setting":{"properties":{"place":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Place","description":"Free-text location, e.g. 'city street'."},"time_of_day":{"anyOf":[{"$ref":"#/components/schemas/TimeOfDay"},{"type":"null"}],"description":"Time of day if discernible."},"environment":{"anyOf":[{"$ref":"#/components/schemas/Environment"},{"type":"null"}],"description":"Indoor/outdoor if discernible."}},"type":"object","title":"Setting","description":"Where a scene takes place."},"Synopsis":{"properties":{"logline":{"type":"string","title":"Logline","description":"One-sentence capture of the whole title."},"synopsis":{"type":"string","title":"Synopsis","description":"2-4 sentence summary of the title."},"themes":{"items":{"type":"string"},"type":"array","title":"Themes","description":"Recurring subjects/themes as keywords."},"sentiment":{"$ref":"#/components/schemas/Sentiment","description":"Overall affective lean of the title."},"emotions":{"items":{"$ref":"#/components/schemas/Emotion"},"type":"array","title":"Emotions","description":"Dominant emotions, strongest (most screen-time) first."}},"type":"object","required":["logline","synopsis","sentiment"],"title":"Synopsis","description":"Whole-title overview: a written synopsis plus an emotion breakdown."},"TierCount":{"properties":{"tier":{"$ref":"#/components/schemas/GarmTier"},"scene_count":{"type":"integer","title":"Scene Count","description":"Scenes whose worst tier is this tier."},"runtime_ms":{"type":"integer","title":"Runtime Ms","description":"Screen-time of those scenes, in ms."}},"type":"object","required":["tier","scene_count","runtime_ms"],"title":"TierCount","description":"Unsafe scenes sharing one worst-case GARM tier: their count + screen-time."},"TimeOfDay":{"type":"string","enum":["dawn","day","dusk","night","other"],"title":"TimeOfDay","description":"Time of day depicted in the scene."},"TitleError":{"properties":{"code":{"type":"string","title":"Code","description":"Stable machine-readable failure code: 'unsupported_media' (the source is not a video we can read — e.g. the URL served a web page, or an unsupported format), 'download_failed' (the source URL could not be downloaded), or 'internal_error' (a fault on our side; retry or contact support)."},"message":{"type":"string","title":"Message","description":"Human-readable explanation of the failure."}},"type":"object","required":["code","message"],"title":"TitleError","description":"Why a title's processing failed — returned when `status` is `failed`."},"TitleResult":{"properties":{"title_id":{"type":"string","title":"Title Id","description":"Opaque title id (the value from upload)."},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","description":"Display title."},"status":{"type":"string","enum":["processing","ready","failed"],"title":"Status","description":"Always 'ready' for this full response; pending/failed titles return TitleStatus."},"duration_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Ms","description":"Title duration in ms, if known."},"synopsis":{"anyOf":[{"$ref":"#/components/schemas/Synopsis"},{"type":"null"}],"description":"Whole-title overview; null until ready."},"brand_safety":{"anyOf":[{"$ref":"#/components/schemas/BrandSafetyRollup"},{"type":"null"}],"description":"Title-level brand-safety (GARM) rollup."},"iab":{"anyOf":[{"$ref":"#/components/schemas/IabRollup"},{"type":"null"}],"description":"Title-level IAB topic coverage rollup."},"scenes":{"items":{"$ref":"#/components/schemas/Scene"},"type":"array","title":"Scenes"}},"type":"object","required":["title_id","title","status","duration_ms"],"title":"TitleResult","description":"Everything we know about a title and its scenes — the ready `GET /v1/titles/{id}` body."},"TitleStatus":{"properties":{"title_id":{"type":"string","title":"Title Id","description":"Opaque title id (the value from upload)."},"status":{"type":"string","enum":["processing","ready","failed"],"title":"Status","description":"'processing' while analysis runs, or 'failed'. Poll until 'ready'."},"result_url":{"type":"string","title":"Result Url","description":"Path to poll for the full result, e.g. /v1/titles/<title_id>."},"progress_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Progress Pct","description":"Best-effort overall completion, 0-100, while `status` is `processing`. May be null early on (before progress can be measured) or when progress is otherwise unknown."},"error":{"anyOf":[{"$ref":"#/components/schemas/TitleError"},{"type":"null"}],"description":"Why processing failed, when `status` is `failed`; null otherwise."}},"type":"object","required":["title_id","status","result_url"],"title":"TitleStatus","description":"Lean status envelope returned while a title is still processing or has failed.\n\nThe full analysis (synopsis, brand_safety, iab, scenes) is returned only once\n`status` is `ready` — see `TitleResult`."},"TopicLabel":{"properties":{"id":{"type":"string","title":"Id","description":"IAB Content Taxonomy id."},"name":{"type":"string","title":"Name","description":"Topic name."},"path":{"type":"string","title":"Path","description":"Full ' > '-delimited taxonomy path."},"evidence":{"type":"string","title":"Evidence","description":"Auditable support: a spoken quote or concrete visible content."},"certainty":{"$ref":"#/components/schemas/Certainty","description":"'clear' if plainly present, else 'borderline'."}},"type":"object","required":["id","name","path","evidence","certainty"],"title":"TopicLabel","description":"One IAB Content Taxonomy topic detected in a scene."},"UploadRequest":{"properties":{"video_url":{"type":"string","maxLength":2083,"minLength":1,"format":"uri","title":"Video Url","description":"Public URL of the source video to analyze."},"title":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Title","description":"Optional display title; taken from the video filename when omitted."}},"type":"object","required":["video_url"],"title":"UploadRequest","description":"Request body for `POST /v1/upload`."},"UploadResponse":{"properties":{"title_id":{"type":"string","title":"Title Id","description":"Opaque id for the title; poll the result endpoint with it."},"status":{"type":"string","enum":["processing","ready","failed"],"title":"Status","description":"Lifecycle status; always 'processing' immediately after upload."},"result_url":{"type":"string","title":"Result Url","description":"Relative path to poll for the result, e.g. /v1/titles/<title_id>."}},"type":"object","required":["title_id","status","result_url"],"title":"UploadResponse","description":"Response for `POST /v1/upload` — analysis has been queued."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"responses":{"Unauthorized":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No title matches the given title_id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ValidationError":{"description":"Request query failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}}}}