{
  "openapi": "3.0.3",
  "info": {
    "title": "Get The Vid Universal Video API",
    "version": "2.1.0",
    "description": "Paste a video page URL (X, TikTok, Instagram, Facebook, YouTube, 1000+ sites) and get downloadable MP4 variants, merged video+audio, or MP3. AI agents: prefer the MCP endpoint POST /api/mcp (tools/list). Only download media the caller owns or has permission to save. Rate limits apply (429 + Retry-After)."
  },
  "servers": [{ "url": "https://getthevid.com", "description": "Production" }],
  "paths": {
    "/api/fetch": {
      "get": {
        "summary": "Resolve a video page into downloadable variants",
        "parameters": [
          { "name": "url", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Full video page URL" },
          { "name": "slide", "in": "query", "required": false, "schema": { "type": "integer", "default": 1 }, "description": "Carousel video number (1-based)" },
          { "name": "cobaltKey", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Optional Cobalt API key fallback" },
          { "name": "cobaltInstance", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Cobalt API instance base URL" }
        ],
        "responses": {
          "200": { "description": "Normalized media object: platform, author, variants[] (best-first), images, best, music?, audio?, slide, slideGroups" },
          "404": { "description": "Unresolvable (private/deleted/unsupported). Body includes debug trail." },
          "429": { "description": "Rate limited. Retry after Retry-After seconds." }
        }
      }
    },
    "/api/download": {
      "get": {
        "summary": "Stream a resolved media URL as an attachment (CORS-safe)",
        "parameters": [
          { "name": "url", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Direct media URL from /api/fetch (cached 15 min) or known CDN host" },
          { "name": "filename", "in": "query", "required": false, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "File bytes with Content-Disposition: attachment" } }
      }
    },
    "/api/merge": {
      "get": {
        "summary": "Download a slide muxed with its audio (or best-with-sound direct). May take 15–120s.",
        "parameters": [
          { "name": "url", "in": "query", "required": true, "schema": { "type": "string" } },
          { "name": "slide", "in": "query", "required": false, "schema": { "type": "integer", "default": 1 } },
          { "name": "filename", "in": "query", "required": false, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "MP4 with sound" }, "501": { "description": "ffmpeg missing" } }
      }
    },
    "/api/audio": {
      "get": {
        "summary": "Download a slide's soundtrack as MP3",
        "parameters": [
          { "name": "url", "in": "query", "required": true, "schema": { "type": "string" } },
          { "name": "slide", "in": "query", "required": false, "schema": { "type": "integer", "default": 1 } },
          { "name": "filename", "in": "query", "required": false, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "MP3 bytes" }, "501": { "description": "ffmpeg missing" } }
      }
    },
    "/api/mcp": {
      "post": {
        "summary": "Model Context Protocol endpoint (stateless Streamable HTTP) for AI agents",
        "description": "Send JSON-RPC 2.0: initialize → tools/list → tools/call. Tools: fetch_video_info, download_video, merge_video, extract_audio.",
        "responses": { "200": { "description": "JSON-RPC response (or 202 empty for notifications)" } }
      }
    },
    "/api/health": {
      "get": {
        "summary": "Service + dependency status",
        "responses": { "200": { "description": "{ ok, ytDlp: {installed, version}, ffmpeg: {...} }" } }
      }
    }
  }
}
