{
  "openapi": "3.0.3",
  "info": {
    "title": "VidWords \u2014 YouTube Transcript API",
    "description": "Fetch transcripts for any public YouTube video and list a channel's uploads. No proxies or infrastructure to manage \u2014 one API call returns clean, timestamped transcript text ready for analysis, AI models, or automation.",
    "version": "1.0.0",
    "contact": {
      "name": "VidWords",
      "url": "https://vidwords.example"
    }
  },
  "servers": [
    {
      "url": "https://vidwords.com",
      "description": "VidWords production"
    }
  ],
  "tags": [
    {
      "name": "Transcripts",
      "description": "Fetch video transcripts"
    },
    {
      "name": "Channels",
      "description": "List a channel's uploaded videos"
    }
  ],
  "paths": {
    "/api/transcripts": {
      "post": {
        "tags": [
          "Transcripts"
        ],
        "summary": "Fetch transcripts for up to 50 videos",
        "operationId": "fetchTranscripts",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TranscriptsRequest"
              },
              "example": {
                "ids": [
                  "dQw4w9WgXcQ",
                  "https://youtu.be/jNQXAC9IVRw"
                ],
                "lang": "en"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Transcript results (per-video; a failed video has an `error` field instead of segments)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TranscriptsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Malformed body, empty ids, or more than 50 ids"
          },
          "401": {
            "description": "Missing or invalid credentials"
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After header)"
          }
        }
      }
    },
    "/api/channels": {
      "post": {
        "tags": [
          "Channels"
        ],
        "summary": "List a channel's uploaded videos (newest first, up to 500)",
        "operationId": "fetchChannels",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChannelsRequest"
              },
              "example": {
                "ids": [
                  "@mkbhd"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Channel video lists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Malformed body or too many channels"
          },
          "401": {
            "description": "Missing or invalid credentials"
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After header)"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "For direct use: `Basic <your-api-token>`. On RapidAPI this is handled automatically by the proxy."
      }
    },
    "schemas": {
      "TranscriptsRequest": {
        "type": "object",
        "required": [
          "ids"
        ],
        "properties": {
          "ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 50,
            "description": "Video IDs or full YouTube URLs (max 50)"
          },
          "lang": {
            "type": "string",
            "description": "Preferred caption language code",
            "default": "en"
          }
        }
      },
      "TranscriptsResponse": {
        "type": "object",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TranscriptResult"
            }
          }
        }
      },
      "TranscriptResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string",
            "nullable": true
          },
          "author": {
            "type": "string",
            "nullable": true
          },
          "language": {
            "type": "string"
          },
          "languageCode": {
            "type": "string"
          },
          "isGenerated": {
            "type": "boolean"
          },
          "text": {
            "type": "string",
            "description": "Full transcript as one string"
          },
          "segments": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "text": {
                  "type": "string"
                },
                "start": {
                  "type": "number"
                },
                "duration": {
                  "type": "number"
                }
              }
            }
          },
          "error": {
            "type": "string",
            "description": "Present instead of segments when a video could not be fetched"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "ChannelsRequest": {
        "type": "object",
        "required": [
          "ids"
        ],
        "properties": {
          "ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 50,
            "description": "Channel @handles, URLs, or UC\u2026 IDs"
          }
        }
      },
      "ChannelsResponse": {
        "type": "object",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChannelResult"
            }
          }
        }
      },
      "ChannelResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "channelId": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "videoCount": {
            "type": "integer"
          },
          "truncated": {
            "type": "boolean"
          },
          "videos": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "title": {
                  "type": "string"
                },
                "author": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}