API reference

FFmpeGo exposes a single encode endpoint. Authenticate with a Bearer API key. Copy the examples below as-is to verify your integration against public sample videos.

POST /v2/run

Send JSON, get the encoded file back — or PUT it to your own signed storage URL.

Base URL: https://ffmpego.com

Auth: Authorization: Bearer ffc_live_...

Billing header (success): X-Compute-Seconds

Request body

inputs and args are required. Everything else is optional.

FieldRequiredDescription
inputsrequiredArray of input files. inputs[i] is FFmpeg input i ([0:v], -map 1:a, …).
argsrequiredFFmpeg flags only. Do not include -i— inputs are prepended automatically. Placeholders like {input0} are not supported.
outputFilenameoptionalOutput file name, including extension. Default: output.
outputContentTypeoptionalOverride response Content-Type when you are not using upload. Otherwise inferred from the output extension.
uploadoptionalAfter a successful encode, PUT the file to a signed URL instead of returning the binary in the HTTP response.

Each inputs[] item

FieldRequiredDescription
urloptionalPublic HTTPS URL of the file. Provide either url or data.
dataoptionalBase64-encoded file bytes (alternative to url).
filenameoptionalHelps FFmpeg detect the format. If omitted, the extension is taken from the URL path (e.g. .mp4).

Each item must include exactly one of url or data.

upload (optional)

When upload is present, the API does not stream the encoded file back. After FFmpeg exits 0, it issues a single PUT to your URL (signed storage upload, S3 presigned PUT, and similar). Resumable/TUS uploads are not supported. URL lifetime is your responsibility.

FieldRequiredDescription
upload.urlrequiredSigned upload URL, used as-is. Do not rewrite the path.
upload.headersrequiredMust include Content-Type (for example video/mp4). Content-Length is added from the file size.
upload.methodoptionalIf provided, must be PUT.

Response

Without upload (default): 200 with the encoded file as the body. Content-Type comes from outputContentType or the output extension.

With upload: 200 JSON:

response.json
{
  "ok": true,
  "uploaded": true,
  "bytes": 21375689,
  "contentType": "video/mp4",
  "outputFilename": "export.mp4"
}

If storage returns HTTP 4xx/5xx after a successful encode, the API responds 502. FFmpeg failures return 500 and skip the upload. Invalid upload objects return 400.

Examples

Public Pixabay clips you can paste into a request to confirm your key and client work. Save the response body as the named output file.

Transcode to MP4

transcode.json
{
  "inputs": [
    {
      "url": "https://cdn.pixabay.com/video/2025/11/07/314643_tiny.mp4"
    }
  ],
  "args": [
    "-c:v",
    "libx264",
    "-c:a",
    "aac",
    "-f",
    "mp4"
  ],
  "outputFilename": "out.mp4",
  "outputContentType": "video/mp4"
}
curl
curl -X POST https://ffmpego.com/v2/run \
  -H "Authorization: Bearer ffc_live_..." \
  -H "Content-Type: application/json" \
  -d '{"inputs":[{"url":"https://cdn.pixabay.com/video/2025/11/07/314643_tiny.mp4"}],"args":["-c:v","libx264","-c:a","aac","-f","mp4"],"outputFilename":"out.mp4","outputContentType":"video/mp4"}' \
  --output out.mp4

Video to GIF

10 fps, 320px wide, Lanczos scaling. Save the response as output.gif.

gif.json
{
  "inputs": [
    {
      "url": "https://cdn.pixabay.com/video/2025/11/07/314643_tiny.mp4"
    }
  ],
  "args": [
    "-vf",
    "fps=10,scale=320:-1:flags=lanczos",
    "-c:v",
    "gif"
  ],
  "outputFilename": "output.gif"
}
curl
curl -X POST https://ffmpego.com/v2/run \
  -H "Authorization: Bearer ffc_live_..." \
  -H "Content-Type: application/json" \
  -d '{"inputs":[{"url":"https://cdn.pixabay.com/video/2025/11/07/314643_tiny.mp4"}],"args":["-vf","fps=10,scale=320:-1:flags=lanczos","-c:v","gif"],"outputFilename":"output.gif"}' \
  --output output.gif

Concatenate two videos

Video-only concat — works even when an input has no audio. If both clips have audio and you want to keep it, use [0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[outv][outa] and add -map [outa].

concat.json
{
  "inputs": [
    {
      "url": "https://cdn.pixabay.com/video/2025/06/24/287510_tiny.mp4",
      "filename": "video1.mp4"
    },
    {
      "url": "https://cdn.pixabay.com/video/2025/11/07/314643_tiny.mp4",
      "filename": "video2.mp4"
    }
  ],
  "args": [
    "-filter_complex",
    "[0:v][1:v]concat=n=2:v=1:a=0[outv]",
    "-map",
    "[outv]"
  ],
  "outputFilename": "concatenated.mp4"
}

Upload the result to storage

Replace upload.url with a one-shot signed PUT URL from your bucket. The HTTP response is JSON metadata, not the video bytes.

upload.json
{
  "inputs": [
    {
      "url": "https://cdn.pixabay.com/video/2025/11/07/314643_tiny.mp4"
    }
  ],
  "args": [
    "-c:v",
    "libx264",
    "-f",
    "mp4"
  ],
  "outputFilename": "export.mp4",
  "upload": {
    "url": "https://<project>.supabase.co/storage/v1/object/upload/sign/bucket/path?token=...",
    "method": "PUT",
    "headers": {
      "Content-Type": "video/mp4"
    }
  }
}

Limits (Free plan)

75 compute seconds / month

5 requests / month

1000 requests / hour

Errors

400 — invalid body (including upload)

401 — missing or invalid API key

402 — monthly quota exceeded

429 — rate limit exceeded

502 — encode succeeded but storage PUT failed

4xx/5xx from FFmpeg — not billed