API Documentation

Two ways to get YouTube transcripts: pull on your schedule, or receive them instantly via webhook the moment a new video drops.

Authentication

The Pull API uses API key authentication. Find your key in the dashboard settings. Pass it using any of these methods:

Recommended
Authorization: Bearer tr_live_xxxxxxxxxxxx
X-Api-Key: tr_live_xxxxxxxxxxxx
GET /api/videos?api_key=tr_live_xxxxxxxxxxxx

Webhooks don't require authentication — you configure the endpoint URL when creating a subscription. VidProxy will POST to that URL whenever a new video is detected.

Pull API

Fetch all transcripts detected for your subscriptions within a time window. Good for batch processing, scheduled jobs, or polling-based integrations.

GET /api/videos

Query Parameters

Parameter Type Default Description
since string 24h Time window. Accepts Nh (hours) or Nd (days). Examples: 6h, 7d.
tag string Filter by subscription label. If omitted, returns videos from all subscriptions.

Example Request

curl https://vidproxy.pro/api/videos?since=24h&tag=my-channel \
  -H "Authorization: Bearer tr_live_xxxxxxxxxxxx"

Response

{
  "videos": [
    {
      "id": 1234,
      "subscription_id": 42,
      "channel_id": "UCxxxxxxxxxxxxxxxxxxxxxx",
      "channel_name": "HomeBrewers",
      "tag": "my-channel",
      "video_id": "dQw4w9WgXcQ",
      "video_title": "How to Brew a West Coast IPA",
      "published_at": "2026-04-30T10:00:00.000Z",
      "transcript_available": true,
      "transcript_text": "Welcome to today's brew session...",
      "transcript_source": "proxy",
      "detected_at": "2026-04-30T10:05:12.000Z",
      "ai_summary": null,
      "ai_key_takeaways": null,
      "ai_topics": null
    }
  ],
  "query": {
    "tag": "my-channel",
    "since": "24h",
    "cutoff": "2026-04-29T10:05:12.000Z"
  }
}

Response Fields

Field Type Description
video_id string YouTube video ID. Construct the full URL as https://www.youtube.com/watch?v={video_id}. Use this for deduplication.
channel_id string YouTube channel ID (e.g. UCxxxxxx).
channel_name string Channel display name, as shown on YouTube.
tag string | null The label you set on the subscription. Useful for routing videos to different pipelines.
video_title string Video title at time of detection.
published_at ISO 8601 When the video was published on YouTube.
transcript_available boolean false only when YouTube explicitly reports transcripts are disabled for this video.
transcript_text string | null Full transcript as plain text. null if unavailable.
transcript_source string proxy, direct, or scraperapi — which fetch method succeeded.
detected_at ISO 8601 When VidProxy first detected this video.
ai_summary string | null AI-generated 2–3 sentence summary of the video. Pro and Agency plans only.
ai_key_takeaways string[] | null Array of key takeaways extracted from the transcript. Pro and Agency plans only.
ai_topics string[] | null Array of topic tags for the video. Pro and Agency plans only.
subscription_id integer Internal subscription ID. Stable identifier for the channel subscription that triggered this.

On-Demand Transcript

Fetch the transcript for any YouTube video by URL or video ID — no channel subscription required. Each successful fetch counts against your monthly lookup quota. Failed fetches (transcript unavailable) are free.

GET /api/transcript

Query Parameters

