Quickstart
Run your first FFmpeg task on FFHub in 3 minutes.
This guide walks you through your first FFmpeg API call: get an API key, submit a transcoding task, and read the result.
1. Get an API Key
Sign up at ffhub.io and create an API key in the dashboard. The key looks like sk_xxxxx — keep it private.
You also get free credits when you sign up, so the steps below cost nothing to try out.
2. Submit a Task
Send any FFmpeg command to POST /v1/tasks. Inputs must be public URLs — local paths get rejected by the cloud worker.
curl -X POST https://api.ffhub.io/v1/tasks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"command": "ffmpeg -i https://storage.ffhub.io/Sample_Video_File_100MB.mp4 -c:v libx264 -preset fast output.mp4"
}'
const res = await fetch("https://api.ffhub.io/v1/tasks", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.FFHUB_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
command:
"ffmpeg -i https://storage.ffhub.io/Sample_Video_File_100MB.mp4 -c:v libx264 -preset fast output.mp4",
}),
});
const { task_id } = await res.json();
import os, requests
res = requests.post(
"https://api.ffhub.io/v1/tasks",
headers={"Authorization": f"Bearer {os.environ['FFHUB_API_KEY']}"},
json={
"command": "ffmpeg -i https://storage.ffhub.io/Sample_Video_File_100MB.mp4 -c:v libx264 -preset fast output.mp4",
},
)
task_id = res.json()["task_id"]
The response gives you a task_id you'll use to poll status:
{
"task_id": "01abcd…",
"status": "pending",
"created_at": "2026-05-10T12:00:00Z"
}
3. Poll Until Done
curl https://api.ffhub.io/v1/tasks/TASK_ID \
-H "Authorization: Bearer YOUR_API_KEY"
Poll once every 2–5 seconds. When status becomes completed, the response includes a public download URL:
{
"task_id": "01abcd…",
"status": "completed",
"progress": 100,
"outputs": [
{
"filename": "output.mp4",
"url": "https://storage.ffhub.io/outputs/01abcd…/output.mp4",
"size": 10485760
}
]
}
Output URLs expire after 24 hours — download what you want to keep.
Uploading Local Files
If your input isn't already a public URL, upload it first to get one. Two steps:
# 1. Ask for a one-time signed PUT URL
SIGNED=$(curl -s -X POST https://api.ffhub.io/v1/uploads/sign \
-H "Authorization: Bearer $FFHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"filename":"input.mp4","size":12345678,"content_type":"video/mp4"}')
# 2. PUT the file directly to R2 — your server never sees the bytes
curl -X PUT "$(echo "$SIGNED" | jq -r '.upload_url')" \
-H "Content-Type: video/mp4" \
--data-binary "@./input.mp4"
# The .public_url field is what you pass to `-i` in the task command.
Full walkthrough in Upload Files.
What Next
- CLI — run FFmpeg from your terminal, local files auto-uploaded
- n8n integration — visual workflows
- Claude Code skill — call FFHub from Claude Code
- OpenAPI spec — every endpoint, every parameter