FFmpeg Micro API Documentation
Transform videos with our simple, secure API. Upload, transcode, and download processed videos.
All API requests should be sent to:https://api.ffmpeg-micro.com
Include your API key in the Authorization header:Authorization: Bearer YOUR_API_KEY
💡 Get your API key from the API Keys page in your dashboard.
Request a presigned URL with filename, content type, and file size in bytes. Send fileSize as a JSON number (not a quoted string or human-readable size).
Use the presigned URL to upload your video file directly to storage (no API key needed for upload).
Confirm with the same filename and byte size as JSON numbers; the API checks the object in storage matches what you declared.
Submit a transcode job with your desired output format and quality. Get job ID immediately.
Poll for job status, and when complete, download your processed video.
API Endpoints
Core routes for uploads, transcodes, and downloads. The full contract is the OpenAPI spec, the same file the API serves.
Want to explore these endpoints interactively?
The API Playground lets you browse each endpoint, see the request shape and headers, and copy ready-to-run cURL commands without leaving the docs.
/v1/upload/presigned-url{
"filename": "video.mp4",
"contentType": "video/mp4",
"fileSize": 12345678
}fileSize must be a JSON number (size in bytes), not a string. Quoted values like "1024" or human-readable sizes are rejected with 400.
{
"success": true,
"result": {
"uploadUrl": "https://storage.googleapis.com/...",
"filename": "1234567890-video.mp4"
}
}curl -X POST https://api.ffmpeg-micro.com/v1/upload/presigned-url \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"filename": "video.mp4",
"contentType": "video/mp4",
"fileSize": 12345678
}'uploadUrl (from step 1)# Replace UPLOAD_URL with the exact uploadUrl value from step 1 curl -X PUT "$UPLOAD_URL" \ -H "Content-Type: video/mp4" \ --data-binary @/path/to/video.mp4
/v1/upload/confirm{
"filename": "1234567890-video.mp4",
"fileSize": 12345678
}fileSize must be a JSON number (bytes), same as step 1—not a string. It must match the uploaded object in storage; wrong types return 400 with an explicit validation error.
curl -X POST https://api.ffmpeg-micro.com/v1/upload/confirm \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"filename": "1234567890-video.mp4",
"fileSize": 12345678
}'/v1/transcodes<YOUR_BUCKET> below with the bucket name from Step 3's fileUrl response.{
"inputs": [
{ "url": "gs://<YOUR_BUCKET>/1234567890-video.mp4" }
],
"outputFormat": "mp4",
"preset": {
"quality": "medium",
"resolution": "1080p"
}
}Note: -filter_complex is not supported. See supported alternatives.
{
"inputs": [
{ "url": "gs://<YOUR_BUCKET>/1234567890-video.mp4" }
],
"outputFormat": "mp4",
"options": [
{ "option": "-c:v", "argument": "libx264" },
{ "option": "-crf", "argument": "23" },
{ "option": "@text-overlay", "argument": {
"text": "Hello World",
"style": { "fontSize": 60, "x": "0.15*w", "y": "(h-text_h)/2" }
}}
]
}{
"id": "job-uuid",
"status": "pending",
"inputs": [
{ "url": "gs://<YOUR_BUCKET>/1234567890-video.mp4" }
],
"output_format": "mp4",
"created_at": "2025-01-01T00:00:00Z"
}curl -X POST https://api.ffmpeg-micro.com/v1/transcodes \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"inputs": [
{ "url": "gs://<YOUR_BUCKET>/1234567890-video.mp4" }
],
"outputFormat": "mp4",
"preset": {
"quality": "medium",
"resolution": "1080p"
}
}'/v1/transcodes/:id{
"success": true,
"jobId": "job-uuid",
"status": "completed",
"outputUrl": "gs://output-bucket/processed-video.mp4",
"createdAt": "2025-01-01T00:00:00Z",
"completedAt": "2025-01-01T00:02:30Z",
"started_at": "2025-01-01T00:00:12Z",
"lane": "short",
"queue_position": 1
}Every job runs in one of three lanes, each on its own server, so a job in one lane can never delay a job in another. Jobs with many large inputs (more than five 4K clips' worth of pixels) go to the heavy lane, which has more memory. Otherwise inputs longer than two minutes go to the long lane, and everything else to short. queue_position is how many jobs were in the queue on the worker that accepted it, yours included (1 means it was next in line). It is set once at acceptance and never updated. started_at is set the moment encoding begins: while it is null your job is waiting, and once it has a value your job is running, whatever queue_position says. started_at - created_at is submission-to-start, an upper bound on your wait because it also includes our own download and probe. Links to uploaded inputs stay valid for 24 hours, so a job that waits still runs.
curl -X GET https://api.ffmpeg-micro.com/v1/transcodes/job-uuid \ -H "Authorization: Bearer YOUR_API_KEY"
/v1/transcodes/:id/download{
"url": "https://storage.googleapis.com/...?X-Goog-Signature=..."
}# Get signed URL curl -X GET https://api.ffmpeg-micro.com/v1/transcodes/job-uuid/download \ -H "Authorization: Bearer YOUR_API_KEY" # Then download the file curl -O "$DOWNLOAD_URL"
/v1/transcribe/v1/transcodes.{
"media_url": "gs://<YOUR_BUCKET>/1234567890-audio.mp3",
"language": "en", // optional — auto-detected by default
"task": "transcribe" // optional — "transcribe" or "translate"
}{
"id": "job-uuid",
"status": "pending",
"media_url": "gs://<YOUR_BUCKET>/1234567890-audio.mp3",
"output_format": "srt",
"created_at": "2026-04-19T17:22:44.396Z"
}curl -X POST https://api.ffmpeg-micro.com/v1/transcribe \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{ "media_url": "gs://<YOUR_BUCKET>/1234567890-audio.mp3" }'/v1/transcribe/:idstatus is completed or failed. Same polling shape as /v1/transcodes/:id.curl -X GET https://api.ffmpeg-micro.com/v1/transcribe/job-uuid \ -H "Authorization: Bearer YOUR_API_KEY"
/v1/transcribe/:id/downloadsubtitles='…' filter to burn captions into a video.{
"url": "https://storage.googleapis.com/...?X-Goog-Signature=..."
}curl -X GET https://api.ffmpeg-micro.com/v1/transcribe/job-uuid/download \ -H "Authorization: Bearer YOUR_API_KEY"
/v1/transcodes- •
status— Filter by status (queued, processing, completed, failed) - •
page— Page number (default: 1) - •
limit— Items per page (default: 20, max: 100) - •
since— Jobs created after this timestamp - •
until— Jobs created before this timestamp
curl -X GET "https://api.ffmpeg-micro.com/v1/transcodes?status=completed&page=1&limit=20" \ -H "Authorization: Bearer YOUR_API_KEY"
/v1/transcodes/:idcurl -X GET "https://api.ffmpeg-micro.com/v1/transcodes/job-uuid" \ -H "Authorization: Bearer YOUR_API_KEY"
/health-check{
"ok": true,
"timestamp": "2025-10-23T14:30:45.123Z",
"uptime": 3600.5,
"supabase": {
"ok": true,
"status": 200,
"statusText": "OK",
"connected": true
}
}curl -X GET https://api.ffmpeg-micro.com/health-check
Supported Formats
- • MP4 (H.264, H.265)
- • WebM (VP8, VP9)
- • AVI (various codecs)
- • MOV (QuickTime)
- • MP4 (H.264 + AAC)
- • WebM (VP9 + Opus)
- • Quality: low, medium, high
- • Resolutions: 480p, 720p, 1080p, 4K
Follow the quickstart to make your first request: upload to finished output in minutes, with working examples for curl, Node.js, and Python.
Start the QuickstartConnect Claude Code, Cursor, or any MCP-compatible tool and transcode videos with natural language. No SDK, no glue code.
Set up the MCP Server- • @text-overlay — add styled text overlays
- • @quote-card — generate social-ready quote cards
Check duration, codecs, resolution and frame rate, and whether a file has video and audio, before you run a transcode job.
Learn about FFprobe