RenderIO
Api referenceWebhooks

Webhook Payload

Understand the webhook delivery format, signature verification, retry schedule, and auto-disable behavior.

Webhook Payload

This page describes the format and behavior of webhook deliveries. Webhooks are not a separate API endpoint you call -- instead, RenderIO sends HTTP POST requests to your configured URL when commands complete.

Delivery format

When a command finishes processing (either SUCCESS or FAILED), RenderIO sends a POST request to your webhook URL with the following payload:

{
  data: CommandPollResponse;
  timestamp: number;
}
FieldTypeDescription
dataCommandPollResponseThe full command result, identical to what GET /api/v1/commands/:commandId returns.
timestampnumberUnix timestamp (in milliseconds) of when the webhook was dispatched.

Headers

Every webhook delivery includes the following headers:

HeaderValueDescription
Content-Typeapplication/jsonThe payload is always JSON.
User-AgentRenderIO-Webhook/1.0Identifies the request as a RenderIO webhook delivery.
X-Webhook-SignaturestringHMAC-SHA256 hex digest of the request body. Only present if you configured a signing secret.

Signature verification

If you set a secret when configuring your webhook, every delivery includes an X-Webhook-Signature header. The signature is computed as an HMAC-SHA256 hex digest of the raw JSON request body using your secret as the key.

Always verify the signature before processing the payload to ensure the request genuinely came from RenderIO.

Node.js verification example

import crypto from "node:crypto";

function verifyWebhookSignature(body, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(body)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(signature, "hex"),
    Buffer.from(expected, "hex"),
  );
}

// In your webhook handler:
app.post("/webhooks/renderio", (req, res) => {
  const rawBody = req.rawBody; // raw request body as string
  const signature = req.headers["x-webhook-signature"];
  const secret = process.env.RENDERIO_WEBHOOK_SECRET;

  if (!verifyWebhookSignature(rawBody, signature, secret)) {
    return res.status(401).send("Invalid signature");
  }

  const { data, timestamp } = JSON.parse(rawBody);
  console.log(`Command ${data.command_id} finished with status: ${data.status}`);

  // Process the webhook payload...

  res.status(200).send("OK");
});

Python verification example

import hashlib
import hmac
import os
import json

def verify_webhook_signature(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode("utf-8"),
        body,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(signature, expected)

# In your webhook handler (Flask example):
@app.route("/webhooks/renderio", methods=["POST"])
def handle_webhook():
    raw_body = request.get_data()
    signature = request.headers.get("X-Webhook-Signature", "")
    secret = os.environ["RENDERIO_WEBHOOK_SECRET"]

    if not verify_webhook_signature(raw_body, signature, secret):
        return "Invalid signature", 401

    payload = json.loads(raw_body)
    data = payload["data"]
    print(f"Command {data['command_id']} finished with status: {data['status']}")

    # Process the webhook payload...

    return "OK", 200

Successful delivery

A delivery is considered successful when your endpoint returns any 2xx HTTP status code. Any other status code or a connection failure is treated as a failed delivery.

Retry schedule

If a delivery fails, RenderIO retries with exponential backoff. The retry intervals are:

AttemptDelay after failure
1Immediate
25 seconds
35 minutes
430 minutes
52 hours
65 hours
710 hours
810 hours

After 8 consecutive failed attempts, the webhook is auto-disabled.

Auto-disable behavior

When a webhook accumulates 8 consecutive delivery failures, RenderIO automatically deactivates it:

  • The is_active field is set to false
  • The disabled_at timestamp is recorded
  • No further deliveries are attempted until you re-enable the webhook

To re-enable a disabled webhook, call PUT /api/v1/webhook-config with your URL. This resets the failure counter and reactivates delivery.

You can check the current failure count and status at any time with GET /api/v1/webhook-config.

Per-command webhook URL

In addition to the account-level webhook configuration, you can specify a webhook_url on individual command requests (e.g., in the body of POST /api/v1/run-ffmpeg-command or POST /api/v1/presets/:presetId/execute). When set, this per-command URL overrides the global webhook configuration for that specific command.

Per-command webhook URLs use the same payload format and signature verification as the global webhook. However, they do not affect the global failure counter or auto-disable behavior.

On this page