Subscribe to RunTight events and receive a signed HTTP POST within about a minute of each one. Ideal for connecting to Zapier, Make, n8n, or your own integration services.
Go to Settings → Webhooks in your RunTight dashboard (admin role, Pro plan required). Click Add Webhook, enter a name and URL, optionally set a secret for HMAC verification, and check the events you want to receive.
wo.createdA new work order is created — in the app, through the API, from an email or request, or from a PM schedule.
wo.completedA work order's status changes to completed. Fires again if a reopened work order is completed again.
wo.overdueAn open or in-progress work order passes its due date, in your workspace's timezone. Fires once per WO.
pm.dueA work order is generated from a PM schedule — automatically or by a planner. A wo.created event is sent for it too.
asset.createdNew equipment is added to your tenant.
Every webhook delivers a JSON body with five top-level fields. id identifies the event and stays the same if it is retried; timestamp is when the event happened.
{
"id": "event-uuid",
"event": "wo.completed",
"tenant_id": "tenant-uuid",
"timestamp": "2026-04-11T18:45:12.123Z",
"data": {
"work_order_id": "wo-uuid",
"title": "Weekly Hydraulic Press Inspection",
"priority": "high",
"due_date": "2026-04-11",
"completed_at": "2026-04-11T18:45:10.567Z",
"time_spent_minutes": 35,
"asset_id": "asset-uuid"
}
}The data field varies by event type:
Content-Type: application/json User-Agent: RunTight-Webhooks/1.0 X-Webhook-Event: wo.completed X-Webhook-Id: event-uuid (same as the body's id) X-Webhook-Signature: sha256=HEX_HMAC (only if secret configured)
If you configure a secret on a webhook, every request includes an X-Webhook-Signature header containing an HMAC-SHA256 hex digest of the raw request body.
Node.js example
import crypto from "crypto";
function verifySignature(body, signatureHeader, secret) {
const expected = "sha256=" + crypto
.createHmac("sha256", secret)
.update(body)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader)
);
}
// In your webhook handler:
const rawBody = await request.text();
const signature = request.headers.get("x-webhook-signature");
if (!verifySignature(rawBody, signature, process.env.WEBHOOK_SECRET)) {
return new Response("Invalid signature", { status: 401 });
}
const payload = JSON.parse(rawBody);id to ignore duplicates.timestamp if order matters.