Run your first FFmpeg API request
This guide walks through a complete workflow — from upload to finished output — so you can make your first request and see how the pieces connect.
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.
- 4.(Optional) Webhook URL — If you want the API to notify you when jobs finish instead of polling, set up a webhook endpoint. See the webhooks guide.
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 or wait for webhook
Jobs run asynchronously. You can poll for status or set up a webhook to get notified when they finish.
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"
}Add a webhookUrl field to your transcode request:
{
"inputs": [{ "url": "gs://your-bucket/1234567890-video.mp4" }],
"outputFormat": "mp4",
"webhookUrl": "https://your-app.com/webhooks/ffmpeg"
}When the job finishes, the API sends a POST to your webhook with the final job state. See webhook docs for payload format and retry behavior.
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.
Cause: Your webhook URL is unreachable, returns an error status, or times out.
Fix: Make sure the webhook endpoint is publicly accessible and returns 200 OK within 10 seconds. Check your server logs for incoming POST requests. See webhook docs for retry behavior.
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.
Webhook setup
Get notified when jobs finish instead of polling. Includes retry logic and payload format.
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.