Skip to content
roasOS API
Esc
navigateopen⌘Jpreview
On this page

Webhooks

Get a callback when a job finishes, instead of polling.

Instead of polling for a result, you can have roasOS POST to your server when a job completes.

Set it up

Pass a webhook_url when you confirm a generation:

{
  "type": "image",
  "prompt": "...",
  "model": "nano-banana-pro",
  "quote_id": "...",
  "webhook_url": "https://your-app.com/roasos/webhook"
}

When the job finishes, we POST the result to that URL.

Verify every delivery

Each request includes three headers:

  • X-RoasOS-Signaturev1=<hex>, an HMAC-SHA256 signature.
  • X-RoasOS-Timestamp — unix seconds when the signature was made.
  • X-RoasOS-Delivery-Id — a stable id, the same across retries. Use it to skip duplicates.

To confirm a request really came from us:

  1. Check the timestamp is recent (e.g. within 5 minutes) to block replays.
  2. Compute HMAC_SHA256(secret, timestamp + "." + rawBody) as lowercase hex, using the raw request body and your key’s webhook secret.
  3. Compare it to the v1= value with a constant-time comparison.
import crypto from "node:crypto";

function verify(rawBody, headers, secret) {
  const timestamp = headers["x-roasos-timestamp"];
  const signature = headers["x-roasos-signature"].replace("v1=", "");
  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${timestamp}.${rawBody}`)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected),
  );
}

Handle retries

Deliveries are at-least-once — you may get the same event more than once. Dedupe on X-RoasOS-Delivery-Id and make your handler idempotent.

Was this page helpful?