API Documentation

Archivarix Tube Search provides a REST API for programmatic access to archived YouTube video metadata, subtitles, and AI summaries. This page is the complete API reference.

API access requires the MCP + API subscription tier. See Pricing for details.

Authentication

API keys are created in your Profile → API tab. Include the key in every request using one of these headers:

X-API-Key: tsk_YOUR_KEY_HERE

or

Authorization: Bearer tsk_YOUR_KEY_HERE

Keys use the tsk_ prefix. Keep your key secret — it grants full API access to your account.

Endpoints

Channel search is a two-step process: create a search session, then consume results via Server-Sent Events.

POST /api/search

Start a new channel search.

Request body (JSON):

{
  "query": "@handle or channel URL or video URL/ID"
}

Response:

{
  "data": {
    "searchSessionId": "uuid",
    "sseEndpointUrl": "/api/search/uuid/stream",
    "channelId": "UCxxxxxx",
    "channelTitle": "Channel Name"
  }
}

GET /api/search/:sessionId/stream

Connect to the SSE stream to receive search results in real time. Set the Accept: text/event-stream header. See the SSE Protocol section below for event types.

POST /api/search/:sessionId/continue

Continue a paginated search to load the next page of archive results. Returns a new SSE stream URL.

GET /api/search/background-status/:channelId

Check if a channel search is currently running in the background.

Response:

{
  "data": {
    "running": true,
    "searchSessionId": "uuid"
  }
}

Full-Text Search

GET /api/fts

Search across all indexed video titles and descriptions.

Query parameters:

ParameterTypeDescription
qstringSearch query (required)
pagenumberPage number (default: 1)
pageSizenumberResults per page (default: 50, max: 100)
statusstringFilter: deleted or live
hasVideobooleanOnly videos with archived video files
hasSubtitlesbooleanOnly videos with subtitles
hasSummarybooleanOnly videos with AI summaries
sortstringrelevance | date-desc | date-asc | duration-desc | duration-asc

Subtitles

GET /api/subtitles/:videoId

Download subtitles for a video.

Query parameters:

ParameterTypeDescription
formatstringsrt (default) or vtt

POST /api/subtitles/:videoId/fetch

Fetch subtitles on-demand via yt-dlp or Wayback Machine. Triggers a background job if subtitles are not yet available.

POST /api/subtitles/bulk-download

Download subtitles for multiple videos at once.

Request body (JSON):

{
  "videoIds": ["dQw4w9WgXcQ", "jNQXAC9IVRw"],
  "query": "optional highlight query"
}

AI Summaries

POST /api/summary/generate

Generate an AI summary for a video. Requires available subtitles.

Request body (JSON):

{
  "videoId": "dQw4w9WgXcQ",
  "private": false
}

Response (202 Accepted):

{
  "data": {
    "status": "generating",
    "videoId": "dQw4w9WgXcQ"
  }
}

GET /api/summary/:videoId

Get the AI summary for a specific video.

DELETE /api/summary/:videoId

Delete a summary. Admin only.

GET /api/summary/browse

Browse summaries with filters.

Query parameters:

ParameterTypeDescription
tagstringFilter by tag
channelIdstringFilter by channel
languagestringFilter by language code
pagenumberPage number (default: 1)
limitnumberResults per page (default: 20)

GET /api/summary/latest

Get the most recently generated summaries.

GET /api/summary/tags

Get popular tags across all summaries.

GET /api/summary/languages

Get available summary languages with counts.

GET /api/summary/channels

Get channels that have summaries.

Video Status

GET /api/videos/:videoId/status-history

Get the status change history for a video (e.g., live → deleted → re-uploaded).

System

GET /api/health

Health check endpoint. Returns server status.

GET /api/features

Get feature flags and limits for the current user/tier.

GET /api/tiers

Get tier comparison data (limits, features per tier).

SSE Protocol

The channel search stream sends Server-Sent Events. Each event has a type and JSON data payload:

EventDescription
search:channel_resolvedChannel info resolved (channelId, title, avatar, etc.)
search:progressPipeline progress update (stage name, percentage)
search:videoIndividual video result
search:video_batchBatch of video results (more efficient)
search:caption_infoSubtitle availability info for discovered videos
search:completeSearch completed successfully
search:errorError occurred during search

Rate Limits

API requests (MCP + API tier) have the following rate limits:

When a limit is exceeded, the API returns HTTP 429 with the RATE_LIMITED error code.

Error Codes

All errors return JSON with an error object:

{"error": {"code": "RATE_LIMITED", "message": "Rate limit exceeded"}}
CodeMeaning
UNAUTHORIZEDMissing or invalid API key
FORBIDDENAPI access not enabled for your account
RATE_LIMITEDRate limit exceeded
API_KEY_REQUIREDProgrammatic access requires an API key
INVALID_INPUTInvalid query or parameters
NOT_FOUNDResource not found

Examples

curl

