Automotion docs
API

Webhooks

Receive signed render.completed / render.failed callbacks and verify the X-Automotion-Signature header.

Instead of polling, pass a webhook_url when creating a render (paid plans only — on the trial, webhook_url answers WEBHOOKS_NOT_ALLOWED). Automotion calls your URL once per render with the terminal state.

Events and payload

Two events exist: render.completed and render.failed. The body is byte-identical across delivery attempts:

webhook payload
{
  "id": "evt_rnd_123_completed",
  "event": "render.completed",
  "createdAt": "2026-07-18T13:00:00.000Z",
  "render": {
    "id": "rnd_123",
    "status": "done",
    "outputUrl": "https://cdn.automotion.dev/renders/rnd_123.mp4",
    "error": null,
    "draft": false,
    "watermark": false,
    "durationSec": 8,
    "expiresAt": "2026-10-16T13:00:00.000Z",
    "createdAt": "2026-07-18T12:58:41.000Z"
  }
}

Request headers:

HeaderMeaning
Content-Typeapplication/json
X-Automotion-Signaturet=<unix seconds>,v1=<hex HMAC> — verify this
X-Automotion-EventThe event name
X-Automotion-DeliveryUnique delivery id (changes per attempt)

id is a stable consumer dedupe key (evt_<renderId>_<event>): store it and ignore repeats — delivery is at-least-once.

Retries

On a non-2xx response or timeout (10 s), delivery retries up to 5 attempts with backoff delays of 1, 5, 25, 125, 625 seconds after each failure. Answer 2xx quickly (enqueue your own processing) to avoid retries. URLs must be publicly resolvable — private/internal addresses are rejected outright (URL_NOT_ALLOWED) and are not retried.

Verifying the signature

Your webhook signing secret (whsec_…) lives in the dashboard and can be rotated there at any time. The signature is computed over the raw request body:

v1 = HMAC_SHA256(secret, "<t>.<rawBody>")

Reject deliveries whose timestamp is more than 5 minutes off your clock (replay protection), and compare digests in constant time.

The exact helper the platform itself tests against ships with the Automotion TypeScript packages:

verify.ts
import { verifyWebhookSignature } from "@automotion/sdk";
 
// In your HTTP handler — rawBody must be the UNPARSED request body string.
const valid = verifyWebhookSignature({
  rawBody,
  header: request.headers["x-automotion-signature"],
  secret: process.env.AUTOMOTION_WEBHOOK_SECRET, // whsec_…
  toleranceSec: 300, // default
});
 
if (!valid) {
  response.statusCode = 401;
  return;
}
const payload = JSON.parse(rawBody);

verifyWebhookSignature never throws and compares in constant time. Parse the JSON only after verification, and always verify the raw bytes — a re-serialized body will not match the signature.

Checklist

  1. Verify the signature against the raw body before trusting anything.
  2. Dedupe on the payload id (evt_<renderId>_<event>).
  3. Respond 2xx fast; do heavy work asynchronously.
  4. Treat render.failed as terminal — render.error.code explains why (error catalog).
  5. Rotate the secret from the dashboard if it ever leaks; rotation replaces the old secret immediately.

On this page