RenderIO
API referenceStorage destinations

Bring Your Own Bucket

Configure an S3-compatible bucket as the output destination for RenderIO commands.

Bring Your Own Bucket

Business accounts can send command outputs directly to an AWS S3 or S3-compatible bucket. RenderIO encrypts the supplied credentials, uses them only to create short-lived upload URLs, and does not copy externally stored outputs into RenderIO-managed storage.

1. Create least-privilege credentials

Grant access only to the bucket and optional prefix RenderIO will use. The connection test writes, verifies, and deletes a temporary object, while production uploads may use multipart upload.

For AWS S3, this policy is a suitable starting point. Replace the bucket and prefix before applying it:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:DeleteObject",
        "s3:AbortMultipartUpload"
      ],
      "Resource": "arn:aws:s3:::YOUR_BUCKET/renderio/*"
    }
  ]
}

The s3:GetObject and s3:DeleteObject actions are required by the connection test. If you skip the test, the upload path itself requires only s3:PutObject and s3:AbortMultipartUpload.

2. Create a destination

POST /api/v1/storage-destinations
curl -X POST https://renderio.dev/api/v1/storage-destinations \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: ffsk_your_api_key_here" \
  -d '{
    "name": "production-outputs",
    "endpoint_url": "https://s3.us-east-1.amazonaws.com",
    "region": "us-east-1",
    "bucket": "your-company-media",
    "prefix": "renderio",
    "path_style": false,
    "credentials": {
      "access_key_id": "YOUR_ACCESS_KEY_ID",
      "secret_access_key": "YOUR_SECRET_ACCESS_KEY"
    }
  }'

The response contains a storage_destination_id such as sd_0123456789abcdef0123456789abcdef. Save this value for command requests. Secret credentials are never returned; only a masked access key ID is shown.

For Cloudflare R2, use https://ACCOUNT_ID.r2.cloudflarestorage.com as endpoint_url, auto as region, and set path_style to true. Other S3-compatible providers may have different endpoint, region, and addressing requirements.

Destination fields

FieldRequiredDescription
nameYesUnique label for this destination.
endpoint_urlYesHTTPS S3-compatible endpoint. Raw IP addresses are rejected.
regionYesSigning region, such as us-east-1 or auto.
bucketYesDestination bucket name.
prefixNoKey prefix. Leading and trailing slashes are removed.
public_base_urlNoPublic or CDN base URL used to construct storage_url. Omit it for a private bucket.
path_styleNoWhether the bucket belongs in the URL path instead of the hostname. Defaults to false.
credentialsYesaccess_key_id, secret_access_key, and optional session_token.

endpoint_url, region, and bucket are immutable. Create a new destination if any of them need to change.

3. Test the connection

POST /api/v1/storage-destinations/:storageDestinationId/test
curl -X POST \
  https://renderio.dev/api/v1/storage-destinations/sd_0123456789abcdef0123456789abcdef/test \
  -H "X-API-KEY: ffsk_your_api_key_here"

A successful test returns:

{ "ok": true }

An unsuccessful connection test still returns HTTP 200, with ok: false and a safe error message. This lets you distinguish an authenticated test request from a provider-side connectivity or permission failure.

4. Send a command output to the bucket

Add storage_destination_id at the top level of any FFmpeg or yt-dlp command request:

curl -X POST https://renderio.dev/api/v1/run-ffmpeg-command \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: ffsk_your_api_key_here" \
  -d '{
    "input_files": {
      "in_video": "https://example.com/input.mp4"
    },
    "output_files": {
      "out_video": "output.mp4"
    },
    "ffmpeg_command": "-i {{in_video}} -c:v libx264 {{out_video}}",
    "storage_destination_id": "sd_0123456789abcdef0123456789abcdef"
  }'
curl -X POST https://renderio.dev/api/v1/run-ffmpeg-command \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: ffsk_your_api_key_here" \
  -d '{
    "input_files": {
      "in_video": "https://example.com/input.mp4"
    },
    "output_files": {
      "out_video": "output.mp4"
    },
    "ffmpeg_command": "-i <<in_video>> -c:v libx264 <<out_video>>",
    "storage_destination_id": "sd_0123456789abcdef0123456789abcdef"
  }'

Objects use this key layout:

{prefix}/{command_id}/{filename}

When the command reaches SUCCESS, each external output includes:

{
  "file_id": "550e8400-e29b-41d4-a716-446655440000",
  "filename": "output.mp4",
  "status": "STORED",
  "rendi_store_type": "OUTPUT",
  "storage_location": "EXTERNAL",
  "external_uri": "s3://your-company-media/renderio/COMMAND_ID/output.mp4",
  "external_object_key": "renderio/COMMAND_ID/output.mp4",
  "storage_url": null,
  "is_deleted": false
}

For a private bucket, storage_url is null; use external_object_key with your own S3 SDK or delivery layer. If public_base_url was configured, storage_url contains the corresponding public or CDN URL.

Manage destinations

MethodPathDescription
GET/api/v1/storage-destinationsList destinations.
POST/api/v1/storage-destinationsCreate a destination.
GET/api/v1/storage-destinations/:storageDestinationIdGet a destination.
PATCH/api/v1/storage-destinations/:storageDestinationIdUpdate its name, prefix, public URL, path style, or credentials.
DELETE/api/v1/storage-destinations/:storageDestinationIdDisable it for future jobs. Existing bucket objects are not deleted.
POST/api/v1/storage-destinations/:storageDestinationId/testTest write, verification, and cleanup.

All endpoints require X-API-KEY authentication and a Business account. A destination can only be used by the account that created it.

On this page