API reference
Webhooks
DunOps can push events to your systems in real time — run completed, approval requested, provider connected.
Setting up a webhook
Go to Settings → Webhooks → Add endpoint. Enter your HTTPS URL and select which events to subscribe to. DunOps sends a POST request to your endpoint for every matching event.
Note
Your endpoint must respond with a 2xx status within 10 seconds. DunOps retries failed deliveries up to 5 times with exponential backoff.
Event types
| Event | When it fires |
|---|---|
run.started | A playbook run begins |
run.step.completed | A single step in a run finishes |
run.approval_required | A step is waiting for human approval |
run.completed | The entire run finishes (success or failure) |
provider.connected | A provider is successfully connected |
provider.disconnected | A provider is removed |
Payload shape
Example: run.completed
{
"event": "run.completed",
"workspace_id": "ws_abc",
"timestamp": "2026-06-17T12:05:00Z",
"data": {
"run_id": "run_5678",
"playbook_id": "pb_1234",
"playbook_name": "Deploy storefront to prod",
"status": "succeeded",
"duration_ms": 4200
}
}Verifying the signature
Every webhook request includes a X-DunOps-Signature header — an HMAC-SHA256 signature of the raw request body, keyed with your webhook secret. Always verify it before processing.
Verify signature (Node.js)
import crypto from "node:crypto";
function isValidSignature(body: string, header: string, secret: string) {
const expected = crypto
.createHmac("sha256", secret)
.update(body)
.digest("hex");
const actual = header.replace("sha256=", "");
return crypto.timingSafeEqual(
Buffer.from(expected, "hex"),
Buffer.from(actual, "hex"),
);
}Warning
Use
timingSafeEqual — a plain string comparison is vulnerable to timing attacks.