Run your first FFmpeg API request
This guide walks through the complete workflow, from upload to finished output, so you can make your first request and see how the pieces connect.
Run this quickstart automatically
Sign up and the dashboard walks you through this exact flow interactively. It creates a temporary API key, then runs each step for you: presigned upload, transcode, poll, download. The matching request and response are shown at every stage. Prefer your terminal? Every step also gives you the copy-paste command.
The video walks through getting started end to end.
Before you begin
Make sure you have these ready before running your first request.
- 1.API key. Get yours from the API Keys page in your dashboard.
- 2.A sample video file. Any MP4, MOV, or WebM file works. We'll use
video.mp4in the examples below. - 3.Somewhere to store the output. Your processed video gets stored in a Google Cloud Storage bucket tied to your account. You'll download it via a signed URL.
Step 1: Authenticate your request
Every API request needs your key in the Authorization header.
Set the header like this on every request:
Authorization: Bearer YOUR_API_KEY
Replace YOUR_API_KEY with your actual key. The API returns 401 Unauthorized if the key is missing or invalid.
Step 2: Submit a job
Upload your video and create a processing job. The workflow is: request upload URL → upload file → confirm upload → create transcode job.
Request
POST https://api.ffmpeg-micro.com/v1/upload/presigned-url
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY
{
"filename": "video.mp4",
"contentType": "video/mp4",
"fileSize": 12345678
}Response
{
"success": true,
"result": {
"uploadUrl": "https://storage.googleapis.com/...",
"filename": "1234567890-video.mp4"
}
}Note: fileSize must be a number (bytes), not a string. The API returns 400 if you send "12345678" instead of 12345678.
Request
PUT https://storage.googleapis.com/... Content-Type: video/mp4 <binary file data>
Send the file as binary data in the request body. The presigned URL expires after 10 minutes.
Request
POST https://api.ffmpeg-micro.com/v1/upload/confirm
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY
{
"filename": "1234567890-video.mp4",
"fileSize": 12345678
}Response
{
"success": true,
"result": {
"fileUrl": "gs://your-bucket/1234567890-video.mp4",
"downloadUrl": "https://storage.googleapis.com/..."
}
}Save the fileUrl. You'll need it to create the transcode job.
Request
POST https://api.ffmpeg-micro.com/v1/transcodes
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY
{
"inputs": [
{ "url": "gs://your-bucket/1234567890-video.mp4" }
],
"outputFormat": "mp4",
"preset": {
"quality": "medium",
"resolution": "1080p"
}
}Response
{
"id": "abc123-job-uuid",
"status": "pending",
"inputs": [
{ "url": "gs://your-bucket/1234567890-video.mp4" }
],
"output_format": "mp4",
"created_at": "2026-05-08T12:00:00Z"
}The job starts as pending and moves to processing when a worker picks it up. Save the id. You'll use it to check status.
Step 3: Check job status
Jobs run asynchronously. Poll the job endpoint until the status changes to completed or failed.
completed or failed.Request
GET https://api.ffmpeg-micro.com/v1/transcodes/abc123-job-uuid Authorization: Bearer YOUR_API_KEY
Response (while processing)
{
"success": true,
"jobId": "abc123-job-uuid",
"status": "processing",
"createdAt": "2026-05-08T12:00:00Z"
}Response (completed)
{
"success": true,
"jobId": "abc123-job-uuid",
"status": "completed",
"outputUrl": "gs://output-bucket/processed-video.mp4",
"createdAt": "2026-05-08T12:00:00Z",
"completedAt": "2026-05-08T12:02:30Z"
}Step 4: Retrieve the completed output
Once the job is completed, download your processed video.
Request a download URL
GET https://api.ffmpeg-micro.com/v1/transcodes/abc123-job-uuid/download Authorization: Bearer YOUR_API_KEY
Response
{
"url": "https://storage.googleapis.com/...?X-Goog-Signature=..."
}Download the file
curl -o output.mp4 "https://storage.googleapis.com/...?X-Goog-Signature=..."
The signed URL expires after 10 minutes. If it expires, just call /download again to get a fresh one.
Copy-paste examples
Complete working examples in curl, Node.js, and Python. Replace YOUR_API_KEY and run.
#!/bin/bash
API_KEY="YOUR_API_KEY"
API_URL="https://api.ffmpeg-micro.com"
VIDEO_FILE="video.mp4"
FILE_SIZE=$(stat -f%z "$VIDEO_FILE") # macOS; use -c%s on Linux
# Step 1: Request presigned upload URL
UPLOAD_RESPONSE=$(curl -s -X POST "$API_URL/v1/upload/presigned-url" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d "{\"filename\": \"$VIDEO_FILE\", \"contentType\": \"video/mp4\", \"fileSize\": $FILE_SIZE}")
UPLOAD_URL=$(echo "$UPLOAD_RESPONSE" | jq -r '.result.uploadUrl')
FILENAME=$(echo "$UPLOAD_RESPONSE" | jq -r '.result.filename')
echo "Upload URL: $UPLOAD_URL"
echo "Filename: $FILENAME"
# Step 2: Upload the file
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: video/mp4" \
--data-binary "@$VIDEO_FILE"
# Step 3: Confirm upload
CONFIRM_RESPONSE=$(curl -s -X POST "$API_URL/v1/upload/confirm" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d "{\"filename\": \"$FILENAME\", \"fileSize\": $FILE_SIZE}")
FILE_URL=$(echo "$CONFIRM_RESPONSE" | jq -r '.result.fileUrl')
echo "File URL: $FILE_URL"
# Step 4: Create transcode job
JOB_RESPONSE=$(curl -s -X POST "$API_URL/v1/transcodes" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d "{\"inputs\": [{\"url\": \"$FILE_URL\"}], \"outputFormat\": \"mp4\", \"preset\": {\"quality\": \"medium\", \"resolution\": \"1080p\"}}")
JOB_ID=$(echo "$JOB_RESPONSE" | jq -r '.id')
echo "Job ID: $JOB_ID"
# Step 5: Poll for completion
while true; do
STATUS_RESPONSE=$(curl -s "$API_URL/v1/transcodes/$JOB_ID" \
-H "Authorization: Bearer $API_KEY")
STATUS=$(echo "$STATUS_RESPONSE" | jq -r '.status')
echo "Status: $STATUS"
if [ "$STATUS" = "completed" ]; then
break
elif [ "$STATUS" = "failed" ]; then
echo "Job failed"
exit 1
fi
sleep 3
done
# Step 6: Download output
DOWNLOAD_RESPONSE=$(curl -s "$API_URL/v1/transcodes/$JOB_ID/download" \
-H "Authorization: Bearer $API_KEY")
DOWNLOAD_URL=$(echo "$DOWNLOAD_RESPONSE" | jq -r '.url')
curl -o "output.mp4" "$DOWNLOAD_URL"
echo "Download complete: output.mp4"Common errors and how to fix them
These are the errors people hit most often when making their first request.
Cause: Missing or invalid API key.
Fix: Check that you're sending Authorization: Bearer YOUR_API_KEY on every request. Make sure the key is active and hasn't been deleted.
Cause: You sent "fileSize": "12345678" (string) instead of "fileSize": 12345678 (number).
Fix: Send file size as a JSON number, not a quoted string. Same for any byte count field.
Cause: You tried to upload a file type the API doesn't support (e.g., .avi with an obscure codec).
Fix: Check supported input formats. MP4, MOV, WebM, and MKV work for most cases.
Cause: You set an outputUrl pointing to a bucket or path the API can't write to.
Fix: Leave outputUrl blank to use the default output bucket. If you need a custom bucket, make sure it's configured in your account settings.
Cause: Invalid JSON or missing required fields (e.g., no inputs array).
Fix: Check the request body matches the API docs. Use a JSON validator to catch syntax errors.
Where to go next
You've made your first request. Here's what to explore next.
Full API reference
Complete endpoint docs, advanced options, and all supported formats.
Real-world examples
Common workflows: thumbnails, clipping, watermarks, HLS packaging, subtitle burn-in.
Automate with n8n
Build no-code video workflows that trigger from uploads, CMS updates, or storage events.
Node.js integration
Production-ready patterns for Express, Next.js, and serverless functions.
Python integration
Django, Flask, and FastAPI examples with async job handling.
Ready to process your first video?
Sign up for a free account and get 100 minutes of processing time. No credit card required.