RenderIO
API referenceCommands

Run Chained Commands

Submit up to 20 FFmpeg commands on the Business plan. They execute sequentially, and outputs from earlier steps are available as inputs to later steps.

Run Chained Commands

POST /api/v1/run-chained-ffmpeg-commands

Submit multiple FFmpeg commands that execute sequentially in a single sandbox. Each command runs after the previous one completes, and outputs from earlier steps are available as inputs to later steps. This is useful for multi-pass encoding, extracting frames then compositing, or any workflow that requires ordered processing.

Authentication

Requires API key via X-API-KEY header.

Request

Headers

HeaderTypeRequiredDescription
Content-TypestringYesMust be application/json
X-API-KEYstringYesYour API key with ffsk_ prefix

Body

interface RunChainedCommandsRequest {
  input_files: Record<string, string>;   // in_* aliases mapped to URLs
  output_files: Record<string, string>;  // out_* aliases mapped to filenames
  ffmpeg_commands: string[];             // Up to 20 per plan, executed sequentially
  metadata?: Record<string, string | number | boolean>; // Max 10 keys
  webhook_url?: string;                  // Per-command webhook override
  storage_destination_id?: string;       // Business: send outputs to your S3-compatible bucket
}
FieldTypeRequiredDescription
input_filesRecord<string, string>YesMap of alias names (must start with in_) to file URLs.
output_filesRecord<string, string>YesMap of alias names (must start with out_) to output filenames.
ffmpeg_commandsstring[]YesArray of FFmpeg commands to execute in order. Maximum 20 commands (Business plan; lower plans enforce a smaller per-plan limit). Use {{alias}} placeholders to reference files.
metadataRecord<string, string | number | boolean>NoArbitrary key-value metadata attached to the command. Maximum 10 keys.
webhook_urlstringNoURL to receive a POST request when all commands complete. Overrides any account-level webhook configuration. Requires the Business plan.
storage_destination_idstringNoSend final outputs to this S3-compatible storage destination. Requires the Business plan.

Response

200 OK

{
  command_id: string;
}
FieldTypeDescription
command_idstringUnique identifier for the chained command. Use this to poll for status.

Retrieve the outputs

Poll GET /api/v1/commands/:commandId until status is SUCCESS or FAILED. Managed outputs provide storage_url. BYOB outputs also provide the persistent external_uri and external_object_key; a private bucket has storage_url: null. See Bring Your Own Bucket.

Error responses

StatusErrorDescription
400INVALID_REQUESTMissing required fields, invalid aliases, or malformed FFmpeg commands.
401UNAUTHORIZEDMissing or invalid API key.
403FORBIDDENThe request exceeds the plan's chained-command limit, or a Business-only webhook or storage destination was requested by an ineligible account.
404NOT_FOUNDThe supplied storage destination does not exist or belongs to another account.
409CONFLICTThe supplied storage destination is disabled.
422VALIDATION_ERRORValidation failed, such as excessive metadata or a malformed storage_destination_id.
429RATE_LIMITEDToo many requests. Retry after the period indicated in the Retry-After header.

Examples

curl -X POST https://renderio.dev/api/v1/run-chained-ffmpeg-commands \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: ffsk_your_api_key_here" \
  -d '{
    "input_files": {
      "in_video": "https://example.com/sample.mp4"
    },
    "output_files": {
      "out_video": "final.mp4"
    },
    "ffmpeg_commands": [
      "ffmpeg -i {{in_video}} -vf scale=1280:720 -c:v libx264 -preset fast intermediate.mp4",
      "ffmpeg -i intermediate.mp4 -af loudnorm -c:v copy {{out_video}}"
    ]
  }'
curl -X POST https://renderio.dev/api/v1/run-chained-ffmpeg-commands \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: ffsk_your_api_key_here" \
  -d '{
    "input_files": {
      "in_video": "https://example.com/sample.mp4"
    },
    "output_files": {
      "out_video": "final.mp4"
    },
    "ffmpeg_commands": [
      "ffmpeg -i <<in_video>> -vf scale=1280:720 -c:v libx264 -preset fast intermediate.mp4",
      "ffmpeg -i intermediate.mp4 -af loudnorm -c:v copy <<out_video>>"
    ]
  }'
import requests

response = requests.post(
    "https://renderio.dev/api/v1/run-chained-ffmpeg-commands",
    headers={
        "Content-Type": "application/json",
        "X-API-KEY": "ffsk_your_api_key_here",
    },
    json={
        "input_files": {
            "in_video": "https://example.com/sample.mp4",
        },
        "output_files": {
            "out_video": "final.mp4",
        },
        "ffmpeg_commands": [
            "ffmpeg -i {{in_video}} -vf scale=1280:720 -c:v libx264 -preset fast intermediate.mp4",
            "ffmpeg -i intermediate.mp4 -af loudnorm -c:v copy {{out_video}}",
        ],
    },
)

data = response.json()
print("Command ID:", data["command_id"])
import requests