# Start a channel search
curl -X POST https://tube.archivarix.net/api/search \
  -H "X-API-Key: tsk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "@MrBeast"}'

# Stream results (SSE)
curl -N https://tube.archivarix.net/api/search/SESSION_ID/stream \
  -H "X-API-Key: tsk_YOUR_KEY" \
  -H "Accept: text/event-stream"

# Continue paginated search
curl -X POST https://tube.archivarix.net/api/search/SESSION_ID/continue \
  -H "X-API-Key: tsk_YOUR_KEY"

# Full-text search
curl "https://tube.archivarix.net/api/fts?q=deleted+video&pageSize=20&sort=relevance" \
  -H "X-API-Key: tsk_YOUR_KEY"

# Download subtitles (SRT)
curl https://tube.archivarix.net/api/subtitles/dQw4w9WgXcQ \
  -H "X-API-Key: tsk_YOUR_KEY"

# Download subtitles (VTT)
curl "https://tube.archivarix.net/api/subtitles/dQw4w9WgXcQ?format=vtt" \
  -H "X-API-Key: tsk_YOUR_KEY"

# Fetch subtitles on-demand
curl -X POST https://tube.archivarix.net/api/subtitles/dQw4w9WgXcQ/fetch \
  -H "X-API-Key: tsk_YOUR_KEY"

# Generate AI summary
curl -X POST https://tube.archivarix.net/api/summary/generate \
  -H "X-API-Key: tsk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"videoId": "dQw4w9WgXcQ"}'

# Get a summary
curl https://tube.archivarix.net/api/summary/dQw4w9WgXcQ \
  -H "X-API-Key: tsk_YOUR_KEY"

# Browse summaries by tag
curl "https://tube.archivarix.net/api/summary/browse?tag=music&limit=10" \
  -H "X-API-Key: tsk_YOUR_KEY"

# Health check
curl https://tube.archivarix.net/api/health

Python

import requests

API_KEY = "tsk_YOUR_KEY"
BASE = "https://tube.archivarix.net"
headers = {"X-API-Key": API_KEY}

# --- Channel search ---
resp = requests.post(f"{BASE}/api/search",
    headers=headers,
    json={"query": "@MrBeast"})
session = resp.json()["data"]
search_id = session["searchSessionId"]

# Stream results (SSE)
with requests.get(f"{BASE}/api/search/{search_id}/stream",
    headers={**headers, "Accept": "text/event-stream"},
    stream=True) as r:
    for line in r.iter_lines(decode_unicode=True):
        if line.startswith("data:"):
            print(line[5:])

# --- Full-text search ---
resp = requests.get(f"{BASE}/api/fts",
    headers=headers,
    params={"q": "deleted video", "pageSize": 20, "sort": "relevance"})
print(resp.json())

# --- Download subtitles ---
resp = requests.get(f"{BASE}/api/subtitles/dQw4w9WgXcQ",
    headers=headers,
    params={"format": "srt"})
with open("subtitles.srt", "w") as f:
    f.write(resp.text)

# --- Generate AI summary ---
resp = requests.post(f"{BASE}/api/summary/generate",
    headers=headers,
    json={"videoId": "dQw4w9WgXcQ"})
print(resp.json())  # {"data": {"status": "generating", ...}}

# --- Get summary ---
resp = requests.get(f"{BASE}/api/summary/dQw4w9WgXcQ",
    headers=headers)
summary = resp.json()["data"]
print(summary["title"], summary["tags"])

JavaScript (Node.js / Browser)

const API_KEY = "tsk_YOUR_KEY";
const BASE = "https://tube.archivarix.net";
const headers = { "X-API-Key": API_KEY };

// --- Channel search ---
const searchResp = await fetch(`${BASE}/api/search`, {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({ query: "@MrBeast" }),
});
const { data: { searchSessionId } } = await searchResp.json();

// Stream results (SSE)
const es = new EventSource(
  `${BASE}/api/search/${searchSessionId}/stream`
);
es.addEventListener("search:video", (e) => {
  const video = JSON.parse(e.data);
  console.log(video.title, video.videoId);
});
es.addEventListener("search:complete", () => es.close());

// --- Full-text search ---
const ftsResp = await fetch(
  `${BASE}/api/fts?q=deleted+video&pageSize=20`,
  { headers }
);
const results = await ftsResp.json();

// --- Download subtitles ---
const subResp = await fetch(
  `${BASE}/api/subtitles/dQw4w9WgXcQ?format=srt`,
  { headers }
);
const srtText = await subResp.text();

// --- Generate AI summary ---
const sumResp = await fetch(`${BASE}/api/summary/generate`, {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({ videoId: "dQw4w9WgXcQ" }),
});
console.log(await sumResp.json());

// --- Browse summaries ---
const browseResp = await fetch(
  `${BASE}/api/summary/browse?tag=music&limit=10`,
  { headers }
);
console.log(await browseResp.json());