ParameterTypeDescription
url string Full YouTube URL (e.g. https://youtube.com/watch?v=abc123 or https://youtu.be/abc123). Use either url or video_id, not both.
video_id string YouTube video ID (11-character string, e.g. dQw4w9WgXcQ).

Example Request

curl "https://vidproxy.pro/api/transcript?video_id=dQw4w9WgXcQ" \
  -H "Authorization: Bearer tr_live_xxxxxxxxxxxx"

Response

{
  "video_id": "dQw4w9WgXcQ",
  "available": true,
  "text": "Full transcript as plain text...",
  "segments": [
    { "start": 0, "duration": 4, "text": "Never gonna give you up" },
    ...
  ],
  "credits_remaining": 2499
}

Response Headers

HeaderDescription
X-Credits-Remaining Lookups remaining this month. unlimited for Agency.

Error Responses

StatusErrorMeaning
400 url or video_id is required Neither parameter was provided, or the URL couldn't be parsed.
402 credits_exhausted Monthly lookup quota reached. Resets on the 1st of each month.

Monthly quotas

PlanLookups / month
Free10
Starter500
Pro2,500
Agency10,000

MCP — Claude & Cursor Integration

VidProxy ships a Model Context Protocol server at https://vidproxy.pro/mcp. Add it to Claude Desktop, Cursor, VS Code, or any MCP-compatible client and your AI assistant can read your channel data, pull transcripts, check what's left on your plan, and manage which channels you monitor — no copy-pasting, no API calls to write.

Setup

Add the following to your MCP client config. For Claude Desktop that's ~/.config/claude/claude_desktop_config.json; for Cursor it's in Settings → MCP.

{
  "mcpServers": {
    "vidproxy": {
      "url": "https://vidproxy.pro/mcp",
      "headers": {
        "Authorization": "Bearer tr_live_xxxxxxxxxxxx"
      }
    }
  }
}

Your API key is in Dashboard → Settings. The MCP server uses the same key as the REST API.

Available Tools

ToolDescriptionCredits
get_transcript Fetch the full transcript for any YouTube video by ID or URL 1 per successful fetch
get_recent_videos Get videos from your monitored channels within a time window (e.g. since: "24h"), including full transcripts Free
search_videos Search your subscription history by keyword — matches video titles and transcript text Free
list_channels List your monitored channels with latest video info. Each row includes a subscription_id that the tools below accept Free
get_account_status Your plan and everything metered against it — channels used vs. allowed, webhooks, remaining transcript credits and their reset date, rate limit, poll interval. Unlimited values come back as null Free
add_channel Start monitoring a channel by @handle, URL or UC… ID. Already monitoring it? You get the existing subscription back rather than a duplicate. Counts against your plan's channel limit Free
set_channel_active Pause or resume a channel. Paused channels are skipped by the poller but keep every stored video and transcript. A paused channel still occupies a slot against your channel limit Free
remove_channel Permanently delete a channel and all stored videos, transcripts and delivery records for it. Requires an explicit confirm: true, and is disabled unless you enable destructive tools for the key — see below Free

Three of these tools write to your account — they add, pause and delete subscriptions using the same plan limits as the dashboard. Your API key is what authorises them, so treat it like a password: anyone holding it can change what you monitor. Rotate it any time in Dashboard → Settings. Webhook URLs are deliberately not settable over MCP — configure those in the dashboard.

remove_channel is disabled by default. Until you enable destructive tools for a key in Dashboard → Settings, the tool is not advertised to your assistant at all and is refused if called — every other tool works normally. Rotating a key switches it back off.

Why it works this way: the confirm: true flag is a speed bump for a well-behaved assistant, not a security boundary, because the model decides whether to set it. Transcripts are written by the channel owner, not by you, so a video whose captions contain instructions aimed at your assistant is a real possibility once that assistant can also delete things. The dashboard toggle is the part of the gate that no text your assistant reads can flip. Deletion is irreversible and we keep no per-account backup of transcripts.

Example prompts

  • "Summarize everything my channels posted in the last 24 hours."
  • "Search my channels for any video mentioning 'interest rates' this week."
  • "Fetch the transcript for youtube.com/watch?v=abc123 and pull out the key points."
  • "Which of my channels posted the most content last month?"
  • "How many transcript credits do I have left this month?"
  • "Start monitoring @Bloomberg and tag it finance."
  • "Pause the channels I haven't gotten a video from in 60 days."

Webhooks

Configure a webhook URL on any subscription and VidProxy will POST a JSON payload to it within minutes of a new video being published. No polling required.

Request Headers

HeaderValue
Content-Type application/json
User-Agent VidProxy/1.0
X-VidProxy-Event new_video

Payload

{
  "event": "new_video",
  "timestamp": "2026-04-30T10:05:12.000Z",
  "subscription": {
    "id": 42,
    "label": "my-channel",
    "channel_id": "UCxxxxxxxxxxxxxxxxxxxxxx",
    "channel_name": "HomeBrewers"
  },
  "video": {
    "id": "dQw4w9WgXcQ",
    "title": "How to Brew a West Coast IPA",
    "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "published": "2026-04-30T10:00:00.000Z"
  },
  "transcript": {
    "available": true,
    "text": "Welcome to today's brew session...",
    "segments": [
      { "text": "Welcome to today's brew session", "start": 0.5, "duration": 3.2 }
    ]
  },
  "enrichment": {
    "summary": "A step-by-step guide to brewing a West Coast IPA...",
    "key_takeaways": ["Use high-alpha hops for bittering", "Dry hop at 68°F for best aroma", "Cold crash before packaging"],
    "topics": ["IPA", "hops", "dry hopping", "homebrewing"]
  }
}

The enrichment field is only present on Pro and Agency plans with AI enrichment enabled. transcript.segments contains per-segment timing data when available.

Retries

If your endpoint returns a non-2xx status or times out (10s), VidProxy retries up to 3 times:

1 Retry after 2 seconds
2 Retry after 10 seconds
3 Retry after 30 seconds

After 3 failed retries the delivery is marked failed and logged in your dashboard. Make your endpoint idempotent — use video.id for deduplication.

Responding to Webhooks

Return any 2xx status code within 10 seconds. If your processing takes longer, acknowledge immediately and handle async.

Keyword Alerts Pro

Keyword Alerts let you save keywords and receive an email whenever any new video across all your subscriptions mentions them — matched against the video title and transcript. This is separate from per-subscription keyword filters, which control webhook delivery.

Managing alerts

Alerts are managed from the Keyword Alerts tab in your dashboard. Add a keyword, and VidProxy will email you each time a new video matches it. Up to 50 keywords per account.

Match behavior

  • Case-insensitive substring match — gpt matches "GPT-4", "ChatGPT", etc.
  • Matches run against both the video title and the full transcript text.
  • If a transcript is not yet available, the title is checked immediately; the transcript is checked once it becomes available.
  • If multiple keywords match the same video, you receive one email listing all matched keywords.

Per-subscription keyword filter

Subscriptions also support a per-subscription Keyword Filter (set in the subscription edit modal). This controls webhook delivery only — the webhook fires only when the video title or transcript matches one of the specified keywords. It does not send emails and is independent of Keyword Alerts.

API

MethodEndpointDescription
GET/api/keyword-alertsList all keyword alerts
POST/api/keyword-alertsCreate a keyword alert — body: { "keyword": "string" }
DELETE/api/keyword-alerts/:idDelete a keyword alert

Rate Limits

The Pull API is rate-limited per API key using a sliding 60-second window. Response headers tell you your current usage:

HeaderDescription
X-RateLimit-Limit Max requests per minute for your plan.
X-RateLimit-Remaining Requests remaining in the current window.
Retry-After Seconds until the window resets (only on 429 responses).

When you exceed the limit you receive a 429 Too Many Requests with a Retry-After header. Back off and retry after that delay.

Plans

Plan Channels Webhooks API req / min Transcript lookups / mo
Free 1 1 60 10
Starter 15 3 60 500
Pro 100 Unlimited 300 2,500
Agency 1,000 Unlimited 300 10,000

View pricing →

FAQ

How do I authenticate a request?
Send your API key in whichever form suits the client: an Authorization: Bearer header, an X-Api-Key header, or an api_key query parameter. The key lives in Dashboard → Settings. Keys are stored hashed, so the plaintext is shown only at the moment you create or rotate one — if you lose it, rotate rather than go looking for it. Rotating retires the old key immediately.
Pull API or webhooks — which should I use?
Webhooks push: VidProxy POSTs to your URL within minutes of a new video, so nothing on your side runs on a timer. The pull API covers the cases a push doesn't fit — batch jobs, backfilling after an outage, or any environment with no public URL to POST to. GET /api/videos?since=24h returns everything detected in that window with transcripts attached. Running both is reasonable: webhooks for the live path, a scheduled pull to catch anything a failed delivery dropped.
When does a transcript lookup spend a credit?
Only when it returns a transcript. A lookup for a video with captions disabled, or one that simply fails, costs nothing. Every response carries an X-Credits-Remaining header, and the quota resets on the 1st of each month: 10 on Free, 500 on Starter, 2,500 on Pro, 10,000 on Agency. Past the quota the endpoint answers 402 credits_exhausted. The get_transcript MCP tool draws on the same pool; webhook deliveries and the pull API never touch it.
Why is transcript_available false on a video I know has captions?
Usually because the captions weren't there yet. YouTube generates auto-captions after a video goes live — normally within minutes, sometimes hours. VidProxy holds delivery until the transcript is confirmed and retries every poll cycle; after 24 hours it stops waiting and delivers the video without one. If you'd rather have the metadata immediately, turn off Wait for transcript before delivering on the subscription. A durable false means YouTube reports captions as disabled for that video, which no amount of retrying changes.
Why did a video arrive hours after it was published?
Almost always because YouTube wouldn't tell us about it yet. New videos are detected through YouTube's public RSS feed, and that endpoint is intermittently unavailable for a few hours most nights — it answers 404 or 500 for channels that are plainly fine, then clears on its own. We currently see it between roughly 01:00 and 07:00 UTC, though the hours drift and other people using the same feed report a different window, so treat that range as an observation rather than a schedule. It's a long-standing YouTube issue, publicly reported since December 2025 and still open; it isn't specific to VidProxy and there's no setting on either side that avoids it.

Nothing is dropped. The feed carries a channel's last 15 uploads and we re-read it every cycle, so the first successful read picks up everything published while it was refusing us. It only costs you a video if a channel publishes more than 15 during the window. Transcripts are unaffected — that's a separate path, and a video detected late still arrives with its transcript attached.
What happens when I hit the rate limit?
You get a 429, with Retry-After giving the seconds until the window clears. The window is a sliding 60 seconds per API key: 60 requests a minute on Free and Starter, 300 on Pro and Agency. X-RateLimit-Remaining on every response lets you back off before you get there. Calls to /mcp draw from that same per-key budget rather than a separate one, so splitting traffic across the two transports doesn't buy you extra headroom.
Does the MCP server need a paid plan?
No. All 8 tools work on every plan, authenticated with the same API key as the REST API. Your plan limits still apply through them — get_transcript spends a credit, add_channel counts against your channel limit. The exception is remove_channel, which stays hidden from the tool list and is refused until you enable destructive tools for that key in Dashboard → Settings. Rotating the key switches that back off.