{
  "components": {
    "schemas": {
      "BatchStatus": {
        "properties": {
          "batch_id": {
            "title": "Batch Id",
            "type": "string"
          },
          "items": {
            "description": "Every job in the batch, in queue order",
            "items": {
              "$ref": "#/components/schemas/TranscriptionApiResponse"
            },
            "title": "Items",
            "type": "array"
          },
          "title": {
            "title": "Title",
            "type": "string"
          }
        },
        "required": [
          "batch_id",
          "title",
          "items"
        ],
        "title": "BatchStatus",
        "type": "object"
      },
      "BurnSubtitlesRequest": {
        "properties": {
          "background": {
            "default": false,
            "description": "Draw a semi-transparent black box behind the subtitles for readability. Off = white text with a black outline.",
            "title": "Background",
            "type": "boolean"
          },
          "font_size": {
            "$ref": "#/components/schemas/FontSize",
            "default": "default",
            "description": "Subtitle text size: default ≈7% of video height, large ≈10%, xl ≈12.5%."
          },
          "language_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO-639-1/639-3 code of the video's spoken language, e.g. \"en\"; can improve quality. Omit to auto-detect.",
            "title": "Language Code"
          },
          "quality": {
            "$ref": "#/components/schemas/Quality",
            "default": "default",
            "description": "Output resolution: default = 720p, hd = 1080p, uhd = 4K"
          },
          "target_languages": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Also produce a burned video per translated language (max 10), e.g. [\"Spanish\", \"French\"]",
            "title": "Target Languages"
          },
          "url": {
            "description": "YouTube video URL",
            "title": "Url",
            "type": "string"
          },
          "verbatim": {
            "default": false,
            "description": "Keep filler words and repetitions instead of cleaning them up",
            "title": "Verbatim",
            "type": "boolean"
          }
        },
        "required": [
          "url"
        ],
        "title": "BurnSubtitlesRequest",
        "type": "object"
      },
      "ErrorResponse": {
        "description": "FastAPI's error body, named so the schema can point at it.",
        "properties": {
          "detail": {
            "title": "Detail",
            "type": "string"
          }
        },
        "required": [
          "detail"
        ],
        "title": "ErrorResponse",
        "type": "object"
      },
      "FontSize": {
        "enum": [
          "default",
          "large",
          "xl"
        ],
        "title": "FontSize",
        "type": "string"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "title": "Detail",
            "type": "array"
          }
        },
        "title": "HTTPValidationError",
        "type": "object"
      },
      "PlaylistPreview": {
        "properties": {
          "fits": {
            "description": "Whether the playlist fits the remaining minutes",
            "title": "Fits",
            "type": "boolean"
          },
          "id": {
            "description": "Playlist id, empty for a channel",
            "title": "Id",
            "type": "string"
          },
          "is_channel": {
            "title": "Is Channel",
            "type": "boolean"
          },
          "max_videos": {
            "description": "Cap on how many videos one batch queues",
            "title": "Max Videos",
            "type": "integer"
          },
          "needed_seconds": {
            "description": "Minutes the whole playlist would consume, in seconds",
            "title": "Needed Seconds",
            "type": "integer"
          },
          "remaining_seconds": {
            "description": "What is left on the plan, in seconds",
            "title": "Remaining Seconds",
            "type": "integer"
          },
          "skipped": {
            "description": "Videos that can't be transcribed (private, deleted or live)",
            "title": "Skipped",
            "type": "integer"
          },
          "tab": {
            "description": "Which channel tab was listed: videos, streams or shorts",
            "title": "Tab",
            "type": "string"
          },
          "title": {
            "title": "Title",
            "type": "string"
          },
          "total": {
            "description": "Videos the playlist holds, before the cap and before skipping",
            "title": "Total",
            "type": "integer"
          },
          "videos": {
            "items": {
              "$ref": "#/components/schemas/PlaylistVideo"
            },
            "title": "Videos",
            "type": "array"
          }
        },
        "required": [
          "id",
          "title",
          "total",
          "skipped",
          "max_videos",
          "is_channel",
          "tab",
          "videos",
          "needed_seconds",
          "remaining_seconds",
          "fits"
        ],
        "title": "PlaylistPreview",
        "type": "object"
      },
      "PlaylistVideo": {
        "description": "One video of a playlist listing. Mirrors `youtube_data_service.VideoInfo`.",
        "properties": {
          "duration": {
            "description": "Seconds",
            "title": "Duration",
            "type": "integer"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "is_age_restricted": {
            "default": false,
            "title": "Is Age Restricted",
            "type": "boolean"
          },
          "is_live": {
            "default": false,
            "description": "Live or upcoming broadcasts have no fixed duration to bill against",
            "title": "Is Live",
            "type": "boolean"
          },
          "language": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The uploader's declared audio language, when set",
            "title": "Language"
          },
          "thumbnail": {
            "title": "Thumbnail",
            "type": "string"
          },
          "title": {
            "title": "Title",
            "type": "string"
          }
        },
        "required": [
          "id",
          "title",
          "duration",
          "thumbnail"
        ],
        "title": "PlaylistVideo",
        "type": "object"
      },
      "Quality": {
        "enum": [
          "default",
          "hd",
          "uhd"
        ],
        "title": "Quality",
        "type": "string"
      },
      "QueuedBatch": {
        "properties": {
          "batch_id": {
            "description": "Poll GET /v1/api/batch/{batch_id} for every job in one call",
            "title": "Batch Id",
            "type": "string"
          },
          "count": {
            "description": "How many jobs were queued",
            "title": "Count",
            "type": "integer"
          },
          "ids": {
            "description": "Job ids, in queue order",
            "items": {
              "type": "string"
            },
            "title": "Ids",
            "type": "array"
          },
          "skipped": {
            "description": "Videos in the playlist that can't be transcribed (private, deleted or live)",
            "title": "Skipped",
            "type": "integer"
          },
          "title": {
            "description": "Playlist or channel title",
            "title": "Title",
            "type": "string"
          }
        },
        "required": [
          "batch_id",
          "title",
          "count",
          "skipped",
          "ids"
        ],
        "title": "QueuedBatch",
        "type": "object"
      },
      "QueuedJob": {
        "properties": {
          "id": {
            "description": "Job id; poll GET /v1/api/transcription/{id} until `state` is `done`",
            "title": "Id",
            "type": "string"
          }
        },
        "required": [
          "id"
        ],
        "title": "QueuedJob",
        "type": "object"
      },
      "QueuedSubtitlesJob": {
        "properties": {
          "format": {
            "description": "The requested format, echoed back",
            "enum": [
              "srt",
              "webvtt"
            ],
            "title": "Format",
            "type": "string"
          },
          "id": {
            "description": "Job id; poll GET /v1/api/transcription/{id} until `state` is `done`",
            "title": "Id",
            "type": "string"
          }
        },
        "required": [
          "id",
          "format"
        ],
        "title": "QueuedSubtitlesJob",
        "type": "object"
      },
      "State": {
        "enum": [
          "waiting",
          "preparing",
          "downloading",
          "converting",
          "uploading",
          "processing",
          "merging",
          "aligning",
          "translating",
          "burning",
          "done",
          "failed"
        ],
        "title": "State",
        "type": "string"
      },
      "SubtitlesRequest": {
        "properties": {
          "format": {
            "default": "srt",
            "description": "Which field to read from the result; both are always populated",
            "enum": [
              "srt",
              "webvtt"
            ],
            "title": "Format",
            "type": "string"
          },
          "language_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO-639-1/639-3 code of the video's spoken language, e.g. \"en\"; can improve quality. Omit to auto-detect.",
            "title": "Language Code"
          },
          "target_languages": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Also translate into these languages (max 10), e.g. [\"Spanish\", \"French\"]",
            "title": "Target Languages"
          },
          "url": {
            "description": "YouTube video URL",
            "title": "Url",
            "type": "string"
          },
          "verbatim": {
            "default": false,
            "description": "Keep filler words and repetitions instead of cleaning them up",
            "title": "Verbatim",
            "type": "boolean"
          }
        },
        "required": [
          "url"
        ],
        "title": "SubtitlesRequest",
        "type": "object"
      },
      "TranscribePlaylistRequest": {
        "properties": {
          "background": {
            "default": false,
            "description": "Draw a semi-transparent black box behind burned-in subtitles",
            "title": "Background",
            "type": "boolean"
          },
          "font_size": {
            "$ref": "#/components/schemas/FontSize",
            "default": "default",
            "description": "Subtitle text size for burned jobs"
          },
          "language_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO-639-1/639-3 code of the video's spoken language, e.g. \"en\"; can improve quality. Omit to auto-detect.",
            "title": "Language Code"
          },
          "quality": {
            "$ref": "#/components/schemas/Quality",
            "default": "default",
            "description": "Video quality for burned jobs (default/hd/uhd)"
          },
          "target_languages": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Extra subtitle languages (subtitles/burned only, max 10)",
            "title": "Target Languages"
          },
          "type": {
            "$ref": "#/components/schemas/TranscriptionType",
            "default": "transcript",
            "description": "What to produce for every video in the playlist"
          },
          "url": {
            "description": "YouTube playlist or channel URL",
            "title": "Url",
            "type": "string"
          },
          "verbatim": {
            "default": false,
            "description": "Keep filler words and repetitions instead of cleaning them up",
            "title": "Verbatim",
            "type": "boolean"
          }
        },
        "required": [
          "url"
        ],
        "title": "TranscribePlaylistRequest",
        "type": "object"
      },
      "TranscribeRequest": {
        "properties": {
          "language_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO-639-1/639-3 code of the video's spoken language, e.g. \"en\"; can improve quality. Omit to auto-detect.",
            "title": "Language Code"
          },
          "url": {
            "description": "YouTube video URL",
            "title": "Url",
            "type": "string"
          },
          "verbatim": {
            "default": false,
            "description": "Keep filler words and repetitions instead of cleaning them up",
            "title": "Verbatim",
            "type": "boolean"
          }
        },
        "required": [
          "url"
        ],
        "title": "TranscribeRequest",
        "type": "object"
      },
      "TranscriptionApiResponse": {
        "description": "Public-facing subset of Transcription returned by the token API and MCP server.",
        "properties": {
          "background": {
            "title": "Background",
            "type": "boolean"
          },
          "burned_video_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Burned Video Url"
          },
          "created_at": {
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "duration": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Duration"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "font_size": {
            "$ref": "#/components/schemas/FontSize"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "is_preview": {
            "default": false,
            "title": "Is Preview",
            "type": "boolean"
          },
          "preview_minutes": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Preview Minutes"
          },
          "progress": {
            "title": "Progress",
            "type": "integer"
          },
          "quality": {
            "$ref": "#/components/schemas/Quality"
          },
          "srt": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Srt"
          },
          "state": {
            "$ref": "#/components/schemas/State"
          },
          "translations": {
            "default": [],
            "items": {
              "$ref": "#/components/schemas/TranslationApiResponse"
            },
            "title": "Translations",
            "type": "array"
          },
          "txt": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Txt"
          },
          "type": {
            "$ref": "#/components/schemas/TranscriptionType"
          },
          "updated_at": {
            "format": "date-time",
            "title": "Updated At",
            "type": "string"
          },
          "verbatim": {
            "title": "Verbatim",
            "type": "boolean"
          },
          "video_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Video Url"
          },
          "webvtt": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webvtt"
          }
        },
        "required": [
          "id",
          "state",
          "progress",
          "type",
          "verbatim",
          "quality",
          "font_size",
          "background",
          "created_at",
          "updated_at"
        ],
        "title": "TranscriptionApiResponse",
        "type": "object"
      },
      "TranscriptionType": {
        "enum": [
          "transcript",
          "subtitles",
          "burned"
        ],
        "title": "TranscriptionType",
        "type": "string"
      },
      "TranslationApiResponse": {
        "description": "Public-facing subset of TranscriptionTranslation returned by the token API and MCP server.",
        "properties": {
          "burned_video_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Burned Video Url"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "language": {
            "title": "Language",
            "type": "string"
          },
          "srt": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Srt"
          },
          "state": {
            "$ref": "#/components/schemas/TranslationState"
          },
          "webvtt": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webvtt"
          }
        },
        "required": [
          "language",
          "state"
        ],
        "title": "TranslationApiResponse",
        "type": "object"
      },
      "TranslationState": {
        "enum": [
          "pending",
          "translating",
          "burning",
          "done",
          "failed"
        ],
        "title": "TranslationState",
        "type": "string"
      },
      "ValidationError": {
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "title": "Location",
            "type": "array"
          },
          "msg": {
            "title": "Message",
            "type": "string"
          },
          "type": {
            "title": "Error Type",
            "type": "string"
          }
        },
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError",
        "type": "object"
      }
    },
    "securitySchemes": {
      "HTTPBearer": {
        "description": "An API token from https://youtubetotext.ai (Settings → API tokens), sent as `Authorization: Bearer ytt_...`.",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "info": {
    "description": "Transcribe YouTube videos from your own code: plain text, subtitles (SRT and\nWebVTT), subtitles burned into the video, and playlists in one batch.\n\nEvery endpoint takes an API token from\n[your account settings](https://youtubetotext.ai) as `Authorization: Bearer ytt_...`.\n\nTranscription is asynchronous: the POST endpoints return a job `id` straight\naway, then you poll `GET /v1/api/transcription/{id}` until `state` is `done`\n(or `failed`) and read `txt`, `srt` / `webvtt`, or `burned_video_url` from the\nresult.",
    "title": "YouTube to Text API",
    "version": "1.0.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/v1/api/batch/{id}": {
      "get": {
        "description": "Status of every job in a playlist batch, in queue order (no transcript text; fetch each job by id for that).",
        "operationId": "get_batch",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchStatus"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "No such batch on this account"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded: 60 job requests and 300 polls per minute per account, shared with the MCP server",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this class of call",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "summary": "Get a playlist batch",
        "tags": [
          "API"
        ]
      }
    },
    "/v1/api/burn-subtitles": {
      "post": {
        "description": "Queue a video to be downloaded with subtitles burned in.",
        "operationId": "burn_subtitles",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BurnSubtitlesRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueuedJob"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid API token"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded: 60 job requests and 300 polls per minute per account, shared with the MCP server",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this class of call",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "summary": "Burn subtitles into a video",
        "tags": [
          "API"
        ]
      }
    },
    "/v1/api/playlist": {
      "get": {
        "description": "What a playlist link would queue: its public videos (max 25), the minutes needed and whether they fit your plan.",
        "operationId": "playlist_info",
        "parameters": [
          {
            "description": "YouTube playlist or channel URL",
            "in": "query",
            "name": "url",
            "required": true,
            "schema": {
              "description": "YouTube playlist or channel URL",
              "title": "Url",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "type",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/TranscriptionType",
              "default": "transcript"
            }
          },
          {
            "in": "query",
            "name": "quality",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/Quality",
              "default": "default"
            }
          },
          {
            "in": "query",
            "name": "target_languages",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "items": {
                    "type": "string"
                  },
                  "type": "array"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Target Languages"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlaylistPreview"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid API token"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded: 60 job requests and 300 polls per minute per account, shared with the MCP server",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this class of call",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "summary": "Preview a playlist",
        "tags": [
          "API"
        ]
      }
    },
    "/v1/api/subtitles": {
      "post": {
        "description": "Queue a YouTube video for subtitle generation (SRT and WebVTT).",
        "operationId": "subtitles",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubtitlesRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueuedSubtitlesJob"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid API token"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded: 60 job requests and 300 polls per minute per account, shared with the MCP server",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this class of call",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "summary": "Generate subtitles",
        "tags": [
          "API"
        ]
      }
    },
    "/v1/api/transcribe": {
      "post": {
        "description": "Queue a YouTube video for plain text transcription. Returns a job id.",
        "operationId": "transcribe",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TranscribeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueuedJob"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid API token"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded: 60 job requests and 300 polls per minute per account, shared with the MCP server",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this class of call",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "summary": "Transcribe a video",
        "tags": [
          "API"
        ]
      }
    },
    "/v1/api/transcribe-playlist": {
      "post": {
        "description": "Queue every public video of a YouTube playlist (max 25) as separate jobs. Returns a batch id and the job ids; poll each job, or GET /batch/{id} for all of them.",
        "operationId": "transcribe_playlist",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TranscribePlaylistRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QueuedBatch"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid API token"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded: 60 job requests and 300 polls per minute per account, shared with the MCP server",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this class of call",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "summary": "Transcribe a playlist",
        "tags": [
          "API"
        ]
      }
    },
    "/v1/api/transcription/{id}": {
      "get": {
        "description": "Poll a transcription's status and result by id.",
        "operationId": "get_transcription",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TranscriptionApiResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid API token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "No such transcription on this account"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Rate limit exceeded: 60 job requests and 300 polls per minute per account, shared with the MCP server",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the window resets",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Limit": {
                "description": "Requests allowed per minute for this class of call",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Requests left in the current window",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "security": [
          {
            "HTTPBearer": []
          }
        ],
        "summary": "Get a transcription",
        "tags": [
          "API"
        ]
      }
    }
  },
  "servers": [
    {
      "url": "https://api.youtubetotext.ai"
    }
  ]
}