response = requests.post(
    "https://renderio.dev/api/v1/run-chained-ffmpeg-commands",
    headers={
        "Content-Type": "application/json",
        "X-API-KEY": "ffsk_your_api_key_here",
    },
    json={
        "input_files": {
            "in_video": "https://example.com/sample.mp4",
        },
        "output_files": {
            "out_video": "final.mp4",
        },
        "ffmpeg_commands": [
            "ffmpeg -i <<in_video>> -vf scale=1280:720 -c:v libx264 -preset fast intermediate.mp4",
            "ffmpeg -i intermediate.mp4 -af loudnorm -c:v copy <<out_video>>",
        ],
    },
)

data = response.json()
print("Command ID:", data["command_id"])
interface ChainedCommandRequest {
  input_files: Record<string, string>;
  output_files: Record<string, string>;
  ffmpeg_commands: string[];
}

interface ChainedCommandResponse {
  command_id: string;
}

const body: ChainedCommandRequest = {
  input_files: {
    in_video: "https://example.com/sample.mp4",
  },
  output_files: {
    out_video: "final.mp4",
  },
  ffmpeg_commands: [
    "ffmpeg -i {{in_video}} -vf scale=1280:720 -c:v libx264 -preset fast intermediate.mp4",
    "ffmpeg -i intermediate.mp4 -af loudnorm -c:v copy {{out_video}}",
  ],
};

const response = await fetch(
  "https://renderio.dev/api/v1/run-chained-ffmpeg-commands",
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-KEY": "ffsk_your_api_key_here",
    },
    body: JSON.stringify(body),
  },
);

const { command_id } = (await response.json()) as ChainedCommandResponse;
console.log("Command ID:", command_id);
interface ChainedCommandRequest {
  input_files: Record<string, string>;
  output_files: Record<string, string>;
  ffmpeg_commands: string[];
}

interface ChainedCommandResponse {
  command_id: string;
}

const body: ChainedCommandRequest = {
  input_files: {
    in_video: "https://example.com/sample.mp4",
  },
  output_files: {
    out_video: "final.mp4",
  },
  ffmpeg_commands: [
    "ffmpeg -i <<in_video>> -vf scale=1280:720 -c:v libx264 -preset fast intermediate.mp4",
    "ffmpeg -i intermediate.mp4 -af loudnorm -c:v copy <<out_video>>",
  ],
};

const response = await fetch(
  "https://renderio.dev/api/v1/run-chained-ffmpeg-commands",
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-KEY": "ffsk_your_api_key_here",
    },
    body: JSON.stringify(body),
  },
);

const { command_id } = (await response.json()) as ChainedCommandResponse;
console.log("Command ID:", command_id);
const response = await fetch(
  "https://renderio.dev/api/v1/run-chained-ffmpeg-commands",
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-KEY": "ffsk_your_api_key_here",
    },
    body: JSON.stringify({
      input_files: {
        in_video: "https://example.com/sample.mp4",
      },
      output_files: {
        out_video: "final.mp4",
      },
      ffmpeg_commands: [
        "ffmpeg -i {{in_video}} -vf scale=1280:720 -c:v libx264 -preset fast intermediate.mp4",
        "ffmpeg -i intermediate.mp4 -af loudnorm -c:v copy {{out_video}}",
      ],
    }),
  },
);

const { command_id } = await response.json();
console.log("Command ID:", command_id);
const response = await fetch(
  "https://renderio.dev/api/v1/run-chained-ffmpeg-commands",
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-KEY": "ffsk_your_api_key_here",
    },
    body: JSON.stringify({
      input_files: {
        in_video: "https://example.com/sample.mp4",
      },
      output_files: {
        out_video: "final.mp4",
      },
      ffmpeg_commands: [
        "ffmpeg -i <<in_video>> -vf scale=1280:720 -c:v libx264 -preset fast intermediate.mp4",
        "ffmpeg -i intermediate.mp4 -af loudnorm -c:v copy <<out_video>>",
      ],
    }),
  },
);

const { command_id } = await response.json();
console.log("Command ID:", command_id);
<?php
$ch = curl_init("https://renderio.dev/api/v1/run-chained-ffmpeg-commands");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Content-Type: application/json",
    "X-API-KEY: ffsk_your_api_key_here",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
    "input_files" => [
        "in_video" => "https://example.com/sample.mp4",
    ],
    "output_files" => [
        "out_video" => "final.mp4",
    ],
    "ffmpeg_commands" => [
        "ffmpeg -i {{in_video}} -vf scale=1280:720 -c:v libx264 -preset fast intermediate.mp4",
        "ffmpeg -i intermediate.mp4 -af loudnorm -c:v copy {{out_video}}",
    ],
]));

$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
echo "Command ID: " . $data["command_id"] . "\n";
<?php
$ch = curl_init("https://renderio.dev/api/v1/run-chained-ffmpeg-commands");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Content-Type: application/json",
    "X-API-KEY: ffsk_your_api_key_here",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
    "input_files" => [
        "in_video" => "https://example.com/sample.mp4",
    ],
    "output_files" => [
        "out_video" => "final.mp4",
    ],
    "ffmpeg_commands" => [
        "ffmpeg -i <<in_video>> -vf scale=1280:720 -c:v libx264 -preset fast intermediate.mp4",
        "ffmpeg -i intermediate.mp4 -af loudnorm -c:v copy <<out_video>>",
    ],
]));

$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
echo "Command ID: " . $data["command_id"] . "\n";

On this page