{"info":{"contact":{"email":"support@jellypod.ai","name":"Jellypod Support","url":"https://www.jellypod.com/docs/api"},"description":"Programmatic access to Jellypod podcasts, episodes, hosts, sources, and voices.","license":{"name":"Proprietary"},"title":"Jellypod API","version":"1.0.0"},"openapi":"3.1.0","servers":[{"description":"Production","url":"https://api.jellypod.com"},{"description":"Local development","url":"http://localhost:3003"}],"tags":[{"description":"Service liveness checks.","name":"Health"},{"description":"Authenticated organization details.","name":"Account"},{"description":"Podcast resources.","name":"Podcasts"},{"description":"Episode resources.","name":"Episodes"},{"description":"Streaming and playback metrics for podcasts and episodes.","name":"Analytics"},{"description":"Host (speaker) resources.","name":"Hosts"},{"description":"Source documents fed to generation.","name":"Sources"},{"description":"Video generation resources.","name":"Videos"},{"description":"Short generation resources.","name":"Shorts"},{"description":"Voiceover generation resources.","name":"Voiceovers"},{"description":"TTS voices.","name":"Voices"}],"components":{"securitySchemes":{"bearerAuth":{"description":"API key issued from /developers/api-keys in the Jellypod studio. Send as `Authorization: Bearer <key>`.","scheme":"bearer","type":"http"}},"schemas":{"ApiIndex":{"type":"object","properties":{"authentication":{"type":"object","properties":{"documentation_url":{"type":"string","format":"uri"},"header":{"type":"string"},"keys_url":{"type":"string","format":"uri"},"type":{"type":"string","enum":["bearer"]}},"required":["documentation_url","header","keys_url","type"]},"description":{"type":"string"},"developers_url":{"type":"string","format":"uri"},"documentation_url":{"type":"string","format":"uri"},"errors":{"type":"object","properties":{"format":{"type":"string","enum":["application/problem+json"]},"specification":{"type":"string","format":"uri"}},"required":["format","specification"]},"llms_txt_url":{"type":"string","format":"uri"},"mcp":{"type":"object","properties":{"documentation_url":{"type":"string","format":"uri"},"server_card_url":{"type":"string","format":"uri"},"transport":{"type":"string","enum":["streamable-http"]},"url":{"type":"string","format":"uri"}},"required":["documentation_url","server_card_url","transport","url"]},"name":{"type":"string"},"openapi_url":{"type":"string","format":"uri"},"version":{"type":"string"}},"required":["authentication","description","developers_url","documentation_url","errors","llms_txt_url","mcp","name","openapi_url","version"],"description":"Discovery document linking the OpenAPI spec, docs, authentication, and MCP server."},"Account":{"type":"object","properties":{"data":{"type":"object","properties":{"organization_id":{"type":"string","readOnly":true},"plan":{"type":"string","readOnly":true},"credits":{"type":"object","properties":{"balance":{"type":"number","readOnly":true}},"required":["balance"]}},"required":["organization_id","plan","credits"]}},"required":["data"],"description":"Caller organization, current plan, and credit balance."},"ApiError":{"type":"object","properties":{"detail":{"type":"string","description":"Longer human-readable explanation when available."},"errors":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}},"required":["field","message"]},"description":"Per-field validation failures. Present when `type` is `validation_error`."},"request_id":{"type":"string","description":"Correlation id, also returned in the `X-Request-Id` response header. Include in support requests."},"status":{"type":"integer","description":"HTTP status code mirrored from the response."},"title":{"type":"string","description":"Short human-readable summary."},"type":{"type":"string","enum":["bad_request","validation_error","unauthorized","forbidden","not_found","conflict","method_not_allowed","unsupported_media_type","unprocessable_entity","rate_limited","bad_gateway","internal_error"],"description":"Machine-readable error class. Suitable for switch/match in client code."}},"required":["status","title","type"],"description":"RFC 9457 error envelope returned for all non-2xx responses from the Jellypod API."},"EpisodeAnalytics":{"type":"object","properties":{"downloads":{"$ref":"#/components/schemas/EpisodeDownloads"},"video_views":{"$ref":"#/components/schemas/EpisodeVideoViews"},"as_of":{"type":"string","description":"ISO-8601 time these metrics were computed.","readOnly":true},"complete":{"type":"boolean","description":"Whether every analytics source answered in full. When false an upstream (OP3 or Mux) was degraded, so the numbers are a floor rather than a total; retry later for a complete read.","readOnly":true},"episode_id":{"type":"string","format":"uuid","readOnly":true}},"required":["downloads","video_views","as_of","complete","episode_id"],"description":"Streaming metrics for a single episode. Audio download windows are measured since publish; video view windows are rolling."},"EpisodeDownloads":{"type":"object","properties":{"first_7_days":{"type":"number","minimum":0,"description":"Audio downloads in the first 7 days after publish."},"first_30_days":{"type":"number","minimum":0,"description":"Audio downloads in the first 30 days after publish."},"total":{"type":"number","minimum":0,"description":"All-time audio downloads (OP3)."}},"required":["first_7_days","first_30_days","total"]},"EpisodeVideoViews":{"type":"object","properties":{"last_7_days":{"type":"number","minimum":0,"description":"Web video views in the last 7 days."},"last_30_days":{"type":"number","minimum":0,"description":"Web video views in the last 30 days."},"total":{"type":"number","minimum":0,"description":"Web video views over the last 90 days (Mux retention window)."}},"required":["last_7_days","last_30_days","total"]},"PodcastAnalytics":{"type":"object","properties":{"analytics_enabled":{"type":"boolean","description":"Whether download tracking is enabled. When false, audio metrics are 0."},"as_of":{"type":"string","description":"ISO-8601 time these metrics were computed.","readOnly":true},"complete":{"type":"boolean","description":"Whether every analytics source answered in full. When false an upstream (OP3 or Mux) was degraded, so the numbers are a floor rather than a total; retry later for a complete read.","readOnly":true},"episodes":{"type":"array","items":{"type":"object","properties":{"downloads":{"type":"object","properties":{"first_7_days":{"type":"number","minimum":0,"description":"Audio downloads in the first 7 days after publish."},"first_30_days":{"type":"number","minimum":0,"description":"Audio downloads in the first 30 days after publish."},"total":{"type":"number","minimum":0,"description":"All-time audio downloads (OP3)."}},"required":["first_7_days","first_30_days","total"]},"video_views":{"type":"object","properties":{"last_7_days":{"type":"number","minimum":0,"description":"Web video views in the last 7 days."},"last_30_days":{"type":"number","minimum":0,"description":"Web video views in the last 30 days."},"total":{"type":"number","minimum":0,"description":"Web video views over the last 90 days (Mux retention window)."}},"required":["last_7_days","last_30_days","total"]},"episode_id":{"type":"string","format":"uuid","readOnly":true}},"required":["downloads","video_views","episode_id"]}},"plays_by_app":{"type":"object","additionalProperties":{"type":"number","minimum":0},"description":"Audio downloads grouped by client app (Spotify, Apple Podcasts, Overcast, ...). Show-level."},"podcast_id":{"type":"string","format":"uuid","readOnly":true},"totals":{"type":"object","properties":{"downloads":{"type":"number","minimum":0,"description":"All-time audio downloads (OP3)."},"last_7_days":{"type":"number","minimum":0,"description":"Combined plays in the last 7 days."},"last_30_days":{"type":"number","minimum":0,"description":"Combined plays in the last 30 days."},"plays":{"type":"number","minimum":0,"description":"All-time audio downloads + web video views."},"video_views":{"type":"number","minimum":0,"description":"Web video views (Mux, last 90 days)."}},"required":["downloads","last_7_days","last_30_days","plays","video_views"]}},"required":["analytics_enabled","as_of","complete","episodes","plays_by_app","podcast_id","totals"],"description":"Streaming metrics for a podcast: combined totals, per-app download breakdown, and per-episode metrics."},"ListEpisodesResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Episode"}}},"required":["data"],"description":"Page of episodes. Use the `Link` response header (`rel=\"next\"`) to paginate."},"Episode":{"type":"object","properties":{"audio_url":{"type":["string","null"],"readOnly":true},"created_at":{"type":"string","readOnly":true},"description":{"type":["string","null"]},"generation":{"type":["object","null"],"properties":{"completed_at":{"type":["string","null"]},"error_message":{"type":"string"},"started_at":{"type":"string"},"state":{"type":"string","enum":["generating","completed","failed"]}},"required":["completed_at","started_at","state"],"readOnly":true},"host_ids":{"type":["array","null"],"items":{"type":"string"}},"id":{"type":"string","format":"uuid","readOnly":true},"image_url":{"type":["string","null"]},"podcast_id":{"type":"string","format":"uuid"},"published_at":{"type":["string","null"],"readOnly":true},"scheduled_at":{"type":["string","null"],"readOnly":true},"source_ids":{"type":"array","items":{"type":"string","format":"uuid"},"readOnly":true},"status":{"$ref":"#/components/schemas/EpisodeStatus"},"title":{"type":["string","null"]},"updated_at":{"type":"string","readOnly":true},"url":{"type":["string","null"],"readOnly":true},"video_url":{"type":["string","null"],"readOnly":true}},"required":["audio_url","created_at","description","generation","host_ids","id","image_url","podcast_id","published_at","scheduled_at","source_ids","status","title","updated_at","url","video_url"],"description":"A podcast episode with publishing metadata and (when available) audio/video URLs."},"EpisodeStatus":{"type":"string","enum":["draft","published","scheduled"],"description":"Lifecycle state stored on the episode row. Generation progress is reported separately on the `generation` field, `generating`/`completed`/`failed` are not `status` values.","readOnly":true},"CreateEpisodeInput":{"type":"object","properties":{"description":{"type":"string","maxLength":2000},"host_ids":{"type":"array","items":{"type":"string"}},"image":{"type":"string","format":"uri"},"podcast_id":{"type":"string","format":"uuid","description":"Podcast that will own the new episode."},"title":{"type":"string","minLength":1,"maxLength":200}},"required":["podcast_id"],"additionalProperties":false,"description":"Fields for creating an empty episode row. No content is generated."},"AcceptedEpisodeResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"created_at":{"type":"string"},"host_ids":{"type":"array","items":{"type":"string"}},"id":{"type":"string"},"magic_created_host_ids":{"type":"array","items":{"type":"string"},"description":"Subset of host_ids that were magic-created by this import (newly added to the org). Empty when all speakers matched existing hosts."},"podcast_id":{"type":"string"},"status":{"type":"string","enum":["generating"]},"updated_at":{"type":"string"},"workflow_run_id":{"type":"string"}},"required":["created_at","host_ids","id","magic_created_host_ids","podcast_id","status","updated_at","workflow_run_id"]}},"required":["data"],"description":"Acknowledgement for an asynchronously-generated episode."},"GenerateEpisodeInput":{"type":"object","properties":{"host_ids":{"type":"array","items":{"type":"string"},"description":"Hosts to use for generation. In script mode, every segment host_id must be included here, or omit host_ids to infer them from the script.","example":["2e6939fe","a91c4d22"]},"options":{"type":"object","properties":{"episode_length":{"type":"string"},"episode_length_minutes":{"type":"integer","minimum":1,"maximum":75},"web_search":{"type":"boolean","default":true}},"default":{"web_search":true},"description":"Prompt-mode generation options. These are not used when `script` is provided."},"prompt":{"type":"string","minLength":10,"maxLength":10000,"description":"Prompt used to write the episode script. Provide either `prompt` or `script`, not both.","example":"Create a friendly two-host episode about simple habits for a calmer workweek."},"script":{"$ref":"#/components/schemas/ImportedEpisodeScript"},"source_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Source documents for prompt-based generation. Not supported when `script` is provided."},"podcast_id":{"type":"string","format":"uuid","description":"Podcast that will own the generated episode."},"render":{"type":"boolean","default":true,"description":"Whether to render audio and video once generation completes. Defaults to true. Set false to leave a draft you can review and render in the studio; generation is charged either way and rendering is free."}},"required":["podcast_id"],"additionalProperties":false,"description":"Fields for generating a new episode asynchronously. Use prompt mode to have Jellypod write the script, or script mode to import a validated structured script."},"ImportedEpisodeScript":{"type":"object","properties":{"chapters":{"type":"array","items":{"$ref":"#/components/schemas/ImportedScriptChapter"},"minItems":1,"maxItems":50,"description":"Ordered script chapters. Maximum 50 chapters."}},"required":["chapters"],"additionalProperties":false,"description":"Structured script input for episode generation. Script mode skips prompt-based script writing. Limits: 75000 total text characters, 50 chapters, 200 segments per chapter, 600 total segments, and 5000 characters per segment.","example":{"chapters":[{"segments":[{"host_id":"2e6939fe","text":"Welcome to the show. Today we are talking about one small habit that can make the week easier."},{"host_id":"a91c4d22","speed":1,"text":"I like that. Let us start with something simple someone can try tomorrow morning."}],"title":"Opening"}]}},"ImportedScriptChapter":{"type":"object","properties":{"segments":{"type":"array","items":{"$ref":"#/components/schemas/ImportedScriptSegment"},"minItems":1,"maxItems":200,"description":"Spoken turns in this chapter. Maximum 200 segments."},"title":{"type":"string","minLength":1,"maxLength":200,"description":"Optional chapter title.","example":"Opening"}},"required":["segments"],"additionalProperties":false,"description":"A group of imported script segments. Each chapter can contain up to 200 segments.","example":{"segments":[{"host_id":"2e6939fe","text":"Welcome to the show. Today we are talking about one small habit that can make the week easier."},{"host_id":"a91c4d22","speed":1,"text":"I like that. Let us start with something simple someone can try tomorrow morning."}],"title":"Opening"}},"ImportedScriptSegment":{"type":"object","properties":{"host_id":{"type":"string","minLength":1,"description":"Host ID for the speaker of this segment.","example":"2e6939fe"},"speed":{"type":"number","minimum":0.5,"maximum":2,"default":1,"description":"Optional playback speed for this segment. Defaults to 1.","example":1},"text":{"type":"string","minLength":1,"maxLength":5000,"description":"Text to synthesize for this segment. Maximum 5000 characters.","example":"Welcome to the show. Today we are talking about one small habit that can make the week easier."}},"required":["host_id","text"],"additionalProperties":false,"description":"One spoken turn in an imported script. The host must belong to your organization.","example":{"host_id":"2e6939fe","speed":1,"text":"Welcome to the show. Today we are talking about one small habit that can make the week easier."}},"ImportEpisodeInput":{"type":"object","properties":{"podcast_id":{"type":"string","format":"uuid","description":"Podcast that will own the imported generated episode."},"render":{"type":"boolean","default":true,"description":"Whether to render audio and video once generation completes. Defaults to true. Set false to leave a draft you can review and render in the studio; generation is charged either way and rendering is free."},"script":{"type":"string","minLength":1,"maxLength":75000,"description":"Script or transcript text. Bracketed speaker labels are resolved to existing or newly generated hosts.","example":"[Host One]\nWelcome to the show. Today we are talking about one small habit that can make the week easier.\n\n[Host Two]\nI like that. Let us start with something simple someone can try tomorrow morning."}},"required":["podcast_id","script"],"additionalProperties":false,"description":"Fields for importing script or transcript text and generating a new episode asynchronously."},"UpdateEpisodeInput":{"type":"object","properties":{"description":{"type":["string","null"],"maxLength":2000},"image":{"type":["string","null"],"format":"uri"},"title":{"type":"string","minLength":1,"maxLength":200}},"additionalProperties":false,"description":"Patchable episode fields. All optional; only provided fields are updated."},"UploadEpisodeImageResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"image_url":{"type":"string"}},"required":["id","image_url"]}},"required":["data"],"description":"The uploaded image URL."},"PublishEpisodeResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"scheduled_time":{"type":"string"},"status":{"type":"string","enum":["published","scheduled"]}},"required":["id","status"]}},"required":["data"],"description":"Result of a publish or schedule operation."},"PublishEpisodeInput":{"type":"object","properties":{"scheduled_time":{"type":"string","format":"date-time"}},"additionalProperties":false,"description":"Optional publishing options. Omit to publish immediately; provide `scheduled_time` to schedule for later."},"TimestampsJsonResponse":{"type":"object","properties":{"data":{"type":"object","properties":{"episode_id":{"type":"string"},"speakers":{"type":"array","items":{"type":"object","properties":{"host_id":{"type":"string"},"name":{"type":"string"}},"required":["host_id","name"]}},"words":{"type":"array","items":{"type":"object","properties":{"end":{"type":"number"},"speaker":{"type":["number","null"]},"start":{"type":"number"},"text":{"type":"string"}},"required":["end","speaker","start","text"]}}},"required":["episode_id","speakers","words"]}},"required":["data"],"description":"Word-level episode timestamps with speaker attribution. Speakers are referenced by integer index into the `speakers` array."},"ListHostsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/HostRow"}}},"required":["data"],"description":"Page of hosts. Use the `Link` response header (`rel=\"next\"`) to paginate."},"HostRow":{"type":"object","properties":{"backstory":{"type":["string","null"]},"created_at":{"type":"string","readOnly":true},"id":{"type":"string","description":"8-character hex host id (e.g. `2e6939fe`).","example":"2e6939fe","readOnly":true},"name":{"type":"string"},"personality":{"type":["string","null"]},"title":{"type":["string","null"]},"updated_at":{"type":"string","readOnly":true},"voice":{"type":["object","null"],"properties":{"accent":{"type":["string","null"]},"description":{"type":["string","null"]},"gender":{"type":"string","enum":["male","female","other"]},"id":{"type":"integer"},"language":{"type":["string","null"]},"model":{"type":["string","null"]},"voice_type":{"type":"string","enum":["professional","clone","design"]}},"required":["accent","description","gender","id","language","model","voice_type"]},"voice_id":{"type":["integer","null"]},"voice_model":{"type":["string","null"]}},"required":["backstory","created_at","id","name","personality","title","updated_at","voice","voice_id","voice_model"],"description":"A host (speaker/presenter) belonging to your organization."},"CreateHostInput":{"type":"object","properties":{"backstory":{"type":"string","minLength":10,"maxLength":3000},"image_path":{"type":"string"},"is_guest":{"type":"boolean"},"name":{"type":"string","minLength":1,"maxLength":100},"personality":{"type":"string","minLength":1,"maxLength":3000},"title":{"type":"string","minLength":1,"maxLength":100},"voice_id":{"type":"integer"},"voice_model":{"type":"string"}},"required":["backstory","name","voice_id"],"additionalProperties":false,"description":"Fields required to create a host."},"UpdateHostInput":{"type":"object","properties":{"backstory":{"type":"string","minLength":10,"maxLength":3000},"image_path":{"type":"string"},"is_guest":{"type":"boolean"},"name":{"type":"string","minLength":1,"maxLength":100},"personality":{"type":"string","minLength":1,"maxLength":3000},"title":{"type":"string","minLength":1,"maxLength":100},"voice_id":{"type":"integer"},"voice_model":{"type":"string"}},"additionalProperties":false,"description":"Patchable host fields. All optional; only provided fields are updated."},"ListPodcastsResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Podcast"}}},"required":["data"],"description":"Page of podcasts. Use the `Link` response header (`rel=\"next\"`) to paginate."},"Podcast":{"type":"object","properties":{"created_at":{"type":"string","readOnly":true},"description":{"type":"string"},"episode_count":{"type":"integer","minimum":0,"description":"Number of episodes that belong to this podcast.","readOnly":true},"episode_order":{"type":"string","enum":["episodic","serial"],"description":"Episode ordering: `episodic` (standalone) or `serial` (sequential). Always returned lowercase."},"host_ids":{"type":["array","null"],"items":{"type":"string"}},"id":{"type":"string","format":"uuid","readOnly":true},"image_url":{"type":["string","null"]},"languages":{"type":"array","items":{"type":"string"}},"rss_feed_url":{"type":"string","readOnly":true},"title":{"type":"string"},"updated_at":{"type":"string","readOnly":true},"url":{"type":"string","readOnly":true},"visibility":{"type":["string","null"],"enum":["public","private","unlisted",null],"description":"Visibility. Always returned lowercase."}},"required":["created_at","description","episode_count","episode_order","host_ids","id","image_url","languages","rss_feed_url","title","updated_at","url","visibility"],"description":"A podcast in your library with metadata, hosts, languages, and feed URLs."},"CreatePodcastInput":{"type":"object","properties":{"description":{"type":"string"},"episode_order":{"type":"string","enum":["episodic","serial"],"default":"serial"},"host_ids":{"type":"array","items":{"type":"string"},"minItems":1},"language":{"type":"string","pattern":"^[a-zA-Z]{2,3}$","default":"en"},"title":{"type":"string","maxLength":100},"visibility":{"type":"string","enum":["public","private"],"default":"public"}},"required":["host_ids","title"],"additionalProperties":false,"description":"Fields required to create a podcast."},"UpdatePodcastInput":{"type":"object","properties":{"description":{"type":"string"},"episode_order":{"type":"string","enum":["episodic","serial"]},"host_ids":{"type":"array","items":{"type":"string"},"minItems":1},"language":{"type":"string","pattern":"^[a-zA-Z]{2,3}$"},"title":{"type":"string","maxLength":100},"visibility":{"type":"string","enum":["public","private","unlisted"]}},"additionalProperties":false,"description":"Patchable podcast fields. All optional; only provided fields are updated."},"ListSourcesResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SourceRow"}}},"required":["data"],"description":"Page of sources. Use the `Link` response header (`rel=\"next\"`) to paginate."},"SourceRow":{"type":"object","properties":{"created_at":{"type":"string","readOnly":true},"error_message":{"type":["string","null"]},"id":{"type":"string","format":"uuid","readOnly":true},"metadata":{},"status":{"type":"string","readOnly":true},"title":{"type":["string","null"]},"type":{"type":["string","null"]},"updated_at":{"type":"string","readOnly":true}},"required":["created_at","error_message","id","status","title","type","updated_at"],"description":"A content source used as input for episodes."},"AcceptedSourceResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SourceRow"}},"required":["data"],"description":"Acknowledgement for asynchronous source processing."},"CreateSourceInput":{"oneOf":[{"type":"object","properties":{"title":{"type":"string"},"type":{"type":"string","enum":["url"]},"url":{"type":"string","format":"uri"}},"required":["type","url"],"additionalProperties":false},{"type":"object","properties":{"title":{"type":"string"},"type":{"type":"string","enum":["youtube"]},"url":{"type":"string","format":"uri"}},"required":["type","url"],"additionalProperties":false},{"type":"object","properties":{"content":{"type":"string","maxLength":100000},"title":{"type":"string"},"type":{"type":"string","enum":["text"]}},"required":["content","type"],"additionalProperties":false}],"description":"Body for creating a URL, YouTube, or text source. `type` is case-insensitive — the server lowercases it before validation. `url` is required when `type` is `url` or `youtube`; `content` is required when `type` is `text`."},"ListVoicesResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/VoiceRow"}}},"required":["data"],"description":"Page of voices. Use the `Link` response header (`rel=\"next\"`) to paginate."},"VoiceRow":{"type":"object","properties":{"accent":{"type":["string","null"]},"description":{"type":["string","null"]},"gender":{"type":"string","enum":["male","female","other"]},"id":{"type":"integer","description":"Positive integer voice id. Pass this value (as a number, not a string) to `voice_id` on `POST /v1/hosts`.","example":30142,"readOnly":true},"language":{"type":["string","null"],"description":"Language code the voice is filed under: the two-letter ISO 639-1 code where one exists, or the three-letter code where it does not (e.g. \"en\", \"ja\", \"fil\"). New codes appear as the catalog grows, so treat this as an open set rather than a fixed list.","example":"en","readOnly":true},"model":{"type":["string","null"],"description":"Provider-prefixed model string used to synthesize this voice (e.g. \"elevenlabs/eleven_v3\"). Null when the voice has no model configured.","example":"elevenlabs/eleven_v3","readOnly":true},"voice_type":{"type":"string","enum":["professional","clone","design"]}},"required":["accent","description","gender","id","language","model","voice_type"],"description":"A TTS voice available to your organization."}},"parameters":{}},"paths":{"/":{"get":{"operationId":"getApiIndex","security":[],"summary":"API discovery index","tags":["Health"],"responses":{"200":{"description":"Links to the API documentation, spec, and related services.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiIndex"}}}}}}},"/health":{"get":{"operationId":"health","tags":["Health"],"security":[],"responses":{"200":{"description":"Service is healthy","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]}},"required":["status"]}}}}}}},"/v1/account":{"get":{"operationId":"getAccount","summary":"Get the authenticated organization","tags":["Account"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Authenticated organization details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/episodes/{episode_id}/analytics":{"get":{"operationId":"getEpisodeAnalytics","security":[{"bearerAuth":[]}],"summary":"Get streaming analytics for an episode","tags":["Analytics"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Episode UUID"},"required":true,"description":"Episode UUID","in":"path","name":"episode_id"}],"responses":{"200":{"description":"Episode analytics","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/EpisodeAnalytics"}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/podcasts/{podcast_id}/analytics":{"get":{"operationId":"getPodcastAnalytics","security":[{"bearerAuth":[]}],"summary":"Get streaming analytics for a podcast","tags":["Analytics"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Podcast UUID"},"required":true,"description":"Podcast UUID","in":"path","name":"podcast_id"}],"responses":{"200":{"description":"Podcast analytics","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PodcastAnalytics"}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/episodes":{"get":{"operationId":"listEpisodes","security":[{"bearerAuth":[]}],"summary":"List episodes","tags":["Episodes"],"parameters":[{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"podcast_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"}],"responses":{"200":{"description":"Page of episodes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEpisodesResponse"}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"description":"Inserts an episode row with only the metadata you provide. No script, audio, or video is generated. Use `POST /v1/episodes/generate` to create an episode and trigger generation in one call.","operationId":"createEpisode","security":[{"bearerAuth":[]}],"summary":"Create an empty episode","tags":["Episodes"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEpisodeInput"}}}},"responses":{"201":{"description":"Episode created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Episode"}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Request `Content-Type` is not supported for this endpoint.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/episodes/generate":{"post":{"operationId":"generateEpisode","security":[{"bearerAuth":[]}],"summary":"Generate a new episode (asynchronous)","tags":["Episodes"],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x21-\\x7e]+$","description":"Reuse this key when resending the same generation request to avoid duplicate work."},"required":false,"description":"Reuse this key when resending the same generation request to avoid duplicate work.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateEpisodeInput"}}}},"responses":{"202":{"description":"Episode queued for generation","headers":{"Location":{"description":"Relative URL clients can poll for the accepted resource.","schema":{"type":"string"}},"Retry-After":{"description":"Suggested polling delay in seconds.","schema":{"minimum":1,"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedEpisodeResponse"}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Request `Content-Type` is not supported for this endpoint.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"502":{"description":"The API could not enqueue the downstream asynchronous workflow.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/episodes/import":{"post":{"operationId":"importEpisode","security":[{"bearerAuth":[]}],"summary":"Import script text and generate a new episode (asynchronous)","tags":["Episodes"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportEpisodeInput"}}}},"responses":{"202":{"description":"Imported episode queued for generation","headers":{"Location":{"description":"Relative URL clients can poll for the accepted resource.","schema":{"type":"string"}},"Retry-After":{"description":"Suggested polling delay in seconds.","schema":{"minimum":1,"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedEpisodeResponse"}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Request `Content-Type` is not supported for this endpoint.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"502":{"description":"The API could not enqueue the downstream asynchronous workflow.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/episodes/{episode_id}":{"patch":{"operationId":"updateEpisode","security":[{"bearerAuth":[]}],"summary":"Update episode fields","tags":["Episodes"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Episode UUID"},"required":true,"description":"Episode UUID","in":"path","name":"episode_id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEpisodeInput"}},"application/merge-patch+json":{"schema":{"$ref":"#/components/schemas/UpdateEpisodeInput"}}}},"responses":{"200":{"description":"Updated episode","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Episode"}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Request `Content-Type` is not supported for this endpoint.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"getEpisode","security":[{"bearerAuth":[]}],"summary":"Get an episode","tags":["Episodes"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Episode UUID"},"required":true,"description":"Episode UUID","in":"path","name":"episode_id"}],"responses":{"200":{"description":"Episode","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Episode"}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"deleteEpisode","security":[{"bearerAuth":[]}],"summary":"Delete an episode","tags":["Episodes"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Episode UUID"},"required":true,"description":"Episode UUID","in":"path","name":"episode_id"}],"responses":{"204":{"description":"Episode deleted"},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/episodes/{episode_id}/image":{"put":{"operationId":"uploadEpisodeImage","security":[{"bearerAuth":[]}],"summary":"Upload an episode cover image (raw image bytes in body)","tags":["Episodes"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Episode UUID"},"required":true,"description":"Episode UUID","in":"path","name":"episode_id"}],"requestBody":{"description":"Raw image bytes. Set `Content-Type` to `image/jpeg`, `image/png`, or `image/webp`.","required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"Image uploaded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadEpisodeImageResponse"}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Request `Content-Type` is not supported for this endpoint.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/episodes/{episode_id}/publish":{"post":{"operationId":"publishEpisode","security":[{"bearerAuth":[]}],"summary":"Publish or schedule an episode","tags":["Episodes"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Episode UUID"},"required":true,"description":"Episode UUID","in":"path","name":"episode_id"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishEpisodeInput"}}}},"responses":{"200":{"description":"Episode published or scheduled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishEpisodeResponse"}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Request `Content-Type` is not supported for this endpoint.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Request was well-formed but the resource is in a state that does not allow this operation (e.g. publishing an episode that has not finished rendering).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/episodes/{episode_id}/unpublish":{"post":{"operationId":"unpublishEpisode","security":[{"bearerAuth":[]}],"summary":"Unpublish a published or scheduled episode","tags":["Episodes"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Episode UUID"},"required":true,"description":"Episode UUID","in":"path","name":"episode_id"}],"responses":{"200":{"description":"Episode unpublished","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Episode"}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Request `Content-Type` is not supported for this endpoint.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Request was well-formed but the resource is in a state that does not allow this operation (e.g. publishing an episode that has not finished rendering).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/episodes/{episode_id}/timestamps":{"get":{"description":"Returns timestamps in the requested `format`. Use `format=json` (default) for structured timestamps, `format=srt` for SubRip, or `format=vtt` for WebVTT.","operationId":"getEpisodeTimestamps","security":[{"bearerAuth":[]}],"summary":"Get episode timestamps","tags":["Episodes"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Episode UUID"},"required":true,"description":"Episode UUID","in":"path","name":"episode_id"},{"schema":{"type":"string","enum":["json","srt","vtt"],"description":"Response format. `json` returns word-level timestamps with speaker attribution; `srt` returns SubRip; `vtt` returns WebVTT. Defaults to `json`."},"required":false,"description":"Response format. `json` returns word-level timestamps with speaker attribution; `srt` returns SubRip; `vtt` returns WebVTT. Defaults to `json`.","in":"query","name":"format"}],"responses":{"200":{"description":"Timestamps in the requested format. Response `Content-Type` reflects `format`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimestampsJsonResponse"}},"application/x-subrip":{"schema":{"type":"string"}},"text/vtt":{"schema":{"type":"string"}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/hosts":{"get":{"operationId":"listHosts","security":[{"bearerAuth":[]}],"summary":"List hosts","tags":["Hosts"],"parameters":[{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Page of hosts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListHostsResponse"}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"createHost","security":[{"bearerAuth":[]}],"summary":"Create a host","tags":["Hosts"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateHostInput"}}}},"responses":{"201":{"description":"Host created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/HostRow"}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Request `Content-Type` is not supported for this endpoint.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/hosts/{host_id}":{"get":{"operationId":"getHost","security":[{"bearerAuth":[]}],"summary":"Get a host","tags":["Hosts"],"parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}$/i","description":"8-character hex host id (e.g. `2e6939fe`).","example":"2e6939fe"},"required":true,"description":"8-character hex host id (e.g. `2e6939fe`).","in":"path","name":"host_id"}],"responses":{"200":{"description":"Host","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/HostRow"}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"updateHost","security":[{"bearerAuth":[]}],"summary":"Update a host","tags":["Hosts"],"parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}$/i","description":"8-character hex host id (e.g. `2e6939fe`).","example":"2e6939fe"},"required":true,"description":"8-character hex host id (e.g. `2e6939fe`).","in":"path","name":"host_id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateHostInput"}},"application/merge-patch+json":{"schema":{"$ref":"#/components/schemas/UpdateHostInput"}}}},"responses":{"200":{"description":"Host updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/HostRow"}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Request `Content-Type` is not supported for this endpoint.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"deleteHost","security":[{"bearerAuth":[]}],"summary":"Delete a host","tags":["Hosts"],"parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}$/i","description":"8-character hex host id (e.g. `2e6939fe`).","example":"2e6939fe"},"required":true,"description":"8-character hex host id (e.g. `2e6939fe`).","in":"path","name":"host_id"}],"responses":{"204":{"description":"Host deleted"},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/podcasts":{"get":{"operationId":"listPodcasts","security":[{"bearerAuth":[]}],"summary":"List podcasts","tags":["Podcasts"],"parameters":[{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Page of podcasts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPodcastsResponse"}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"createPodcast","security":[{"bearerAuth":[]}],"summary":"Create a podcast","tags":["Podcasts"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePodcastInput"}}}},"responses":{"201":{"description":"Podcast created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Podcast"}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Request `Content-Type` is not supported for this endpoint.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/podcasts/{podcast_id}":{"get":{"operationId":"getPodcast","security":[{"bearerAuth":[]}],"summary":"Get a podcast","tags":["Podcasts"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Podcast UUID"},"required":true,"description":"Podcast UUID","in":"path","name":"podcast_id"}],"responses":{"200":{"description":"Podcast","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Podcast"}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"updatePodcast","security":[{"bearerAuth":[]}],"summary":"Update a podcast","tags":["Podcasts"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Podcast UUID"},"required":true,"description":"Podcast UUID","in":"path","name":"podcast_id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePodcastInput"}},"application/merge-patch+json":{"schema":{"$ref":"#/components/schemas/UpdatePodcastInput"}}}},"responses":{"200":{"description":"Podcast updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Podcast"}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Request `Content-Type` is not supported for this endpoint.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"deletePodcast","security":[{"bearerAuth":[]}],"summary":"Delete a podcast","tags":["Podcasts"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Podcast UUID"},"required":true,"description":"Podcast UUID","in":"path","name":"podcast_id"}],"responses":{"204":{"description":"Podcast deleted"},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/podcasts/{podcast_id}/image":{"put":{"operationId":"updatePodcastImage","security":[{"bearerAuth":[]}],"summary":"Replace the podcast cover image","tags":["Podcasts"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Podcast UUID"},"required":true,"description":"Podcast UUID","in":"path","name":"podcast_id"}],"requestBody":{"description":"Raw image bytes. Set `Content-Type` to `image/jpeg`, `image/png`, or `image/webp`.","required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"Image updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Podcast"}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Request `Content-Type` is not supported for this endpoint.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/sources":{"get":{"operationId":"listSources","security":[{"bearerAuth":[]}],"summary":"List sources","tags":["Sources"],"parameters":[{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"type","in":"query"}],"responses":{"200":{"description":"Page of sources","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSourcesResponse"}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"operationId":"createSource","security":[{"bearerAuth":[]}],"summary":"Create a source from a URL, YouTube link, or text payload","tags":["Sources"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSourceInput"}}}},"responses":{"202":{"description":"Source accepted for processing","headers":{"Location":{"description":"Relative URL clients can poll for the accepted resource.","schema":{"type":"string"}},"Retry-After":{"description":"Suggested polling delay in seconds.","schema":{"minimum":1,"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedSourceResponse"}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Request `Content-Type` is not supported for this endpoint.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"502":{"description":"The API could not enqueue the downstream asynchronous workflow.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/sources/{source_id}":{"get":{"operationId":"getSource","security":[{"bearerAuth":[]}],"summary":"Get a source","tags":["Sources"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Source UUID"},"required":true,"description":"Source UUID","in":"path","name":"source_id"}],"responses":{"200":{"description":"Source","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SourceRow"}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"deleteSource","security":[{"bearerAuth":[]}],"summary":"Delete a source","tags":["Sources"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Source UUID"},"required":true,"description":"Source UUID","in":"path","name":"source_id"}],"responses":{"204":{"description":"Source deleted"},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/sources/uploads":{"post":{"operationId":"requestSourceUpload","security":[{"bearerAuth":[]}],"summary":"Reserve a file Source and receive a scoped upload URL","tags":["Sources"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file_name":{"type":"string","minLength":1,"maxLength":255},"mime_type":{"type":"string"},"prepare_visuals":{"type":"boolean","default":false,"description":"Deprecated compatibility field. Source preparation is automatic.","deprecated":true},"size_bytes":{"type":"integer","exclusiveMinimum":0,"maximum":104857600},"title":{"type":"string","minLength":1,"maxLength":500}},"required":["file_name","mime_type","size_bytes"],"additionalProperties":false}}}},"responses":{"201":{"description":"Upload slot reserved. PUT raw file bytes to upload.url with the returned headers, then POST complete_path. File content is processed asynchronously.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"complete_path":{"type":"string"},"source":{"type":"object","properties":{"created_at":{"type":"string"},"error_message":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"metadata":{},"status":{"type":"string"},"title":{"type":["string","null"]},"type":{"type":["string","null"]},"updated_at":{"type":"string"}},"required":["created_at","error_message","id","status","title","type","updated_at"]},"upload":{"type":"object","properties":{"expires_at":{"type":"string","format":"date-time"},"headers":{"type":"object","properties":{"content-type":{"type":"string"}},"required":["content-type"]},"method":{"type":"string","enum":["PUT"]},"url":{"type":"string","format":"uri"}},"required":["expires_at","headers","method","url"]}},"required":["complete_path","source","upload"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"502":{"description":"The API could not enqueue the downstream asynchronous workflow.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/sources/{source_id}/complete-upload":{"post":{"operationId":"completeSourceUpload","security":[{"bearerAuth":[]}],"summary":"Validate an uploaded file and start Source processing","tags":["Sources"],"parameters":[{"schema":{"type":"string","format":"uuid","description":"Source UUID"},"required":true,"description":"Source UUID","in":"path","name":"source_id"}],"responses":{"202":{"description":"File accepted for processing. Voiceover requires completed Sources prepared with visuals; Video and Short workflows can wait for processing Sources.","headers":{"Location":{"description":"Relative URL clients can poll for the accepted resource.","schema":{"type":"string"}},"Retry-After":{"description":"Suggested polling delay in seconds.","schema":{"minimum":1,"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedSourceResponse"}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"502":{"description":"The API could not enqueue the downstream asynchronous workflow.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/videos/options":{"get":{"operationId":"getVideoOptions","security":[{"bearerAuth":[]}],"summary":"Discover video creation options","tags":["Videos"],"responses":{"200":{"description":"Creation options and saved defaults","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"default_duration_seconds":{"type":["number","null"]},"default_host_id":{"type":["string","null"]},"default_language":{"type":"string"},"default_orientation":{"type":"string"},"default_style_id":{"type":["string","null"]},"guidance":{"type":"string"},"object":{"type":"string","enum":["video","short","voiceover"]},"styles":{"type":"array","items":{"type":"object","properties":{"description":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"}},"required":["description","id","name"]}},"supported_duration_seconds":{"type":"array","items":{"type":"number"}}},"required":["default_duration_seconds","default_host_id","default_language","default_orientation","default_style_id","guidance","object","styles","supported_duration_seconds"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/shorts/options":{"get":{"operationId":"getShortOptions","security":[{"bearerAuth":[]}],"summary":"Discover short creation options","tags":["Shorts"],"responses":{"200":{"description":"Creation options and saved defaults","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"default_duration_seconds":{"type":["number","null"]},"default_host_id":{"type":["string","null"]},"default_language":{"type":"string"},"default_orientation":{"type":"string"},"default_style_id":{"type":["string","null"]},"guidance":{"type":"string"},"object":{"type":"string","enum":["video","short","voiceover"]},"styles":{"type":"array","items":{"type":"object","properties":{"description":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"}},"required":["description","id","name"]}},"supported_duration_seconds":{"type":"array","items":{"type":"number"}}},"required":["default_duration_seconds","default_host_id","default_language","default_orientation","default_style_id","guidance","object","styles","supported_duration_seconds"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/voiceovers/options":{"get":{"operationId":"getVoiceoverOptions","security":[{"bearerAuth":[]}],"summary":"Discover voiceover creation options","tags":["Voiceovers"],"responses":{"200":{"description":"Creation options and saved defaults","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"default_duration_seconds":{"type":["number","null"]},"default_host_id":{"type":["string","null"]},"default_language":{"type":"string"},"default_orientation":{"type":"string"},"default_style_id":{"type":["string","null"]},"guidance":{"type":"string"},"object":{"type":"string","enum":["video","short","voiceover"]},"styles":{"type":"array","items":{"type":"object","properties":{"description":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"}},"required":["description","id","name"]}},"supported_duration_seconds":{"type":"array","items":{"type":"number"}}},"required":["default_duration_seconds","default_host_id","default_language","default_orientation","default_style_id","guidance","object","styles","supported_duration_seconds"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/videos/{product_id}":{"get":{"security":[{"bearerAuth":[]}],"tags":["Videos"],"operationId":"getVideo","summary":"Get a video","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"product_id","in":"path"}],"responses":{"200":{"description":"Product details","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"created_at":{"type":"string"},"error":{"type":["string","null"]},"generation_id":{"type":["string","null"]},"host_id":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["video"]},"phase":{"type":["string","null"]},"status":{"type":"string","enum":["idle","generating","completed","failed"]},"studio_url":{"type":"string","format":"uri"},"style_id":{"type":"string"},"target_duration_seconds":{"type":["number","null"]},"title":{"type":"string"},"updated_at":{"type":"string"}},"required":["created_at","error","generation_id","host_id","id","object","phase","status","studio_url","style_id","target_duration_seconds","title","updated_at"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/videos/{product_id}/status":{"get":{"security":[{"bearerAuth":[]}],"tags":["Videos"],"operationId":"getVideoStatus","summary":"Check video generation","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"product_id","in":"path"}],"responses":{"200":{"description":"Current generation status","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"error":{"type":["string","null"]},"generation_id":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["video","short","voiceover"]},"phase":{"type":["string","null"]},"status":{"type":"string","enum":["idle","generating","completed","failed"]},"studio_url":{"type":"string","format":"uri"},"poll_after_seconds":{"type":"number"}},"required":["error","generation_id","id","object","phase","status","studio_url","poll_after_seconds"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/videos/{product_id}/retry":{"post":{"security":[{"bearerAuth":[]}],"tags":["Videos"],"operationId":"retryVideo","summary":"Retry a failed video","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"product_id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x21-\\x7e]+$","description":"Required stable key for one logical generation command. Reuse it when the HTTP response is lost."},"required":true,"description":"Required stable key for one logical generation command. Reuse it when the HTTP response is lost.","name":"idempotency-key","in":"header"}],"responses":{"202":{"description":"Generation retry accepted","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"created_at":{"type":"string"},"error":{"type":["string","null"]},"generation_id":{"type":["string","null"]},"host_id":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["video"]},"phase":{"type":["string","null"]},"status":{"type":"string","enum":["idle","generating","completed","failed"]},"studio_url":{"type":"string","format":"uri"},"style_id":{"type":"string"},"target_duration_seconds":{"type":["number","null"]},"title":{"type":"string"},"updated_at":{"type":"string"}},"required":["created_at","error","generation_id","host_id","id","object","phase","status","studio_url","style_id","target_duration_seconds","title","updated_at"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/videos/{product_id}/download":{"get":{"security":[{"bearerAuth":[]}],"tags":["Videos"],"operationId":"downloadVideo","summary":"Get the video download","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"product_id","in":"path"}],"responses":{"200":{"description":"Download availability and URL","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"delivery":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["available"]},"origin":{"type":"string","enum":["mux","storage"]},"url":{"type":"string","format":"uri"}},"required":["kind","origin","url"]},{"type":"object","properties":{"kind":{"type":"string","enum":["preparing"]},"reason":{"type":"string","enum":["ingest","rendition"]}},"required":["kind","reason"]},{"type":"object","properties":{"kind":{"type":"string","enum":["unavailable"]}},"required":["kind"]}]},"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["video","short","voiceover"]}},"required":["delivery","id","object"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/shorts/{product_id}":{"get":{"security":[{"bearerAuth":[]}],"tags":["Shorts"],"operationId":"getShort","summary":"Get a short","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"product_id","in":"path"}],"responses":{"200":{"description":"Product details","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"created_at":{"type":"string"},"error":{"type":["string","null"]},"generation_id":{"type":["string","null"]},"host_id":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["short"]},"phase":{"type":["string","null"]},"status":{"type":"string","enum":["idle","generating","completed","failed"]},"studio_url":{"type":"string","format":"uri"},"style_id":{"type":"string"},"target_duration_seconds":{"type":["number","null"]},"title":{"type":"string"},"updated_at":{"type":"string"}},"required":["created_at","error","generation_id","host_id","id","object","phase","status","studio_url","style_id","target_duration_seconds","title","updated_at"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/shorts/{product_id}/status":{"get":{"security":[{"bearerAuth":[]}],"tags":["Shorts"],"operationId":"getShortStatus","summary":"Check short generation","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"product_id","in":"path"}],"responses":{"200":{"description":"Current generation status","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"error":{"type":["string","null"]},"generation_id":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["video","short","voiceover"]},"phase":{"type":["string","null"]},"status":{"type":"string","enum":["idle","generating","completed","failed"]},"studio_url":{"type":"string","format":"uri"},"poll_after_seconds":{"type":"number"}},"required":["error","generation_id","id","object","phase","status","studio_url","poll_after_seconds"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/shorts/{product_id}/retry":{"post":{"security":[{"bearerAuth":[]}],"tags":["Shorts"],"operationId":"retryShort","summary":"Retry a failed short","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"product_id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x21-\\x7e]+$","description":"Required stable key for one logical generation command. Reuse it when the HTTP response is lost."},"required":true,"description":"Required stable key for one logical generation command. Reuse it when the HTTP response is lost.","name":"idempotency-key","in":"header"}],"responses":{"202":{"description":"Generation retry accepted","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"created_at":{"type":"string"},"error":{"type":["string","null"]},"generation_id":{"type":["string","null"]},"host_id":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["short"]},"phase":{"type":["string","null"]},"status":{"type":"string","enum":["idle","generating","completed","failed"]},"studio_url":{"type":"string","format":"uri"},"style_id":{"type":"string"},"target_duration_seconds":{"type":["number","null"]},"title":{"type":"string"},"updated_at":{"type":"string"}},"required":["created_at","error","generation_id","host_id","id","object","phase","status","studio_url","style_id","target_duration_seconds","title","updated_at"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/shorts/{product_id}/download":{"get":{"security":[{"bearerAuth":[]}],"tags":["Shorts"],"operationId":"downloadShort","summary":"Get the short download","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"product_id","in":"path"}],"responses":{"200":{"description":"Download availability and URL","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"delivery":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["available"]},"origin":{"type":"string","enum":["mux","storage"]},"url":{"type":"string","format":"uri"}},"required":["kind","origin","url"]},{"type":"object","properties":{"kind":{"type":"string","enum":["preparing"]},"reason":{"type":"string","enum":["ingest","rendition"]}},"required":["kind","reason"]},{"type":"object","properties":{"kind":{"type":"string","enum":["unavailable"]}},"required":["kind"]}]},"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["video","short","voiceover"]}},"required":["delivery","id","object"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/voiceovers/{product_id}":{"get":{"security":[{"bearerAuth":[]}],"tags":["Voiceovers"],"operationId":"getVoiceover","summary":"Get a voiceover","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"product_id","in":"path"}],"responses":{"200":{"description":"Product details","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"created_at":{"type":"string"},"error":{"type":["string","null"]},"generation_id":{"type":["string","null"]},"host_id":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["voiceover"]},"phase":{"type":["string","null"]},"status":{"type":"string","enum":["idle","generating","completed","failed"]},"studio_url":{"type":"string","format":"uri"},"style_id":{"type":"string"},"target_duration_seconds":{"type":["number","null"]},"title":{"type":"string"},"updated_at":{"type":"string"}},"required":["created_at","error","generation_id","host_id","id","object","phase","status","studio_url","style_id","target_duration_seconds","title","updated_at"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/voiceovers/{product_id}/status":{"get":{"security":[{"bearerAuth":[]}],"tags":["Voiceovers"],"operationId":"getVoiceoverStatus","summary":"Check voiceover generation","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"product_id","in":"path"}],"responses":{"200":{"description":"Current generation status","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"error":{"type":["string","null"]},"generation_id":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["video","short","voiceover"]},"phase":{"type":["string","null"]},"status":{"type":"string","enum":["idle","generating","completed","failed"]},"studio_url":{"type":"string","format":"uri"},"poll_after_seconds":{"type":"number"}},"required":["error","generation_id","id","object","phase","status","studio_url","poll_after_seconds"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/voiceovers/{product_id}/retry":{"post":{"security":[{"bearerAuth":[]}],"tags":["Voiceovers"],"operationId":"retryVoiceover","summary":"Retry a failed voiceover","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"product_id","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x21-\\x7e]+$","description":"Required stable key for one logical generation command. Reuse it when the HTTP response is lost."},"required":true,"description":"Required stable key for one logical generation command. Reuse it when the HTTP response is lost.","name":"idempotency-key","in":"header"}],"responses":{"202":{"description":"Generation retry accepted","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"created_at":{"type":"string"},"error":{"type":["string","null"]},"generation_id":{"type":["string","null"]},"host_id":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["voiceover"]},"phase":{"type":["string","null"]},"status":{"type":"string","enum":["idle","generating","completed","failed"]},"studio_url":{"type":"string","format":"uri"},"style_id":{"type":"string"},"target_duration_seconds":{"type":["number","null"]},"title":{"type":"string"},"updated_at":{"type":"string"}},"required":["created_at","error","generation_id","host_id","id","object","phase","status","studio_url","style_id","target_duration_seconds","title","updated_at"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/voiceovers/{product_id}/download":{"get":{"security":[{"bearerAuth":[]}],"tags":["Voiceovers"],"operationId":"downloadVoiceover","summary":"Get the voiceover download","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"product_id","in":"path"}],"responses":{"200":{"description":"Download availability and URL","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"delivery":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["available"]},"origin":{"type":"string","enum":["mux","storage"]},"url":{"type":"string","format":"uri"}},"required":["kind","origin","url"]},{"type":"object","properties":{"kind":{"type":"string","enum":["preparing"]},"reason":{"type":"string","enum":["ingest","rendition"]}},"required":["kind","reason"]},{"type":"object","properties":{"kind":{"type":"string","enum":["unavailable"]}},"required":["kind"]}]},"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["video","short","voiceover"]}},"required":["delivery","id","object"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/videos":{"get":{"security":[{"bearerAuth":[]}],"tags":["Videos"],"operationId":"listVideos","summary":"List videos","parameters":[{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Page of videos","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"created_at":{"type":"string"},"error":{"type":["string","null"]},"generation_id":{"type":["string","null"]},"host_id":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["video"]},"phase":{"type":["string","null"]},"status":{"type":"string","enum":["idle","generating","completed","failed"]},"studio_url":{"type":"string","format":"uri"},"style_id":{"type":"string"},"target_duration_seconds":{"type":["number","null"]},"title":{"type":"string"},"updated_at":{"type":"string"}},"required":["created_at","error","generation_id","host_id","id","object","phase","status","studio_url","style_id","target_duration_seconds","title","updated_at"]}}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"security":[{"bearerAuth":[]}],"tags":["Videos"],"operationId":"createVideo","summary":"Create a video","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x21-\\x7e]+$","description":"Required stable key for one logical generation command. Reuse it when the HTTP response is lost."},"required":true,"description":"Required stable key for one logical generation command. Reuse it when the HTTP response is lost.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"host_id":{"type":"string","format":"uuid","description":"Narrator Host ID. Uses the saved organization narrator when omitted."},"language":{"type":"string","description":"Narration language code. Defaults to organization settings."},"orientation":{"type":"string","enum":["AUTO","PORTRAIT","LANDSCAPE","SQUARE"],"description":"Output orientation. Defaults to the product policy."},"prompt":{"type":"string","minLength":1,"maxLength":20000,"description":"Describe the story, audience, and desired result."},"source_ids":{"type":"array","items":{"type":"string","format":"uuid"},"maxItems":100,"description":"Sources owned by your organization. Generation waits for processing Sources; missing or failed Sources are rejected."},"style_id":{"type":"string","description":"Visual style ID from style discovery; defaults to organization settings."},"target_duration_seconds":{"anyOf":[{"type":"number","enum":[180]},{"type":"number","enum":[300]},{"type":"number","enum":[420]},{"type":"number","enum":[600]},{"type":"number","enum":[900]},{"type":"number","enum":[1200]}],"description":"Supported Video duration. Defaults to the saved duration or 420 seconds."}},"required":["prompt"],"additionalProperties":false}}}},"responses":{"202":{"description":"Generation accepted. Check the status URL until generation finishes.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"created_at":{"type":"string"},"error":{"type":["string","null"]},"generation_id":{"type":["string","null"]},"host_id":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["video"]},"phase":{"type":["string","null"]},"status":{"type":"string","enum":["idle","generating","completed","failed"]},"studio_url":{"type":"string","format":"uri"},"style_id":{"type":"string"},"target_duration_seconds":{"type":["number","null"]},"title":{"type":"string"},"updated_at":{"type":"string"}},"required":["created_at","error","generation_id","host_id","id","object","phase","status","studio_url","style_id","target_duration_seconds","title","updated_at"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Request `Content-Type` is not supported for this endpoint.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/shorts":{"get":{"security":[{"bearerAuth":[]}],"tags":["Shorts"],"operationId":"listShorts","summary":"List shorts","parameters":[{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Page of shorts","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"created_at":{"type":"string"},"error":{"type":["string","null"]},"generation_id":{"type":["string","null"]},"host_id":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["short"]},"phase":{"type":["string","null"]},"status":{"type":"string","enum":["idle","generating","completed","failed"]},"studio_url":{"type":"string","format":"uri"},"style_id":{"type":"string"},"target_duration_seconds":{"type":["number","null"]},"title":{"type":"string"},"updated_at":{"type":"string"}},"required":["created_at","error","generation_id","host_id","id","object","phase","status","studio_url","style_id","target_duration_seconds","title","updated_at"]}}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"security":[{"bearerAuth":[]}],"tags":["Shorts"],"operationId":"createShort","summary":"Create a short","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x21-\\x7e]+$","description":"Required stable key for one logical generation command. Reuse it when the HTTP response is lost."},"required":true,"description":"Required stable key for one logical generation command. Reuse it when the HTTP response is lost.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"host_id":{"type":"string","format":"uuid","description":"Narrator Host ID. Uses the saved organization narrator when omitted."},"language":{"type":"string","description":"Narration language code. Defaults to organization settings."},"orientation":{"type":"string","enum":["AUTO","PORTRAIT","LANDSCAPE","SQUARE"],"description":"Output orientation. Defaults to the product policy."},"prompt":{"type":"string","minLength":1,"maxLength":20000,"description":"Describe the story, audience, and desired result."},"source_ids":{"type":"array","items":{"type":"string","format":"uuid"},"maxItems":100,"description":"Sources owned by your organization. Generation waits for processing Sources; missing or failed Sources are rejected."},"style_id":{"type":"string","description":"Visual style ID from style discovery; defaults to organization settings."},"background_music":{"type":"boolean","description":"Include background music. Defaults to organization settings."},"target_duration_seconds":{"anyOf":[{"type":"number","enum":[30]},{"type":"number","enum":[60]}],"default":30,"description":"Short duration: 30 or 60 seconds."}},"required":["prompt"],"additionalProperties":false}}}},"responses":{"202":{"description":"Generation accepted. Check the status URL until generation finishes.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"created_at":{"type":"string"},"error":{"type":["string","null"]},"generation_id":{"type":["string","null"]},"host_id":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["short"]},"phase":{"type":["string","null"]},"status":{"type":"string","enum":["idle","generating","completed","failed"]},"studio_url":{"type":"string","format":"uri"},"style_id":{"type":"string"},"target_duration_seconds":{"type":["number","null"]},"title":{"type":"string"},"updated_at":{"type":"string"}},"required":["created_at","error","generation_id","host_id","id","object","phase","status","studio_url","style_id","target_duration_seconds","title","updated_at"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Request `Content-Type` is not supported for this endpoint.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/voiceovers":{"get":{"security":[{"bearerAuth":[]}],"tags":["Voiceovers"],"operationId":"listVoiceovers","summary":"List voiceovers","parameters":[{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Page of voiceovers","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"created_at":{"type":"string"},"error":{"type":["string","null"]},"generation_id":{"type":["string","null"]},"host_id":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["voiceover"]},"phase":{"type":["string","null"]},"status":{"type":"string","enum":["idle","generating","completed","failed"]},"studio_url":{"type":"string","format":"uri"},"style_id":{"type":"string"},"target_duration_seconds":{"type":["number","null"]},"title":{"type":"string"},"updated_at":{"type":"string"}},"required":["created_at","error","generation_id","host_id","id","object","phase","status","studio_url","style_id","target_duration_seconds","title","updated_at"]}}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"post":{"security":[{"bearerAuth":[]}],"tags":["Voiceovers"],"operationId":"createVoiceover","summary":"Create a voiceover","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x21-\\x7e]+$","description":"Required stable key for one logical generation command. Reuse it when the HTTP response is lost."},"required":true,"description":"Required stable key for one logical generation command. Reuse it when the HTTP response is lost.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"host_id":{"type":"string","format":"uuid","description":"Narrator Host ID. Uses the saved organization narrator when omitted."},"language":{"type":"string","description":"Narration language code. Defaults to organization settings."},"orientation":{"type":"string","enum":["AUTO","PORTRAIT","LANDSCAPE","SQUARE"],"description":"Output orientation. Defaults to the product policy."},"captions_enabled":{"type":"boolean","default":false,"description":"Show narration captions."},"direction":{"type":"string","maxLength":4000,"description":"Optional narration instructions for the uploaded visuals."},"source_ids":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":10,"description":"Uploaded document or image Sources, in presentation order."},"target_duration_seconds":{"anyOf":[{"type":"number","enum":[180]},{"type":"number","enum":[300]},{"type":"number","enum":[420]},{"type":"number","enum":[600]},{"type":"number","enum":[900]},{"type":"number","enum":[1200]},{"type":"number","enum":[1800]},{"type":"number","enum":[2700]},{"type":"number","enum":[3600]}],"description":"Supported narration duration. Omit for automatic duration based on source content."},"visual_motion":{"type":"string","enum":["static","dynamic"],"default":"static","description":"Use static visuals or animated movement."}},"required":["source_ids"],"additionalProperties":false}}}},"responses":{"202":{"description":"Generation accepted. Check the status URL until generation finishes.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"created_at":{"type":"string"},"error":{"type":["string","null"]},"generation_id":{"type":["string","null"]},"host_id":{"type":["string","null"]},"id":{"type":"string","format":"uuid"},"object":{"type":"string","enum":["voiceover"]},"phase":{"type":["string","null"]},"status":{"type":"string","enum":["idle","generating","completed","failed"]},"studio_url":{"type":"string","format":"uri"},"style_id":{"type":"string"},"target_duration_seconds":{"type":["number","null"]},"title":{"type":"string"},"updated_at":{"type":"string"}},"required":["created_at","error","generation_id","host_id","id","object","phase","status","studio_url","style_id","target_duration_seconds","title","updated_at"]}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Request `Content-Type` is not supported for this endpoint.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/voices":{"get":{"operationId":"listVoices","security":[{"bearerAuth":[]}],"summary":"List voices","tags":["Voices"],"parameters":[{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"gender","in":"query"},{"schema":{"type":"string","pattern":"^[a-zA-Z]{2,3}$"},"required":false,"name":"language","in":"query"},{"schema":{"type":"string"},"required":false,"name":"voice_type","in":"query"}],"responses":{"200":{"description":"Page of voices","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListVoicesResponse"}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/voices/{voice_id}":{"get":{"operationId":"getVoice","security":[{"bearerAuth":[]}],"summary":"Get a voice","tags":["Voices"],"parameters":[{"schema":{"type":"string","pattern":"^[1-9]\\d*$","description":"Voice ID (positive integer).","example":"30142"},"required":true,"description":"Voice ID (positive integer).","in":"path","name":"voice_id"}],"responses":{"200":{"description":"Voice","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/VoiceRow"}},"required":["data"]}}}},"400":{"description":"Validation failed or malformed request.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated, but this API key does not have access to this resource.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Resource not found.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Rate limit exceeded. Response includes `Retry-After`, `RateLimit`, and `RateLimit-Policy` headers (IETF draft).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}}},"webhooks":{}}