REST API reference
Five endpoints. Plain HTTP, plain JSON. No SDK required.
Base URL
https://brains.subtitlesking.com
For self-hosted: whatever you run the upload server at.
Authentication
| Endpoint | Auth |
|---|---|
| /presign | X-API-KEY header |
| /upload | Single-use presigned token (query) |
| /queue | None |
| /transcript | Presigned token (query, 24 h) |
| /download | Presigned token (query, 24 h) |
| /downloadpresign | X-API-KEY header |
The presigned-token model means you only ever send your real API key on
/presign — every other URL is short-lived and tied to a single video.
Endpoints
POST /presign
Generate a one-time presigned upload URL.
Headers:
X-API-KEY(required)Content-Type: application/json
Body:
{ "filename": "clip.mp4", "username": "" }
Response:
{ "uploadURL": "https://brains.subtitlesking.com/upload?presignedToken=…" }
POST /upload
Receive the multipart file upload. Use the URL returned by /presign.
Body: multipart form data with a file field.
Response:
{
"status": "success",
"message": "Upload successful",
"videoID": "1730500000000000000",
"authToken": "12345678"
}
POST /queue
Look up status by auth token.
Body:
{ "authToken": "12345678" }
Response:
[
{
"authToken": "12345678",
"status": "subtitles_burned",
"downloadURL": "https://…/download?videoID=…&presignedToken=…",
"transcriptURL": "https://…/transcript?videoID=…&presignedToken=…"
}
]
If the auth token is unknown, the response is:
[{ "authToken": "", "status": "404", "downloadURL": "", "transcriptURL": "" }]
transcriptURL is populated as soon as status reaches srt_generated;
downloadURL is populated when status reaches subtitles_burned.
GET /transcript
Stream the SRT transcript.
Query params:
videoIDpresignedToken
Response: application/x-subrip (SRT file).
GET /download
Stream the subtitle-burned video.
Query params:
videoIDpresignedToken
Response: the video file.
Status state machine
new
→ compressing
→ compressed
→ generating_srt
→ srt_generated ← transcript_url available
→ burning_subtitles
→ subtitles_burned ← download_url available
→ deleted (after 24 h cleanup)
error_while_compressing
error_while_generating_srt
error_while_burning_subtitles
Polling cadence
A reasonable poll interval is 30–60 seconds. Most videos finish within 3–10 minutes. If you need lower-latency notifications, prefer the MCP server (which abstracts the polling) over raw HTTP.
Limits
- Free tier: 100 MB max video size.
- 24 h retention on processed files.
- Reasonable rate limiting on
/presign.
Errors
Standard HTTP status codes:
400— bad request (missing filename, invalid token).401— unauthorized (bad or expired token).404— not found (videoID not in DB).500— internal error.
Error responses are plain text in the body.
Next steps
- MCP server reference — same backend, agent-friendly interface.
- Self-host guide — run all five endpoints on your own box.