{"openapi":"3.1.0","info":{"title":"Video Ads API","version":"0.1.0","description":"Request personalized video ad placements and render the overlay creatives shown over the player."},"servers":[{"url":"https://eiger.develop.kontext.so"}],"security":[{"bearerAuth":[]}],"paths":{"/v1/ads":{"post":{"summary":"Request ad placements","operationId":"getAds","tags":["ads"],"description":"Returns the overlay placements for a video, identified by `title_id`. Each placement carries a stable `iframe_url` to embed at its time slot. An empty `slots` array means there are no overlays for this playback.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdsRequest"}}}},"responses":{"200":{"description":"Ad slots to render over the video timeline (empty slots = no overlays)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdsResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"422":{"$ref":"#/components/responses/ValidationError"}}}},"/overlay/{slotId}":{"get":{"summary":"Render a creative overlay","operationId":"getOverlay","tags":["overlay"],"security":[],"description":"Renders the ad creative for a placement as an HTML document, designed to be embedded as a cross-origin `<iframe>` over the video player.\n\nWhen the viewer clicks the call-to-action, the creative sends a message to the parent window so the player can open the destination and coordinate playback (for example, pausing the video):\n\n```json\n{ \"type\": \"kontext.ad.click\", \"version\": 1, \"slot_id\": \"demo-123-0\", \"cta_url\": \"https://example.com/landing\" }\n```\n\nReacting to the click is the integrating player's responsibility: it must listen for this message, validate `event.origin` against this host, then open `cta_url` (it may also pause and resume playback). Without a listener the call-to-action is inert.","parameters":[{"name":"slotId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The ad creative.","content":{"text/html":{"schema":{"type":"string"}}}},"404":{"description":"No creative is available for this placement; empty body, so the iframe renders nothing."}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"AdsRequest":{"type":"object","required":["title_id"],"properties":{"title_id":{"type":"string","description":"Title id returned by the video-analysis POST /v1/upload"},"context":{"type":"object","properties":{"player_width":{"type":"integer"},"player_height":{"type":"integer"}}}}},"AdSlot":{"type":"object","required":["slot_id","start_ms","end_ms","placement","iframe_url","width","height","position"],"properties":{"slot_id":{"type":"string","example":"demo-123-0"},"start_ms":{"type":"integer","description":"Slot start offset in the video, milliseconds","example":47200},"end_ms":{"type":"integer","description":"Slot end offset in the video, milliseconds","example":57200},"placement":{"type":"string","enum":["overlay"],"example":"overlay"},"iframe_url":{"type":"string","format":"uri","description":"Embed as a cross-origin iframe over the player — a /overlay/{slotId} URL on this host","example":"https://example.com/overlay/demo-123-0"},"width":{"type":"integer","example":640},"height":{"type":"integer","example":100},"position":{"type":"string","enum":["top","bottom"],"description":"Overlay position (top/bottom edge of the video), from video analysis","example":"bottom"}}},"AdsResponse":{"type":"object","required":["title_id","slots"],"properties":{"title_id":{"type":"string","example":"demo-123"},"slots":{"type":"array","items":{"$ref":"#/components/schemas/AdSlot"}}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["invalid_json","invalid_request","unauthorized"]},"message":{"type":"string"}}}}}},"responses":{"BadRequest":{"description":"Malformed request (e.g. invalid JSON)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ValidationError":{"description":"Request body failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}