Reeltopus API and MCP server
The Reeltopus REST API and MCP server: turn long videos into ranked, captioned 9:16 clips, export MP4s, caption files and editor timelines, and post them, from code, automations or AI agents.
Quickstart
Create an API key under Settings → API, then go from a long video to export links in five calls. Base URL: https://reeltopus.com/api/v1.
# 1. Start a project from a YouTube link (hours are held for its length)
curl -X POST https://reeltopus.com/api/v1/projects \
-H "Authorization: Bearer $REELTOPUS_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"url": "https://www.youtube.com/watch?v=VIDEO_ID", "rightsConfirmed": true}'
# 2. Poll until "status": "ready" (or subscribe to the project.ready webhook)
curl https://reeltopus.com/api/v1/projects/PROJECT_ID -H "Authorization: Bearer $REELTOPUS_API_KEY"
# 3. Ranked clips, best first
curl https://reeltopus.com/api/v1/projects/PROJECT_ID/clips -H "Authorization: Bearer $REELTOPUS_API_KEY"
# 4. Optional edits: style, trim, silence removal
curl -X PATCH https://reeltopus.com/api/v1/clips/CLIP_ID \
-H "Authorization: Bearer $REELTOPUS_API_KEY" -H "Content-Type: application/json" \
-d '{"captionStyle": "karaoke", "removeSilences": true}'
# 5. Export, then fetch the links once "status": "ready"
curl -X POST https://reeltopus.com/api/v1/clips/CLIP_ID/export \
-H "Authorization: Bearer $REELTOPUS_API_KEY" -H "Content-Type: application/json" \
-d '{"resolution": "1080p"}'
curl https://reeltopus.com/api/v1/clips/CLIP_ID/export -H "Authorization: Bearer $REELTOPUS_API_KEY"Processing spends your workspace's hours exactly like an upload in the app: the video's length is held when processing starts, charged on the transcribed length when it succeeds, and refunded in full if it fails. Archive mode costs half. Exports, caption files, editor timelines and posts are free.
Keys, limits, idempotency and errors
- Send the key as
Authorization: Bearer rt_live_…. Keys belong to a workspace and act for the owner or admin who created them; they stop working when revoked or when that person leaves the workspace. Only a hash is stored, so a lost key can't be shown again: create a new one. - Rate limits per key, per minute: free 60, creator 120, pro 300, agency 600. Creating projects is also limited to 10 a minute per workspace. Every response carries
RateLimit-Limit,RateLimit-RemainingandRateLimit-Reset; a 429 addsRetry-After. - Send
Idempotency-Key(any unique string, such as a UUID) on writes. A retry with the same key gets the first response back, markedIdempotent-Replayed: true, instead of creating a second project or post. Keys last 24 hours; reusing one with a different request is a 422. - Errors are
{ "error": { "code": "not_enough_hours", "message": "…" } }with a stablecode. Every response has anX-Request-Idto quote to support. - Download links (MP4, captions, editor timeline) work without a key and expire after an hour; fetch the export again for fresh ones.
Uploading files
For files on your side, upload straight to storage in parts. durationMs is optional: Reeltopus measures the file when the upload completes and holds hours for its real length. Files up to 20 GB.
const api = (path, init = {}) =>
fetch(`https://reeltopus.com/api/v1${path}`, {
...init,
headers: { Authorization: `Bearer ${process.env.REELTOPUS_API_KEY}`, "Content-Type": "application/json", ...init.headers },
}).then((r) => r.json());
const file = await fs.promises.readFile("episode.mp4");
const { project, upload } = await api("/uploads", {
method: "POST",
body: JSON.stringify({ filename: "episode.mp4", sizeBytes: file.length, mimeType: "video/mp4" }),
});
const parts = [];
for (const { partNumber, url } of upload.parts) { // > 100 parts: POST /uploads/{id}/parts for the rest
const chunk = file.subarray((partNumber - 1) * upload.partSize, partNumber * upload.partSize);
const res = await fetch(url, { method: "PUT", body: chunk });
parts.push({ partNumber, etag: res.headers.get("etag") });
}
await api(`/uploads/${project.id}/complete`, { method: "POST", body: JSON.stringify({ parts }) });Video links: POST /projects takes YouTube links today, for videos you own or have the rights to (rightsConfirmed: true records that). For anything else, upload the file.
Webhooks
Add an endpoint under Settings → API or with POST /webhooks. Reeltopus POSTs a JSON event and expects any 2xx within 10 seconds; anything else is retried with backoff for about a day. Events:
project.ready: A video finished processing; its clips are ready.project.failed: A video could not be processed. Its hours were refunded.clip.exported: A clip's MP4 export finished; download links are in the payload.clip.export_failed: A clip's MP4 export failed.post.published: A post went live on the platform.post.failed: A post could not be published.
Payloads look like { "id": "evt_…", "type": "project.ready", "createdAt": "…", "data": { "project": {…} } }, where data holds the same objects the API returns. The event id stays the same on retries, so use it to de-duplicate. Signatures follow Standard Webhooks:
import { Webhook } from "standardwebhooks"; // npm i standardwebhooks (Python, Go, Ruby… exist too)
const wh = new Webhook(process.env.REELTOPUS_WEBHOOK_SECRET.replace(/^whsec_/, ""));
export async function POST(request) {
const body = await request.text(); // the raw body, before any JSON parsing
const event = wh.verify(body, {
"webhook-id": request.headers.get("webhook-id"),
"webhook-timestamp": request.headers.get("webhook-timestamp"),
"webhook-signature": request.headers.get("webhook-signature"),
}); // throws if the signature or timestamp is wrong
if (event.type === "clip.exported") console.log(event.data.export.files.mp4.url);
return new Response(null, { status: 204 });
}
// Without a library: HMAC-SHA256 over `${id}.${timestamp}.${body}`, keyed with the
// base64-decoded secret (after whsec_), base64-encoded, compared to each "v1,<sig>"
// in webhook-signature. Reject timestamps more than 5 minutes off.MCP server
Agents can drive the whole workflow through the remote MCP server at https://reeltopus.com/api/mcp (Streamable HTTP, stateless). It accepts two kinds of bearer token:
- OAuth, for claude.ai, Claude Desktop, ChatGPT and any client that connects by signing in: add
https://reeltopus.com/api/mcpas a custom connector. A 401 points the client athttps://reeltopus.com/.well-known/oauth-protected-resource/api/mcp, which names Reeltopus as the authorization server (https://reeltopus.com/.well-known/oauth-authorization-server): authorization code with PKCE (S256), client ID metadata documents or dynamic registration at/oauth/register, refresh tokens that rotate, and revocation at/oauth/revoke. The member who signs in picks the workspace and what the app may do: read (see your workspace), process (process videos), edit (edit and export clips), post (post to your connected accounts). Access tokens last an hour. Connected apps are listed, and can be disconnected, under Settings → API. - An API key, for clients that take a header. In Claude Code:
claude mcp add --transport http reeltopus https://reeltopus.com/api/mcp --header "Authorization: Bearer rt_live_…"Cursor, the OpenAI Agents SDK, LangChain and most MCP clients take the URL and header in their config:
{
"mcpServers": {
"reeltopus": {
"type": "http",
"url": "https://reeltopus.com/api/mcp",
"headers": {
"Authorization": "Bearer rt_live_…"
}
}
}
}What the server tells the agent:
Reeltopus turns long videos into short vertical clips with captions, reframed for 9:16, and posts them.
Typical workflow:
1. get_account: check the hours left (processing a video spends its length in hours; exports and posts are free).
2. create_project_from_url with a YouTube link (or start_upload + complete_upload for a file you can upload over HTTP).
3. get_status every 30-60 seconds until status is "ready" (or "failed"; failed projects are refunded).
4. get_clips: clips ranked best first, with title, hook, score, transcript.
5. Optionally edit_clip (caption style, trim, silence removal, title, hook, word-level edits).
6. export_clip, then get_export until status is "ready": it returns the MP4 link. Caption files (SRT/VTT/ASS) and the editor timeline links work right away.
7. Optionally list_connections and schedule_post to publish to a connected account.
Rules: only import videos the user owns or has the rights to, and confirm with the user before posting anything publicly. Download links expire after an hour; call get_export again for fresh ones.Tools:
get_account: Shows the Reeltopus workspace this key belongs to: plan, processing hours left (balanceSeconds), hours held by running jobs, the monthly allowance and next refill, and rate limits.create_project_from_url: Starts clipping a YouTube video (watch, youtu.be, shorts or live link).start_upload: Starts uploading a local video file, for agents that can make HTTP requests themselves (for example with curl).get_upload_part_urls: Presigned PUT URLs for further parts of an upload started with start_upload (up to 100 per call).complete_upload: Finishes an upload started with start_upload, once every part is uploaded: Reeltopus checks the file's length, holds those hours and starts processing.get_status: A project's status: importing (downloading the link), uploading, processing (transcribing and finding clips), ready (call get_clips), or failed (see error; held hours were refunded).list_projects: The workspace's projects (videos), newest first, with their status.get_clips: The clips Reeltopus found in a ready project, best first (rank 1 is the most likely to perform), each with title, hook, reason, score, start and end in the source, exported length, transcript, caption style and export status.edit_clip: Changes a clip; everything in one call is one undo step in the app.export_clip: Queues the clip's captioned, reframed MP4 export (free).get_export: A clip's export status (idle, queued, rendering, ready, failed) and download links valid for an hour: the MP4 (once ready), SRT/VTT/ASS caption files and the editor timeline (.zip with FCPXML for Final Cut and DaVinci Resolve, Premiere XML and SRT).list_caption_styles: The caption styles a clip can use (id and name), for edit_clip and export_clip.list_connections: Social accounts connected to the workspace (connected by the user in the Reeltopus app), with the visibilities and title and description limits each accepts.schedule_post: Publishes an exported clip (export status ready) to a connected account, now or at scheduledAt (ISO 8601, up to a year ahead).get_post: A post's status (scheduled, queued, publishing, published, failed, cancelled), its platform URL once published, or the error.cancel_post: Cancels a scheduled or queued post before it starts publishing.
Reference
Every operation below is in the OpenAPI 3.1 document with full request and response schemas, ready for code generators, Postman or an agent's tool loader.
GET/api/v1/me
Get the workspace, its hours and rate limits
POST/api/v1/uploads
Start a file upload
Creates a project and a multipart upload. PUT each part (partSize bytes; the last one smaller) to its presigned URL, keep each response's ETag header, then call complete. Presigned URLs last an hour.
POST/api/v1/uploads/{projectId}/parts
Get presigned URLs for more parts
POST/api/v1/uploads/{projectId}/complete
Finish an upload and start processing
Reeltopus measures the file, holds hours for its length (half in archive mode) and starts transcribing. Hours are settled on the transcript's length and refunded in full if processing fails, exactly as for uploads in the app.
GET/api/v1/projects
List projects, newest first
POST/api/v1/projects
Create a project from a video link
Checks the YouTube video (length, availability), holds hours for its length and queues the download, then processing. Only for videos the workspace owns or has the rights to; set rightsConfirmed to true.
GET/api/v1/projects/{projectId}
Get a project's status
GET/api/v1/projects/{projectId}/clips
List a project's clips, best first
GET/api/v1/clips/{clipId}
Get a clip
PATCH/api/v1/clips/{clipId}
Edit a clip
Fields become edit operations, applied before `edits`; the whole request is one undo step in the app. A finished export whose picture, sound or captions changed goes back to idle.
GET/api/v1/clips/{clipId}/export
Get a clip's export status and download links
POST/api/v1/clips/{clipId}/export
Export a clip as MP4
Free. Poll GET until status is ready (or subscribe to clip.exported). An export already under way is left alone.
GET/api/v1/caption-styles
List caption styles
GET/api/v1/connections
List connected social accounts
Accounts are connected by a person in the app (Connections), never through the API.
GET/api/v1/posts
List posts, newest first
POST/api/v1/posts
Post or schedule an exported clip
GET/api/v1/posts/{postId}
Get a post
DELETE/api/v1/posts/{postId}
Cancel a scheduled post
GET/api/v1/webhooks
List webhook endpoints
POST/api/v1/webhooks
Subscribe a URL to events
The response includes the signing secret, once. Up to 10 endpoints per workspace.
DELETE/api/v1/webhooks/{webhookId}
Delete a webhook endpoint
POST/api/v1/webhooks/{webhookId}/test
Send a test event now