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
Search (Channel Search via SSE)
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:
| Parameter | Type | Description |
|---|---|---|
q | string | Search query (required) |
page | number | Page number (default: 1) |
pageSize | number | Results per page (default: 50, max: 100) |
status | string | Filter: deleted or live |
hasVideo | boolean | Only videos with archived video files |
hasSubtitles | boolean | Only videos with subtitles |
hasSummary | boolean | Only videos with AI summaries |
sort | string | relevance | date-desc | date-asc | duration-desc | duration-asc |
Subtitles
GET /api/subtitles/:videoId
Download subtitles for a video.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
format | string | srt (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:
| Parameter | Type | Description |
|---|---|---|
tag | string | Filter by tag |
channelId | string | Filter by channel |
language | string | Filter by language code |
page | number | Page number (default: 1) |
limit | number | Results 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:
| Event | Description |
|---|---|
search:channel_resolved | Channel info resolved (channelId, title, avatar, etc.) |
search:progress | Pipeline progress update (stage name, percentage) |
search:video | Individual video result |
search:video_batch | Batch of video results (more efficient) |
search:caption_info | Subtitle availability info for discovered videos |
search:complete | Search completed successfully |
search:error | Error 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"}}
| Code | Meaning |
|---|---|
UNAUTHORIZED | Missing or invalid API key |
FORBIDDEN | API access not enabled for your account |
RATE_LIMITED | Rate limit exceeded |
API_KEY_REQUIRED | Programmatic access requires an API key |
INVALID_INPUT | Invalid query or parameters |
NOT_FOUND | Resource 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());