Skip to content
PlatformWebhooks & async

Webhooks & async

For slow pages or large batches, run a render with async: true and let RenderKit POST the result to your server when it's ready. No polling loops, no held-open connections. Available on hobby and up.

Submitting an async render

Add async: true, a webhook_url, and a webhook_secret to any render request. You get a 202 with a job immediately.

POST /v1/screenshot
curl https://api.renderkit.tech/v1/screenshot \
  -H "x-api-key: $RK_KEY" -H "Content-Type: application/json" \
  -d '{
    "url": "https://a-very-slow-page.example",
    "full_page": true,
    "async": true,
    "webhook_url": "https://api.yourapp.com/hooks/renderkit",
    "webhook_secret": "whsec_…"
  }'

The webhook payload

When the render finishes we POST JSON to your webhook_url. The event is render.done on success or render.failed on error.

POST → your webhook_url
{
  "id": "rnd_8fk2m1c4",
  "event": "render.done",
  "result": {
    "status": "done",
    "url": "https://cdn.renderkit.tech/renders/3a7b9c…e9.png",
    "content": null,
    "render_ms": 842,
    "meta": { "width": 1440, "height": 4860, "format": "png" }
  },
  "timestamp": "2026-06-14T10:24:01.000Z"
}
event: render.failed
{
  "id": "rnd_8fk2m1c4",
  "event": "render.failed",
  "error": { "code": "TIMEOUT", "message": "Upstream timed out" },
  "timestamp": "2026-06-14T10:24:31.000Z"
}

Verifying the signature

Each delivery includes an X-RenderKit-Signature header: the HMAC-SHA-256 of the raw request body, keyed with your webhook_secret, hex-encoded. Recompute it and compare in constant time before trusting the payload.

verify.js
import crypto from "node:crypto";

function verify(rawBody, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(rawBody) // the exact bytes received, before JSON.parse
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected),
  );
}

Sign the raw body

Compute the HMAC over the raw bytes you received, not a re-serialized object — key order and whitespace must match exactly. Respond 2xx quickly; do heavy work after acknowledging.

Retries

If your endpoint doesn't return a 2xx, delivery is retried on a backoff schedule of roughly 30s → 5m → 30m. Make your handler idempotent — key off the render id.