{"openapi":"3.0.3","info":{"title":"XonaPlay API","version":"0.31.0","description":"Public `/v1` surface: videos, playback, direct uploads, live streams and webhooks. All JSON on the wire is snake_case (see the guide for the full conventions). Not shown: admin/internal routes."},"servers":[{"url":"https://api.xonaplay.com"}],"tags":[{"name":"Videos","description":"List, read, update and delete videos, and get a signed playback link."},{"name":"Uploads","description":"Open a direct upload session, PUT the parts to storage, then confirm."},{"name":"Live","description":"List live streams and get a signed playback link for one that is on air."},{"name":"Playback","description":"Signed HLS/embed links for a video or live stream — the only way to play content."},{"name":"Webhooks","description":"Register endpoints for video and live events, and inspect deliveries."}],"paths":{"/v1/live":{"get":{"operationId":"getV1Live","tags":["Live"],"summary":"List live streams","description":"Live streams of the authenticated workspace, merged from every engine (platform custody and BYO), newest first. Paginated.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"Paginated list of live streams.","content":{"application/json":{"schema":{"type":"object","required":["status","data","meta"],"properties":{"status":{"const":"ok","type":"string"},"data":{"type":"array","items":{"description":"A live stream, regardless of custody (platform or BYO engine).","type":"object","required":["id","short_id","name","slug","status","visibility","playback_security","stream_key","ingest","dvr_enabled","dvr_window_minutes","replay_enabled","replay_unlisted","viewers","total_views","custody","engine","storage_profile","links","last_live_at","created_at","updated_at"],"properties":{"id":{"format":"uuid","type":"string"},"short_id":{"anyOf":[{"type":"null"},{"type":"string"}]},"name":{"type":"string"},"slug":{"type":"string"},"status":{"anyOf":[{"const":"idle","type":"string"},{"const":"live","type":"string"},{"const":"ended","type":"string"}]},"visibility":{"anyOf":[{"const":"public","type":"string"},{"const":"private","type":"string"},{"const":"unlisted","type":"string"}]},"playback_security":{"anyOf":[{"const":"inherit","type":"string"},{"const":"open","type":"string"},{"const":"protected","type":"string"},{"const":"strict","type":"string"},{"const":"maximum","type":"string"}]},"stream_key":{"description":"OBS \"Stream Key\", in clear text for the owner.","type":"string"},"ingest":{"type":"object","required":["primary","backup"],"properties":{"primary":{"anyOf":[{"type":"null"},{"type":"string"}]},"backup":{"anyOf":[{"type":"null"},{"type":"string"}]}}},"dvr_enabled":{"type":"boolean"},"dvr_window_minutes":{"anyOf":[{"const":30,"type":"number"},{"const":60,"type":"number"},{"const":120,"type":"number"},{"const":240,"type":"number"}]},"replay_enabled":{"type":"boolean"},"replay_unlisted":{"type":"boolean"},"viewers":{"description":"Concurrent viewers right now.","anyOf":[{"format":"integer","default":0,"type":"string"},{"description":"Concurrent viewers right now.","type":"integer"}]},"total_views":{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]},"custody":{"anyOf":[{"const":"api","type":"string"},{"const":"engine","type":"string"}]},"engine":{"anyOf":[{"type":"null"},{"type":"object","required":["id","name","mode","status","base_url"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"mode":{"anyOf":[{"const":"managed","type":"string"},{"const":"byo","type":"string"}]},"status":{"anyOf":[{"const":"online","type":"string"},{"const":"offline","type":"string"},{"const":"maintenance","type":"string"}]},"base_url":{"type":"string"}}}]},"storage_profile":{"anyOf":[{"type":"null"},{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}}]},"links":{"type":"object","required":["player","hls","poster"],"properties":{"player":{"format":"uri","type":"string"},"hls":{"format":"uri","type":"string"},"poster":{"anyOf":[{"type":"null"},{"format":"uri","type":"string"}]}}},"last_live_at":{"anyOf":[{"type":"null"},{"format":"date-time","type":"string"}]},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"}}}},"meta":{"type":"object","required":["total","page","per_page","last_page"],"properties":{"total":{"description":"Total items after filtering.","anyOf":[{"format":"integer","default":0,"type":"string"},{"description":"Total items after filtering.","type":"integer"}]},"page":{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]},"per_page":{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]},"last_page":{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"parameters":[{"schema":{"type":"string","pattern":"^[0-9]{1,6}$"},"in":"query","name":"page","required":false},{"schema":{"type":"string","pattern":"^[0-9]{1,4}$"},"in":"query","name":"per_page","required":false},{"schema":{"type":"string","maxLength":255},"in":"query","name":"q","required":false}]}},"/v1/live/{stream_id}":{"get":{"operationId":"getV1LiveByStream_id","tags":["Live"],"summary":"Get a live stream","description":"Accepts either the `id` (UUID) or the `short_id`.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"The live stream.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"description":"A live stream, regardless of custody (platform or BYO engine).","type":"object","required":["id","short_id","name","slug","status","visibility","playback_security","stream_key","ingest","dvr_enabled","dvr_window_minutes","replay_enabled","replay_unlisted","viewers","total_views","custody","engine","storage_profile","links","last_live_at","created_at","updated_at"],"properties":{"id":{"format":"uuid","type":"string"},"short_id":{"anyOf":[{"type":"null"},{"type":"string"}]},"name":{"type":"string"},"slug":{"type":"string"},"status":{"anyOf":[{"const":"idle","type":"string"},{"const":"live","type":"string"},{"const":"ended","type":"string"}]},"visibility":{"anyOf":[{"const":"public","type":"string"},{"const":"private","type":"string"},{"const":"unlisted","type":"string"}]},"playback_security":{"anyOf":[{"const":"inherit","type":"string"},{"const":"open","type":"string"},{"const":"protected","type":"string"},{"const":"strict","type":"string"},{"const":"maximum","type":"string"}]},"stream_key":{"description":"OBS \"Stream Key\", in clear text for the owner.","type":"string"},"ingest":{"type":"object","required":["primary","backup"],"properties":{"primary":{"anyOf":[{"type":"null"},{"type":"string"}]},"backup":{"anyOf":[{"type":"null"},{"type":"string"}]}}},"dvr_enabled":{"type":"boolean"},"dvr_window_minutes":{"anyOf":[{"const":30,"type":"number"},{"const":60,"type":"number"},{"const":120,"type":"number"},{"const":240,"type":"number"}]},"replay_enabled":{"type":"boolean"},"replay_unlisted":{"type":"boolean"},"viewers":{"description":"Concurrent viewers right now.","anyOf":[{"format":"integer","default":0,"type":"string"},{"description":"Concurrent viewers right now.","type":"integer"}]},"total_views":{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]},"custody":{"anyOf":[{"const":"api","type":"string"},{"const":"engine","type":"string"}]},"engine":{"anyOf":[{"type":"null"},{"type":"object","required":["id","name","mode","status","base_url"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"mode":{"anyOf":[{"const":"managed","type":"string"},{"const":"byo","type":"string"}]},"status":{"anyOf":[{"const":"online","type":"string"},{"const":"offline","type":"string"},{"const":"maintenance","type":"string"}]},"base_url":{"type":"string"}}}]},"storage_profile":{"anyOf":[{"type":"null"},{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}}]},"links":{"type":"object","required":["player","hls","poster"],"properties":{"player":{"format":"uri","type":"string"},"hls":{"format":"uri","type":"string"},"poster":{"anyOf":[{"type":"null"},{"format":"uri","type":"string"}]}}},"last_live_at":{"anyOf":[{"type":"null"},{"format":"date-time","type":"string"}]},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"404":{"description":"No live stream with that id or short_id (`NOT_FOUND`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"parameters":[{"schema":{"type":"string","minLength":1},"in":"path","name":"stream_id","required":true}]}},"/v1/live/{stream_id}/playback":{"get":{"operationId":"getV1LiveByStream_idPlayback","tags":["Playback"],"summary":"Get signed playback links for a live stream","description":"The ONLY way to play a live stream: returns a signed `hls_url`/`embed_url` pair whose shape depends on the workspace playback security level. No credential required for public `open`/`protected` content; otherwise a secret key or session is required. On a fatal player error, call this again (see the \"Reload\" rule in the guide) instead of reusing the old URL.","security":[{},{"bearerAuth":[]}],"responses":{"200":{"description":"Signed playback links.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"description":"Signed playback links for a live stream.","type":"object","required":["stream_id","short_id","hls_url","poster_url","embed_url","expires_at","security","status"],"properties":{"stream_id":{"format":"uuid","type":"string"},"short_id":{"anyOf":[{"type":"null"},{"type":"string"}]},"hls_url":{"format":"uri","type":"string"},"poster_url":{"anyOf":[{"type":"null"},{"format":"uri","type":"string"}]},"embed_url":{"format":"uri","type":"string"},"expires_at":{"anyOf":[{"type":"null"},{"format":"date-time","type":"string"}]},"security":{"anyOf":[{"const":"inherit","type":"string"},{"const":"open","type":"string"},{"const":"protected","type":"string"},{"const":"strict","type":"string"},{"const":"maximum","type":"string"}]},"status":{"anyOf":[{"const":"idle","type":"string"},{"const":"live","type":"string"},{"const":"ended","type":"string"}]}}}}}}}},"401":{"description":"A secret key or session is required for this content (`KEY_REQUIRED`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"403":{"description":"Domain not allowed (`DOMAIN_NOT_ALLOWED`), workspace unavailable (`WORKSPACE_UNAVAILABLE`), or viewer banned (`ACCESS_DENIED`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"404":{"description":"No live stream with that id or short_id (`NOT_FOUND`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"409":{"description":"The stream is not live right now (`LIVE_NOT_ACTIVE`); retry later.","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"429":{"description":"Too many requests; retry after `Retry-After` (`RATE_LIMITED`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"parameters":[{"schema":{"type":"string","minLength":1},"in":"path","name":"stream_id","required":true},{"schema":{"type":"string"},"in":"query","name":"viewer_id","required":false}]}},"/v1/videos":{"get":{"operationId":"getV1Videos","tags":["Videos"],"summary":"List videos","description":"Videos of the authenticated workspace, merged from every engine (platform custody and BYO), newest first. Paginated.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"Paginated list of videos.","content":{"application/json":{"schema":{"type":"object","required":["status","data","meta"],"properties":{"status":{"const":"ok","type":"string"},"data":{"type":"array","items":{"description":"A video, regardless of custody (platform or BYO engine).","type":"object","required":["id","short_id","title","slug","description","status","visibility","playback_security","delivery","source_type","duration_sec","width","height","size_original_bytes","size_processed_bytes","qualities","custody","engine","compute_engine","storage_profile","links","metadata","created_at","updated_at"],"properties":{"id":{"format":"uuid","type":"string"},"short_id":{"anyOf":[{"type":"null"},{"type":"string"}]},"title":{"type":"string"},"slug":{"type":"string"},"description":{"anyOf":[{"type":"null"},{"type":"string"}]},"status":{"anyOf":[{"const":"uploading","type":"string"},{"const":"queued","type":"string"},{"const":"processing","type":"string"},{"const":"partial","type":"string"},{"const":"ready","type":"string"},{"const":"error","type":"string"},{"const":"deleting","type":"string"}]},"visibility":{"anyOf":[{"const":"public","type":"string"},{"const":"private","type":"string"},{"const":"unlisted","type":"string"}]},"playback_security":{"anyOf":[{"const":"inherit","type":"string"},{"const":"open","type":"string"},{"const":"protected","type":"string"},{"const":"strict","type":"string"},{"const":"maximum","type":"string"}]},"delivery":{"description":"`hls` (default): XonaPlay renders adaptive HLS from the original. `original`: no transcoding at all — the untouched original is what you play and download. The original is always kept as uploaded in both cases.","anyOf":[{"const":"hls","type":"string"},{"const":"original","type":"string"}]},"source_type":{"anyOf":[{"const":"upload","type":"string"},{"const":"live","type":"string"},{"const":"url","type":"string"}]},"duration_sec":{"anyOf":[{"type":"null"},{"type":"number"}]},"width":{"anyOf":[{"type":"null"},{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]}]},"height":{"anyOf":[{"type":"null"},{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]}]},"size_original_bytes":{"anyOf":[{"type":"null"},{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]}]},"size_processed_bytes":{"anyOf":[{"type":"null"},{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]}]},"qualities":{"description":"Renditions available, e.g. [\"FHD\",\"HD\",\"SD\",\"LD\"].","type":"array","items":{"type":"string"}},"custody":{"anyOf":[{"const":"api","type":"string"},{"const":"engine","type":"string"}]},"engine":{"anyOf":[{"type":"null"},{"type":"object","required":["id","name","mode","status","base_url"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"mode":{"anyOf":[{"const":"managed","type":"string"},{"const":"byo","type":"string"}]},"status":{"anyOf":[{"const":"online","type":"string"},{"const":"offline","type":"string"},{"const":"maintenance","type":"string"}]},"base_url":{"type":"string"}}}]},"compute_engine":{"anyOf":[{"type":"null"},{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}}]},"storage_profile":{"anyOf":[{"type":"null"},{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}}]},"links":{"type":"object","required":["player","hls","poster"],"properties":{"player":{"format":"uri","type":"string"},"hls":{"format":"uri","type":"string"},"poster":{"anyOf":[{"type":"null"},{"format":"uri","type":"string"}]}}},"metadata":{"description":"Free-form (poster override, ffprobe, description, …).","type":"object","patternProperties":{"^(.*)$":{}}},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"}}}},"meta":{"type":"object","required":["total","page","per_page","last_page"],"properties":{"total":{"description":"Total items after filtering.","anyOf":[{"format":"integer","default":0,"type":"string"},{"description":"Total items after filtering.","type":"integer"}]},"page":{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]},"per_page":{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]},"last_page":{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"parameters":[{"schema":{"type":"string","pattern":"^[0-9]{1,6}$"},"in":"query","name":"page","required":false},{"schema":{"type":"string","pattern":"^[0-9]{1,4}$"},"in":"query","name":"per_page","required":false},{"schema":{"type":"string","maxLength":255},"in":"query","name":"q","required":false},{"schema":{"type":"string","maxLength":32},"in":"query","name":"status","required":false}]}},"/v1/videos/imports":{"post":{"operationId":"postV1VideosImports","tags":["Uploads"],"summary":"Import a video from a URL","description":"XonaPlay downloads the file from `source_url` server-to-server (redirects allowed, public HTTPS only) and stores it untouched as the original — your server never handles the bytes. With `delivery: \"original\"` the video is ready as soon as the download finishes; with `\"hls\"` (default) rendering starts then. You get `video.ready` or `video.failed`.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"Import queued.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"description":"The import was queued. XonaPlay downloads the file server-to-server and stores it untouched; you get `video.ready` (or `video.failed`) when it is done.","type":"object","required":["video_id","import_id","status"],"properties":{"video_id":{"format":"uuid","type":"string"},"import_id":{"format":"uuid","type":"string"},"status":{"const":"uploading","type":"string"}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"402":{"description":"Plan limit reached (`PLAN_LIMIT`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"422":{"description":"Invalid or not allowed `source_url` (`VALIDATION_FAILED`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title","source_url"],"properties":{"title":{"minLength":1,"maxLength":512,"type":"string"},"source_url":{"minLength":8,"maxLength":2048,"type":"string"},"file_name":{"minLength":1,"maxLength":255,"type":"string"},"delivery":{"anyOf":[{"const":"hls","type":"string"},{"const":"original","type":"string"}]},"storage_profile_id":{"type":"string"},"compute_engine_id":{"type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","required":["title","source_url"],"properties":{"title":{"minLength":1,"maxLength":512,"type":"string"},"source_url":{"minLength":8,"maxLength":2048,"type":"string"},"file_name":{"minLength":1,"maxLength":255,"type":"string"},"delivery":{"anyOf":[{"const":"hls","type":"string"},{"const":"original","type":"string"}]},"storage_profile_id":{"type":"string"},"compute_engine_id":{"type":"string"}}}},"text/plain":{"schema":{"type":"object","required":["title","source_url"],"properties":{"title":{"minLength":1,"maxLength":512,"type":"string"},"source_url":{"minLength":8,"maxLength":2048,"type":"string"},"file_name":{"minLength":1,"maxLength":255,"type":"string"},"delivery":{"anyOf":[{"const":"hls","type":"string"},{"const":"original","type":"string"}]},"storage_profile_id":{"type":"string"},"compute_engine_id":{"type":"string"}}}}}}}},"/v1/videos/uploads":{"post":{"operationId":"postV1VideosUploads","tags":["Uploads"],"summary":"Create an upload session","description":"Starts a multipart direct upload straight to storage: creates the video (status `uploading`) and returns one pre-signed PUT URL per part.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"Upload session created.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"description":"A multipart direct-upload session, ready for the browser to PUT parts to.","type":"object","required":["video_id","session_id","part_size","urls","max_height"],"properties":{"video_id":{"format":"uuid","type":"string"},"session_id":{"format":"uuid","type":"string"},"part_size":{"description":"Bytes per part (multipart PUT).","anyOf":[{"format":"integer","default":0,"type":"string"},{"description":"Bytes per part (multipart PUT).","type":"integer"}]},"urls":{"description":"One pre-signed PUT URL per part, in order.","type":"array","items":{"format":"uri","type":"string"}},"max_height":{"description":"Plan's resolution cap; the pipeline enforces it.","anyOf":[{"format":"integer","default":0,"type":"string"},{"description":"Plan's resolution cap; the pipeline enforces it.","type":"integer"}]}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"422":{"description":"Validation failed (e.g. missing `size_bytes`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title","file_name","size_bytes"],"properties":{"title":{"minLength":1,"maxLength":512,"type":"string"},"file_name":{"minLength":1,"maxLength":255,"type":"string"},"size_bytes":{"minimum":1,"type":"number"},"content_type":{"maxLength":255,"type":"string"},"storage_profile_id":{"type":"string"},"compute_engine_id":{"type":"string"},"delivery":{"anyOf":[{"const":"hls","type":"string"},{"const":"original","type":"string"}]}}}},"multipart/form-data":{"schema":{"type":"object","required":["title","file_name","size_bytes"],"properties":{"title":{"minLength":1,"maxLength":512,"type":"string"},"file_name":{"minLength":1,"maxLength":255,"type":"string"},"size_bytes":{"minimum":1,"type":"number"},"content_type":{"maxLength":255,"type":"string"},"storage_profile_id":{"type":"string"},"compute_engine_id":{"type":"string"},"delivery":{"anyOf":[{"const":"hls","type":"string"},{"const":"original","type":"string"}]}}}},"text/plain":{"schema":{"type":"object","required":["title","file_name","size_bytes"],"properties":{"title":{"minLength":1,"maxLength":512,"type":"string"},"file_name":{"minLength":1,"maxLength":255,"type":"string"},"size_bytes":{"minimum":1,"type":"number"},"content_type":{"maxLength":255,"type":"string"},"storage_profile_id":{"type":"string"},"compute_engine_id":{"type":"string"},"delivery":{"anyOf":[{"const":"hls","type":"string"},{"const":"original","type":"string"}]}}}}}}}},"/v1/videos/uploads/{session_id}":{"delete":{"operationId":"deleteV1VideosUploadsBySession_id","tags":["Uploads"],"summary":"Abort an upload session","description":"Cancels the multipart upload and deletes the pending video.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"Aborted.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"type":"object","required":["aborted"],"properties":{"aborted":{"type":"boolean"}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"404":{"description":"No upload session with that id (`NOT_FOUND`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"parameters":[{"schema":{"type":"string","minLength":1},"in":"path","name":"session_id","required":true}]}},"/v1/videos/uploads/{session_id}/complete":{"post":{"operationId":"postV1VideosUploadsBySession_idComplete","tags":["Uploads"],"summary":"Complete an upload session","description":"Closes the multipart upload (completes it in storage), verifies the total size against what was declared and the plan limits, and queues the video for processing.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"The upload was completed and the video queued.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"description":"The upload session was closed and the video entered the pipeline.","type":"object","required":["video_id","status"],"properties":{"video_id":{"format":"uuid","type":"string"},"status":{"description":"`queued` (delivery `hls`: rendering starts) or `ready` (delivery `original`: playable right away).","type":"string"}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"404":{"description":"No upload session with that id (`NOT_FOUND`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"409":{"description":"The session is already closed, or the uploaded size exceeds what was declared or the plan storage limit.","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"parts":{"type":"array","items":{"type":"object","required":["part_number","etag"],"properties":{"part_number":{"type":"number"},"etag":{"type":"string"}}}}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"parts":{"type":"array","items":{"type":"object","required":["part_number","etag"],"properties":{"part_number":{"type":"number"},"etag":{"type":"string"}}}}}}},"text/plain":{"schema":{"type":"object","properties":{"parts":{"type":"array","items":{"type":"object","required":["part_number","etag"],"properties":{"part_number":{"type":"number"},"etag":{"type":"string"}}}}}}}}},"parameters":[{"schema":{"type":"string","minLength":1},"in":"path","name":"session_id","required":true}]}},"/v1/videos/{video_id}":{"get":{"operationId":"getV1VideosByVideo_id","tags":["Videos"],"summary":"Get a video","description":"Accepts either the `id` (UUID) or the `short_id`.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"The video.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"description":"A video, regardless of custody (platform or BYO engine).","type":"object","required":["id","short_id","title","slug","description","status","visibility","playback_security","delivery","source_type","duration_sec","width","height","size_original_bytes","size_processed_bytes","qualities","custody","engine","compute_engine","storage_profile","links","metadata","created_at","updated_at"],"properties":{"id":{"format":"uuid","type":"string"},"short_id":{"anyOf":[{"type":"null"},{"type":"string"}]},"title":{"type":"string"},"slug":{"type":"string"},"description":{"anyOf":[{"type":"null"},{"type":"string"}]},"status":{"anyOf":[{"const":"uploading","type":"string"},{"const":"queued","type":"string"},{"const":"processing","type":"string"},{"const":"partial","type":"string"},{"const":"ready","type":"string"},{"const":"error","type":"string"},{"const":"deleting","type":"string"}]},"visibility":{"anyOf":[{"const":"public","type":"string"},{"const":"private","type":"string"},{"const":"unlisted","type":"string"}]},"playback_security":{"anyOf":[{"const":"inherit","type":"string"},{"const":"open","type":"string"},{"const":"protected","type":"string"},{"const":"strict","type":"string"},{"const":"maximum","type":"string"}]},"delivery":{"description":"`hls` (default): XonaPlay renders adaptive HLS from the original. `original`: no transcoding at all — the untouched original is what you play and download. The original is always kept as uploaded in both cases.","anyOf":[{"const":"hls","type":"string"},{"const":"original","type":"string"}]},"source_type":{"anyOf":[{"const":"upload","type":"string"},{"const":"live","type":"string"},{"const":"url","type":"string"}]},"duration_sec":{"anyOf":[{"type":"null"},{"type":"number"}]},"width":{"anyOf":[{"type":"null"},{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]}]},"height":{"anyOf":[{"type":"null"},{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]}]},"size_original_bytes":{"anyOf":[{"type":"null"},{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]}]},"size_processed_bytes":{"anyOf":[{"type":"null"},{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]}]},"qualities":{"description":"Renditions available, e.g. [\"FHD\",\"HD\",\"SD\",\"LD\"].","type":"array","items":{"type":"string"}},"custody":{"anyOf":[{"const":"api","type":"string"},{"const":"engine","type":"string"}]},"engine":{"anyOf":[{"type":"null"},{"type":"object","required":["id","name","mode","status","base_url"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"mode":{"anyOf":[{"const":"managed","type":"string"},{"const":"byo","type":"string"}]},"status":{"anyOf":[{"const":"online","type":"string"},{"const":"offline","type":"string"},{"const":"maintenance","type":"string"}]},"base_url":{"type":"string"}}}]},"compute_engine":{"anyOf":[{"type":"null"},{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}}]},"storage_profile":{"anyOf":[{"type":"null"},{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}}]},"links":{"type":"object","required":["player","hls","poster"],"properties":{"player":{"format":"uri","type":"string"},"hls":{"format":"uri","type":"string"},"poster":{"anyOf":[{"type":"null"},{"format":"uri","type":"string"}]}}},"metadata":{"description":"Free-form (poster override, ffprobe, description, …).","type":"object","patternProperties":{"^(.*)$":{}}},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"404":{"description":"No video with that id or short_id (`NOT_FOUND`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"parameters":[{"schema":{"type":"string","minLength":1},"in":"path","name":"video_id","required":true}]},"patch":{"operationId":"patchV1VideosByVideo_id","tags":["Videos"],"summary":"Update a video","description":"Partial update. `playback_security` overrides the workspace default for this video only; it is rejected on BYO-engine videos (`NOT_SUPPORTED_FOR_BYO`) and `maximum` requires the staff opt-in for the workspace (`MAXIMUM_NOT_ALLOWED`).","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"The updated video.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"description":"A video, regardless of custody (platform or BYO engine).","type":"object","required":["id","short_id","title","slug","description","status","visibility","playback_security","delivery","source_type","duration_sec","width","height","size_original_bytes","size_processed_bytes","qualities","custody","engine","compute_engine","storage_profile","links","metadata","created_at","updated_at"],"properties":{"id":{"format":"uuid","type":"string"},"short_id":{"anyOf":[{"type":"null"},{"type":"string"}]},"title":{"type":"string"},"slug":{"type":"string"},"description":{"anyOf":[{"type":"null"},{"type":"string"}]},"status":{"anyOf":[{"const":"uploading","type":"string"},{"const":"queued","type":"string"},{"const":"processing","type":"string"},{"const":"partial","type":"string"},{"const":"ready","type":"string"},{"const":"error","type":"string"},{"const":"deleting","type":"string"}]},"visibility":{"anyOf":[{"const":"public","type":"string"},{"const":"private","type":"string"},{"const":"unlisted","type":"string"}]},"playback_security":{"anyOf":[{"const":"inherit","type":"string"},{"const":"open","type":"string"},{"const":"protected","type":"string"},{"const":"strict","type":"string"},{"const":"maximum","type":"string"}]},"delivery":{"description":"`hls` (default): XonaPlay renders adaptive HLS from the original. `original`: no transcoding at all — the untouched original is what you play and download. The original is always kept as uploaded in both cases.","anyOf":[{"const":"hls","type":"string"},{"const":"original","type":"string"}]},"source_type":{"anyOf":[{"const":"upload","type":"string"},{"const":"live","type":"string"},{"const":"url","type":"string"}]},"duration_sec":{"anyOf":[{"type":"null"},{"type":"number"}]},"width":{"anyOf":[{"type":"null"},{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]}]},"height":{"anyOf":[{"type":"null"},{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]}]},"size_original_bytes":{"anyOf":[{"type":"null"},{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]}]},"size_processed_bytes":{"anyOf":[{"type":"null"},{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]}]},"qualities":{"description":"Renditions available, e.g. [\"FHD\",\"HD\",\"SD\",\"LD\"].","type":"array","items":{"type":"string"}},"custody":{"anyOf":[{"const":"api","type":"string"},{"const":"engine","type":"string"}]},"engine":{"anyOf":[{"type":"null"},{"type":"object","required":["id","name","mode","status","base_url"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"mode":{"anyOf":[{"const":"managed","type":"string"},{"const":"byo","type":"string"}]},"status":{"anyOf":[{"const":"online","type":"string"},{"const":"offline","type":"string"},{"const":"maintenance","type":"string"}]},"base_url":{"type":"string"}}}]},"compute_engine":{"anyOf":[{"type":"null"},{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}}]},"storage_profile":{"anyOf":[{"type":"null"},{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}}]},"links":{"type":"object","required":["player","hls","poster"],"properties":{"player":{"format":"uri","type":"string"},"hls":{"format":"uri","type":"string"},"poster":{"anyOf":[{"type":"null"},{"format":"uri","type":"string"}]}}},"metadata":{"description":"Free-form (poster override, ffprobe, description, …).","type":"object","patternProperties":{"^(.*)$":{}}},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"404":{"description":"No video with that id or short_id (`NOT_FOUND`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"422":{"description":"Validation failed, `playback_security=maximum` without the workspace opt-in (`MAXIMUM_NOT_ALLOWED`), or an override on a BYO video (`NOT_SUPPORTED_FOR_BYO`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"minLength":1,"type":"string"},"slug":{"minLength":1,"type":"string"},"visibility":{"anyOf":[{"const":"public","type":"string"},{"const":"private","type":"string"},{"const":"unlisted","type":"string"}]},"playback_security":{"anyOf":[{"const":"inherit","type":"string"},{"const":"open","type":"string"},{"const":"protected","type":"string"},{"const":"strict","type":"string"},{"const":"maximum","type":"string"}]},"delivery":{"const":"hls","type":"string"},"metadata":{"type":"object","patternProperties":{"^(.*)$":{}}}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"title":{"minLength":1,"type":"string"},"slug":{"minLength":1,"type":"string"},"visibility":{"anyOf":[{"const":"public","type":"string"},{"const":"private","type":"string"},{"const":"unlisted","type":"string"}]},"playback_security":{"anyOf":[{"const":"inherit","type":"string"},{"const":"open","type":"string"},{"const":"protected","type":"string"},{"const":"strict","type":"string"},{"const":"maximum","type":"string"}]},"delivery":{"const":"hls","type":"string"},"metadata":{"type":"object","patternProperties":{"^(.*)$":{}}}}}},"text/plain":{"schema":{"type":"object","properties":{"title":{"minLength":1,"type":"string"},"slug":{"minLength":1,"type":"string"},"visibility":{"anyOf":[{"const":"public","type":"string"},{"const":"private","type":"string"},{"const":"unlisted","type":"string"}]},"playback_security":{"anyOf":[{"const":"inherit","type":"string"},{"const":"open","type":"string"},{"const":"protected","type":"string"},{"const":"strict","type":"string"},{"const":"maximum","type":"string"}]},"delivery":{"const":"hls","type":"string"},"metadata":{"type":"object","patternProperties":{"^(.*)$":{}}}}}}}},"parameters":[{"schema":{"type":"string","minLength":1},"in":"path","name":"video_id","required":true}]},"delete":{"operationId":"deleteV1VideosByVideo_id","tags":["Videos"],"summary":"Delete a video","description":"`only_original=true` keeps the processed renditions and deletes only the source file.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"type":"object","required":["deleted","only_original"],"properties":{"deleted":{"type":"boolean"},"only_original":{"type":"boolean"}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"404":{"description":"No video with that id or short_id (`NOT_FOUND`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"parameters":[{"schema":{"type":"string","minLength":1},"in":"path","name":"video_id","required":true},{"schema":{"type":"string"},"in":"query","name":"only_original","required":false}]}},"/v1/videos/{video_id}/download":{"get":{"operationId":"getV1VideosByVideo_idDownload","tags":["Videos"],"summary":"Download the original file","description":"Short-lived signed link (1 hour) to the original exactly as it was uploaded or imported — never transcoded. Requires a secret key or a session.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"Download link.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"description":"Download link for the original file.","type":"object","required":["url","expires_at","file_name","size_bytes"],"properties":{"url":{"format":"uri","description":"Short-lived signed link to the untouched original, served as an attachment with its file name.","type":"string"},"expires_at":{"format":"date-time","type":"string"},"file_name":{"type":"string"},"size_bytes":{"anyOf":[{"type":"null"},{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]}]}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"404":{"description":"No video with that id or short_id (`NOT_FOUND`), or its original was deleted (`ORIGINAL_NOT_AVAILABLE`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"409":{"description":"The original is still uploading (`VIDEO_NOT_READY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"422":{"description":"The video lives on your own server (`NOT_SUPPORTED_FOR_BYO`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"parameters":[{"schema":{"type":"string","minLength":1},"in":"path","name":"video_id","required":true}]}},"/v1/videos/{video_id}/playback":{"get":{"operationId":"getV1VideosByVideo_idPlayback","tags":["Playback"],"summary":"Get signed playback links for a video","description":"The ONLY way to play a video: returns a signed `hls_url`/`embed_url` pair whose shape depends on the workspace/video playback security level (`open`/`protected`/`strict`/`maximum`). No credential required for public `open`/`protected` content; otherwise a secret key or session is required. On a fatal player error, call this again (see the \"Reload\" rule in the guide) instead of reusing the old URL.","security":[{},{"bearerAuth":[]}],"responses":{"200":{"description":"Signed playback links.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"description":"Signed playback links for a video. Never build an HLS/embed URL by hand — always call this endpoint.","type":"object","required":["video_id","short_id","hls_url","original_url","poster_url","thumbnails_url","embed_url","expires_at","security","delivery","duration_sec"],"properties":{"video_id":{"format":"uuid","type":"string"},"short_id":{"anyOf":[{"type":"null"},{"type":"string"}]},"hls_url":{"description":"Adaptive HLS master playlist. `null` while it is still rendering, or when `delivery` is `original`.","anyOf":[{"type":"null"},{"format":"uri","type":"string"}]},"original_url":{"description":"The untouched original file (mp4, mkv, mov…), byte-range friendly, signed with the same rules as `hls_url`. Available as soon as the upload/import finishes. Which players can play it depends on its format — `hls_url` is the guaranteed one.","anyOf":[{"type":"null"},{"format":"uri","type":"string"}]},"poster_url":{"anyOf":[{"type":"null"},{"format":"uri","type":"string"}]},"thumbnails_url":{"anyOf":[{"type":"null"},{"format":"uri","type":"string"}]},"embed_url":{"format":"uri","type":"string"},"expires_at":{"anyOf":[{"type":"null"},{"format":"date-time","type":"string"}]},"security":{"anyOf":[{"const":"inherit","type":"string"},{"const":"open","type":"string"},{"const":"protected","type":"string"},{"const":"strict","type":"string"},{"const":"maximum","type":"string"}]},"delivery":{"description":"`hls` (default): XonaPlay renders adaptive HLS from the original. `original`: no transcoding at all — the untouched original is what you play and download. The original is always kept as uploaded in both cases.","anyOf":[{"const":"hls","type":"string"},{"const":"original","type":"string"}]},"duration_sec":{"anyOf":[{"type":"null"},{"type":"number"}]}}}}}}}},"401":{"description":"A secret key or session is required for this content (`KEY_REQUIRED`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"403":{"description":"Domain not allowed (`DOMAIN_NOT_ALLOWED`), workspace unavailable (`WORKSPACE_UNAVAILABLE`), or viewer banned (`ACCESS_DENIED`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"404":{"description":"No video with that id or short_id (`NOT_FOUND`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"409":{"description":"The video is still processing (`VIDEO_NOT_READY`); retry later.","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"429":{"description":"Too many requests; retry after `Retry-After` (`RATE_LIMITED`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"parameters":[{"schema":{"type":"string","minLength":1},"in":"path","name":"video_id","required":true},{"schema":{"type":"string"},"in":"query","name":"viewer_id","required":false}]}},"/v1/videos/{video_id}/tracks":{"get":{"operationId":"getV1VideosByVideo_idTracks","tags":["Videos"],"summary":"List audio and subtitle tracks","description":"Tracks that came with the original file (`origin: source`) plus the ones added through the API (`origin: manual`). `supported` is false when tracks cannot be added to this video, with the reason in `unsupported_reason`.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"Tracks.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"description":"Tracks of a video.","type":"object","required":["supported","unsupported_reason","tracks"],"properties":{"supported":{"type":"boolean"},"unsupported_reason":{"description":"Why tracks cannot be added: the video is not delivered as HLS, is still processing, or lives on your own server.","anyOf":[{"type":"null"},{"const":"not_hls","type":"string"},{"const":"not_ready","type":"string"},{"const":"byo_custody","type":"string"}]},"tracks":{"type":"array","items":{"description":"An audio or subtitle track of a video.","type":"object","required":["id","kind","origin","lang","label","status","error","created_at"],"properties":{"id":{"description":"Null for tracks that came with the original file.","anyOf":[{"type":"null"},{"format":"uuid","type":"string"}]},"kind":{"anyOf":[{"const":"audio","type":"string"},{"const":"subtitle","type":"string"}]},"origin":{"description":"`source` = extracted from the uploaded file; `manual` = added through the API (the only ones you can delete).","anyOf":[{"const":"source","type":"string"},{"const":"manual","type":"string"}]},"lang":{"description":"Lowercase language code, e.g. `es`, `pt-br`.","type":"string"},"label":{"type":"string"},"status":{"anyOf":[{"const":"uploading","type":"string"},{"const":"processing","type":"string"},{"const":"ready","type":"string"},{"const":"failed","type":"string"}]},"error":{"anyOf":[{"type":"null"},{"type":"string"}]},"created_at":{"anyOf":[{"type":"null"},{"format":"date-time","type":"string"}]}}}}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"404":{"description":"No video with that id or short_id (`NOT_FOUND`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"parameters":[{"schema":{"type":"string","minLength":1},"in":"path","name":"video_id","required":true}]}},"/v1/videos/{video_id}/tracks/audio":{"post":{"operationId":"postV1VideosByVideo_idTracksAudio","tags":["Videos"],"summary":"Add an audio track","description":"Step 1 of 2. Creates the track (`uploading`) and returns a pre-signed `PUT` for the audio file (mp3, m4a, aac, wav, flac, ogg or opus; up to 1 GiB). Upload the file, then call `POST /videos/{video_id}/tracks/{track_id}/complete`.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"Track and upload URL.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"description":"The track (status `uploading`) and the pre-signed PUT for the audio file.","type":"object","required":["track","upload"],"properties":{"track":{"description":"An audio or subtitle track of a video.","type":"object","required":["id","kind","origin","lang","label","status","error","created_at"],"properties":{"id":{"description":"Null for tracks that came with the original file.","anyOf":[{"type":"null"},{"format":"uuid","type":"string"}]},"kind":{"anyOf":[{"const":"audio","type":"string"},{"const":"subtitle","type":"string"}]},"origin":{"description":"`source` = extracted from the uploaded file; `manual` = added through the API (the only ones you can delete).","anyOf":[{"const":"source","type":"string"},{"const":"manual","type":"string"}]},"lang":{"description":"Lowercase language code, e.g. `es`, `pt-br`.","type":"string"},"label":{"type":"string"},"status":{"anyOf":[{"const":"uploading","type":"string"},{"const":"processing","type":"string"},{"const":"ready","type":"string"},{"const":"failed","type":"string"}]},"error":{"anyOf":[{"type":"null"},{"type":"string"}]},"created_at":{"anyOf":[{"type":"null"},{"format":"date-time","type":"string"}]}}},"upload":{"type":"object","required":["url","method","headers","expires_at"],"properties":{"url":{"format":"uri","type":"string"},"method":{"const":"PUT","type":"string"},"headers":{"description":"Send these headers with the PUT.","type":"object","patternProperties":{"^(.*)$":{"type":"string"}}},"expires_at":{"format":"date-time","type":"string"}}}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"404":{"description":"No video with that id or short_id (`NOT_FOUND`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"409":{"description":"The video does not accept tracks yet (`TRACKS_NOT_SUPPORTED`: not HLS, still processing, or on your own server), or the per-video limit was reached (`TRACK_LIMIT_REACHED`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"422":{"description":"Invalid `lang`/`label`, unsupported file type or size (`UNSUPPORTED_AUDIO_FORMAT`, `AUDIO_TOO_LARGE`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["lang","label","file_name","size_bytes","content_type"],"properties":{"lang":{"minLength":2,"maxLength":16,"type":"string"},"label":{"minLength":1,"maxLength":128,"type":"string"},"file_name":{"minLength":1,"maxLength":512,"type":"string"},"size_bytes":{"minimum":1,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"type":"integer"}]},"content_type":{"minLength":1,"maxLength":128,"type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","required":["lang","label","file_name","size_bytes","content_type"],"properties":{"lang":{"minLength":2,"maxLength":16,"type":"string"},"label":{"minLength":1,"maxLength":128,"type":"string"},"file_name":{"minLength":1,"maxLength":512,"type":"string"},"size_bytes":{"minimum":1,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"type":"integer"}]},"content_type":{"minLength":1,"maxLength":128,"type":"string"}}}},"text/plain":{"schema":{"type":"object","required":["lang","label","file_name","size_bytes","content_type"],"properties":{"lang":{"minLength":2,"maxLength":16,"type":"string"},"label":{"minLength":1,"maxLength":128,"type":"string"},"file_name":{"minLength":1,"maxLength":512,"type":"string"},"size_bytes":{"minimum":1,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"type":"integer"}]},"content_type":{"minLength":1,"maxLength":128,"type":"string"}}}}}},"parameters":[{"schema":{"type":"string","minLength":1},"in":"path","name":"video_id","required":true}]}},"/v1/videos/{video_id}/tracks/subtitles":{"post":{"operationId":"postV1VideosByVideo_idTracksSubtitles","tags":["Videos"],"summary":"Add a subtitle track","description":"Send the text of an `.srt` or `.vtt` file (max 2 MB) in `content`. SRT is converted to WebVTT. The track is ready immediately.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"The new track.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"description":"The track.","type":"object","required":["track"],"properties":{"track":{"description":"An audio or subtitle track of a video.","type":"object","required":["id","kind","origin","lang","label","status","error","created_at"],"properties":{"id":{"description":"Null for tracks that came with the original file.","anyOf":[{"type":"null"},{"format":"uuid","type":"string"}]},"kind":{"anyOf":[{"const":"audio","type":"string"},{"const":"subtitle","type":"string"}]},"origin":{"description":"`source` = extracted from the uploaded file; `manual` = added through the API (the only ones you can delete).","anyOf":[{"const":"source","type":"string"},{"const":"manual","type":"string"}]},"lang":{"description":"Lowercase language code, e.g. `es`, `pt-br`.","type":"string"},"label":{"type":"string"},"status":{"anyOf":[{"const":"uploading","type":"string"},{"const":"processing","type":"string"},{"const":"ready","type":"string"},{"const":"failed","type":"string"}]},"error":{"anyOf":[{"type":"null"},{"type":"string"}]},"created_at":{"anyOf":[{"type":"null"},{"format":"date-time","type":"string"}]}}}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"404":{"description":"No video with that id or short_id (`NOT_FOUND`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"409":{"description":"The video does not accept tracks yet (`TRACKS_NOT_SUPPORTED`: not HLS, still processing, or on your own server), or the per-video limit was reached (`TRACK_LIMIT_REACHED`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"413":{"description":"The subtitle file is larger than 2 MB (`SUBTITLE_TOO_LARGE`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"422":{"description":"Invalid `lang`, `label` or subtitle content (`INVALID_LANG`, `INVALID_SUBTITLE`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["lang","label","content"],"properties":{"lang":{"minLength":2,"maxLength":16,"type":"string"},"label":{"minLength":1,"maxLength":128,"type":"string"},"content":{"minLength":1,"maxLength":2200000,"type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","required":["lang","label","content"],"properties":{"lang":{"minLength":2,"maxLength":16,"type":"string"},"label":{"minLength":1,"maxLength":128,"type":"string"},"content":{"minLength":1,"maxLength":2200000,"type":"string"}}}},"text/plain":{"schema":{"type":"object","required":["lang","label","content"],"properties":{"lang":{"minLength":2,"maxLength":16,"type":"string"},"label":{"minLength":1,"maxLength":128,"type":"string"},"content":{"minLength":1,"maxLength":2200000,"type":"string"}}}}}},"parameters":[{"schema":{"type":"string","minLength":1},"in":"path","name":"video_id","required":true}]}},"/v1/videos/{video_id}/tracks/{track_id}":{"delete":{"operationId":"deleteV1VideosByVideo_idTracksByTrack_id","tags":["Videos"],"summary":"Delete a track you added","description":"Only `origin: manual` tracks can be deleted.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"type":"object","required":["deleted"],"properties":{"deleted":{"type":"boolean"}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"404":{"description":"No video or track with that id (`NOT_FOUND`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"409":{"description":"The video does not accept tracks yet (`TRACKS_NOT_SUPPORTED`: not HLS, still processing, or on your own server), or the per-video limit was reached (`TRACK_LIMIT_REACHED`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"parameters":[{"schema":{"type":"string","minLength":1},"in":"path","name":"video_id","required":true},{"schema":{"type":"string","minLength":1},"in":"path","name":"track_id","required":true}]}},"/v1/videos/{video_id}/tracks/{track_id}/complete":{"post":{"operationId":"postV1VideosByVideo_idTracksByTrack_idComplete","tags":["Videos"],"summary":"Complete an audio track upload","description":"Step 2 of 2. Verifies the uploaded file and starts processing (`processing` → `ready` or `failed`). Safe to call twice.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"The track.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"description":"The track.","type":"object","required":["track"],"properties":{"track":{"description":"An audio or subtitle track of a video.","type":"object","required":["id","kind","origin","lang","label","status","error","created_at"],"properties":{"id":{"description":"Null for tracks that came with the original file.","anyOf":[{"type":"null"},{"format":"uuid","type":"string"}]},"kind":{"anyOf":[{"const":"audio","type":"string"},{"const":"subtitle","type":"string"}]},"origin":{"description":"`source` = extracted from the uploaded file; `manual` = added through the API (the only ones you can delete).","anyOf":[{"const":"source","type":"string"},{"const":"manual","type":"string"}]},"lang":{"description":"Lowercase language code, e.g. `es`, `pt-br`.","type":"string"},"label":{"type":"string"},"status":{"anyOf":[{"const":"uploading","type":"string"},{"const":"processing","type":"string"},{"const":"ready","type":"string"},{"const":"failed","type":"string"}]},"error":{"anyOf":[{"type":"null"},{"type":"string"}]},"created_at":{"anyOf":[{"type":"null"},{"format":"date-time","type":"string"}]}}}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"404":{"description":"No video or track with that id (`NOT_FOUND`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"409":{"description":"The file is missing or its size does not match (`UPLOAD_MISSING`, `UPLOAD_SIZE_MISMATCH`), or the video does not accept tracks.","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"503":{"description":"No processing server is available right now (`NO_ENGINE_AVAILABLE`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"parameters":[{"schema":{"type":"string","minLength":1},"in":"path","name":"video_id","required":true},{"schema":{"type":"string","minLength":1},"in":"path","name":"track_id","required":true}]}},"/v1/webhooks":{"get":{"operationId":"getV1Webhooks","tags":["Webhooks"],"summary":"List webhook endpoints","description":"Webhook endpoints registered for the workspace (secrets never come back in full).","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"Webhook endpoints.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"type":"array","items":{"description":"A webhook endpoint registered for this workspace.","type":"object","required":["id","url","description","secret_last4","events","enabled","disabled_by_staff","last_success_at","last_failure_at","created_at","updated_at"],"properties":{"id":{"format":"uuid","type":"string"},"url":{"format":"uri","type":"string"},"description":{"anyOf":[{"type":"null"},{"type":"string"}]},"secret_last4":{"description":"Last 4 chars of the signing secret (whsec_…), shown once in full on create.","type":"string"},"events":{"type":"array","items":{"anyOf":[{"const":"video.ready","type":"string"},{"const":"video.failed","type":"string"},{"const":"live.started","type":"string"},{"const":"live.ended","type":"string"}]}},"enabled":{"type":"boolean"},"disabled_by_staff":{"type":"boolean"},"last_success_at":{"anyOf":[{"type":"null"},{"format":"date-time","type":"string"}]},"last_failure_at":{"anyOf":[{"type":"null"},{"format":"date-time","type":"string"}]},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"}}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}}},"post":{"operationId":"postV1Webhooks","tags":["Webhooks"],"summary":"Create a webhook endpoint","description":"Registers a new endpoint. The signing secret (`whsec_…`) is returned ONCE, in this response — store it, it cannot be retrieved again.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"Endpoint created, with its signing secret.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"description":"A freshly created endpoint, with its signing secret.","type":"object","required":["endpoint","secret"],"properties":{"endpoint":{"description":"A webhook endpoint registered for this workspace.","type":"object","required":["id","url","description","secret_last4","events","enabled","disabled_by_staff","last_success_at","last_failure_at","created_at","updated_at"],"properties":{"id":{"format":"uuid","type":"string"},"url":{"format":"uri","type":"string"},"description":{"anyOf":[{"type":"null"},{"type":"string"}]},"secret_last4":{"description":"Last 4 chars of the signing secret (whsec_…), shown once in full on create.","type":"string"},"events":{"type":"array","items":{"anyOf":[{"const":"video.ready","type":"string"},{"const":"video.failed","type":"string"},{"const":"live.started","type":"string"},{"const":"live.ended","type":"string"}]}},"enabled":{"type":"boolean"},"disabled_by_staff":{"type":"boolean"},"last_success_at":{"anyOf":[{"type":"null"},{"format":"date-time","type":"string"}]},"last_failure_at":{"anyOf":[{"type":"null"},{"format":"date-time","type":"string"}]},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"}}},"secret":{"description":"Signing secret (whsec_…) — shown only once, on creation.","type":"string"}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"409":{"description":"Workspace already has the maximum number of endpoints (`ENDPOINT_LIMIT_REACHED`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"422":{"description":"Validation failed (bad `url` or `events`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url","events"],"properties":{"url":{"minLength":1,"maxLength":1024,"type":"string"},"description":{"maxLength":255,"type":"string"},"events":{"minItems":1,"type":"array","items":{"anyOf":[{"const":"video.ready","type":"string"},{"const":"video.failed","type":"string"},{"const":"live.started","type":"string"},{"const":"live.ended","type":"string"}]}}}}},"multipart/form-data":{"schema":{"type":"object","required":["url","events"],"properties":{"url":{"minLength":1,"maxLength":1024,"type":"string"},"description":{"maxLength":255,"type":"string"},"events":{"minItems":1,"type":"array","items":{"anyOf":[{"const":"video.ready","type":"string"},{"const":"video.failed","type":"string"},{"const":"live.started","type":"string"},{"const":"live.ended","type":"string"}]}}}}},"text/plain":{"schema":{"type":"object","required":["url","events"],"properties":{"url":{"minLength":1,"maxLength":1024,"type":"string"},"description":{"maxLength":255,"type":"string"},"events":{"minItems":1,"type":"array","items":{"anyOf":[{"const":"video.ready","type":"string"},{"const":"video.failed","type":"string"},{"const":"live.started","type":"string"},{"const":"live.ended","type":"string"}]}}}}}}}}},"/v1/webhooks/{id}":{"patch":{"operationId":"patchV1WebhooksById","tags":["Webhooks"],"summary":"Update a webhook endpoint","description":"Partial update. An endpoint disabled by staff cannot be re-enabled by the workspace.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"The updated endpoint.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"description":"A webhook endpoint registered for this workspace.","type":"object","required":["id","url","description","secret_last4","events","enabled","disabled_by_staff","last_success_at","last_failure_at","created_at","updated_at"],"properties":{"id":{"format":"uuid","type":"string"},"url":{"format":"uri","type":"string"},"description":{"anyOf":[{"type":"null"},{"type":"string"}]},"secret_last4":{"description":"Last 4 chars of the signing secret (whsec_…), shown once in full on create.","type":"string"},"events":{"type":"array","items":{"anyOf":[{"const":"video.ready","type":"string"},{"const":"video.failed","type":"string"},{"const":"live.started","type":"string"},{"const":"live.ended","type":"string"}]}},"enabled":{"type":"boolean"},"disabled_by_staff":{"type":"boolean"},"last_success_at":{"anyOf":[{"type":"null"},{"format":"date-time","type":"string"}]},"last_failure_at":{"anyOf":[{"type":"null"},{"format":"date-time","type":"string"}]},"created_at":{"format":"date-time","type":"string"},"updated_at":{"format":"date-time","type":"string"}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"403":{"description":"This endpoint was disabled by staff and cannot be re-enabled (`DISABLED_BY_STAFF`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"404":{"description":"No webhook endpoint with that id (`NOT_FOUND`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"422":{"description":"Validation failed (bad `url` or `events`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"minLength":1,"maxLength":1024,"type":"string"},"description":{"maxLength":255,"type":"string"},"events":{"minItems":1,"type":"array","items":{"anyOf":[{"const":"video.ready","type":"string"},{"const":"video.failed","type":"string"},{"const":"live.started","type":"string"},{"const":"live.ended","type":"string"}]}},"enabled":{"type":"boolean"}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"url":{"minLength":1,"maxLength":1024,"type":"string"},"description":{"maxLength":255,"type":"string"},"events":{"minItems":1,"type":"array","items":{"anyOf":[{"const":"video.ready","type":"string"},{"const":"video.failed","type":"string"},{"const":"live.started","type":"string"},{"const":"live.ended","type":"string"}]}},"enabled":{"type":"boolean"}}}},"text/plain":{"schema":{"type":"object","properties":{"url":{"minLength":1,"maxLength":1024,"type":"string"},"description":{"maxLength":255,"type":"string"},"events":{"minItems":1,"type":"array","items":{"anyOf":[{"const":"video.ready","type":"string"},{"const":"video.failed","type":"string"},{"const":"live.started","type":"string"},{"const":"live.ended","type":"string"}]}},"enabled":{"type":"boolean"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}]},"delete":{"operationId":"deleteV1WebhooksById","tags":["Webhooks"],"summary":"Delete a webhook endpoint","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"type":"object","required":["deleted"],"properties":{"deleted":{"type":"boolean"}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"404":{"description":"No webhook endpoint with that id (`NOT_FOUND`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}]}},"/v1/webhooks/{id}/deliveries":{"get":{"operationId":"getV1WebhooksByIdDeliveries","tags":["Webhooks"],"summary":"List delivery attempts","description":"Delivery history for one endpoint, newest first. Paginated.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"Paginated deliveries.","content":{"application/json":{"schema":{"type":"object","required":["status","data","meta"],"properties":{"status":{"const":"ok","type":"string"},"data":{"type":"array","items":{"description":"One delivery attempt chain for a webhook event.","type":"object","required":["id","event","status","attempts","last_status_code","last_error","created_at","delivered_at"],"properties":{"id":{"format":"uuid","type":"string"},"event":{"type":"string"},"status":{"anyOf":[{"const":"pending","type":"string"},{"const":"delivered","type":"string"},{"const":"failed","type":"string"}]},"attempts":{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]},"last_status_code":{"anyOf":[{"type":"null"},{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]}]},"last_error":{"anyOf":[{"type":"null"},{"type":"string"}]},"created_at":{"format":"date-time","type":"string"},"delivered_at":{"anyOf":[{"type":"null"},{"format":"date-time","type":"string"}]}}}},"meta":{"type":"object","required":["total","page","per_page","last_page"],"properties":{"total":{"description":"Total items after filtering.","anyOf":[{"format":"integer","default":0,"type":"string"},{"description":"Total items after filtering.","type":"integer"}]},"page":{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]},"per_page":{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]},"last_page":{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"404":{"description":"No webhook endpoint with that id (`NOT_FOUND`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true},{"schema":{"type":"string"},"in":"query","name":"page","required":false},{"schema":{"type":"string"},"in":"query","name":"per_page","required":false}]}},"/v1/webhooks/{id}/test":{"post":{"operationId":"postV1WebhooksByIdTest","tags":["Webhooks"],"summary":"Send a test event","description":"Delivers a `webhook.test` event to the endpoint right away, so you can check your receiver.","security":[{"bearerAuth":[]},{}],"responses":{"200":{"description":"The test delivery.","content":{"application/json":{"schema":{"type":"object","required":["status","data"],"properties":{"status":{"const":"ok","type":"string"},"data":{"description":"One delivery attempt chain for a webhook event.","type":"object","required":["id","event","status","attempts","last_status_code","last_error","created_at","delivered_at"],"properties":{"id":{"format":"uuid","type":"string"},"event":{"type":"string"},"status":{"anyOf":[{"const":"pending","type":"string"},{"const":"delivered","type":"string"},{"const":"failed","type":"string"}]},"attempts":{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]},"last_status_code":{"anyOf":[{"type":"null"},{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]}]},"last_error":{"anyOf":[{"type":"null"},{"type":"string"}]},"created_at":{"format":"date-time","type":"string"},"delivered_at":{"anyOf":[{"type":"null"},{"format":"date-time","type":"string"}]}}}}}}}},"401":{"description":"Missing or invalid credential (`KEY_REQUIRED`, `INVALID_KEY`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}},"404":{"description":"No webhook endpoint with that id (`NOT_FOUND`).","content":{"application/json":{"schema":{"description":"Error envelope. Every error response has this shape.","type":"object","required":["status","code","message"],"properties":{"status":{"const":"error","type":"string"},"code":{"description":"Stable, UPPERCASE machine-readable error code (see the error table in the guide).","examples":["NOT_FOUND"],"type":"string"},"message":{"description":"Human-readable, safe to display.","type":"string"}}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true}]}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Secret key xp_sk_… (Settings → API keys). A workspace session cookie also works on the public routes."}}}}