Render smoother video from your app.
The whole integration is four calls: upload a clip, start a render, poll until it finishes, download the output. Do it by hand below, or skip straight to the one-prompt path and let your AI tool wire it up.
Get an API key
API users authenticate with a dashboard-generated key. Keep it server-side in production; these examples show the key inline so the replaceable value is obvious. Send it on every protected request as Authorization: Bearer <your_api_key>.
Verify the key works:
curl -s "https://reframefx-production.up.railway.app/me" \
-H "Authorization: Bearer <your_api_key>"Returns your profile and balance_xeconds. A 401 means the key is missing or wrong.
Endpoints
The full render flow, one endpoint at a time. Every protected request needs the Authorization header from above. The upload PUT is the only call that goes to storage instead of the API.
POST/upload/presignCreate a direct upload URL for your file, then PUT the bytes to it.
# 1. Presign: returns { upload_url, key, project_id }
curl -s -X POST "https://reframefx-production.up.railway.app/upload/presign" \
-H "Authorization: Bearer <your_api_key>" \
-H "Content-Type: application/json" \
-d '{"filename":"clip.mp4","content_type":"video/mp4"}'
# 2. Upload the file to the upload_url from that response.
# Note: PUT, no auth header, Content-Type must match the presign.
curl -s -X PUT "<upload_url>" \
-H "Content-Type: video/mp4" \
--upload-file ./clip.mp4{
"upload_url": "https://...storage.../clip.mp4?signature=...",
"key": "uploads/ab12.../clip.mp4",
"project_id": "9f3c..."
}POST/pricing/estimate-videoOptional. Probe the uploaded file and see the charged xeconds for each target FPS before you render.
curl -s -X POST "https://reframefx-production.up.railway.app/pricing/estimate-video" \
-H "Authorization: Bearer <your_api_key>" \
-H "Content-Type: application/json" \
-d '{"r2_key":"<key from presign>","target_fps_options":[60,120,240]}'{
"metadata": { "fps": 24, "duration_sec": 12.4, "width": 1920, "height": 1080 },
"estimates": [
{ "target_fps": 60, "band": "smooth", "multiplier": 1, "charged_xeconds": 12 },
{ "target_fps": 120, "band": "slomo", "multiplier": 2, "charged_xeconds": 24 },
{ "target_fps": 240, "band": "ultra", "multiplier": 4, "charged_xeconds": 48 }
]
}POST/jobsStart the render. Credits are deducted when the job is accepted. target_fps must be greater than the source FPS.
curl -s -X POST "https://reframefx-production.up.railway.app/jobs" \
-H "Authorization: Bearer <your_api_key>" \
-H "Content-Type: application/json" \
-d '{"r2_key":"<key>","project_id":"<project_id>","target_fps":60}'{
"job_id": "job_7b2e...",
"status": "queued"
}GET/jobs/{job_id}Fetch the job and read live_status. Re-request roughly every 10 seconds until it's done or failed. On done, output_url is the rendered video.
# Loop/repeat this request about every 10s until live_status is done or failed.
curl -s "https://reframefx-production.up.railway.app/jobs/<job_id>" \
-H "Authorization: Bearer <your_api_key>"{
"job_id": "job_7b2e...",
"live_status": "done",
"target_fps": 60,
"output_url": "https://...storage.../output.mp4?signature=...",
"xeconds_charged": 12
}Job status
Poll GET /jobs/{job_id} and read live_status. The API returns stable status values; your app owns the user-facing wording.
pendingJob created and waiting for render status.queuedAccepted and waiting to start.no_workersQueued while render capacity is full.cold_startRender environment is preparing.processingVideo is being processed.doneRender succeeded. Use output_url to download.failedRender failed. Deducted xeconds are refunded automatically.Limits & pricing
Video size250MB maximum during launch. Larger files return 413.Video length120 seconds maximum during launch.Output FPS24-240fps, and target_fps must be greater than the source FPS.Smooth bandUp to 60fps. charged_xeconds = max(1, floor(duration_sec)) x 1.Slo-mo band61-120fps. charged_xeconds = max(1, floor(duration_sec)) x 2.Ultra band (cinematic slo-mo)121-240fps. charged_xeconds = max(1, floor(duration_sec)) x 4.Free creditsFree renders are watermarked. Paid-credit renders are clean by default.Errors
Errors return a status code and JSON with a readable detail field.
{
"detail": "Launch limit is 120s per video. Longer video chunking is coming."
}400Invalid request body or unsupported params.401Missing or invalid API key.402Insufficient xeconds balance.403The resource belongs to another account.404Project, job, or file was not found.413Upload exceeds launch size or duration limits.500Unexpected server error. Retry reads; contact support if a write is unclear.For AI agents
ReframeFX is built to be integrated by coding agents. The fastest path is the Integrate with one prompt button at the top — it copies a self-contained prompt for Cursor, Claude Code, or any AI tool. For programmatic discovery, these are always live:
- /openapi.json — machine-readable OpenAPI 3 schema for Postman, client generators, and agents.
- /llms-full.txt — the full docs as plain text, in one fetch.
- /llms.txt — a short, structured index of the canonical pages and key facts.