Skip to navigation

Webhooks

View as Markdown

Subscribe to webhooks to receive events at a URL you control, instead of polling. Each delivery is an HTTP POST with a JSON body, retried on failure. Subscribe from your organisation’s settings, or through the API.

Subscribing through the API

Zapier, Make, Power Automate and your own scripts can manage subscriptions with the webhooks endpoints (REST-hook style). The caller must be an organisation admin and the organisation’s plan must include API integrations; otherwise the endpoints answer 403 or 402.

  1. GET /api/v2/webhooks/events lists the event names you can subscribe to, grouped by category.
  2. POST /api/v2/webhooks with a url and subscribed_actions creates the subscription and returns it with its signing_secret. Unknown event names are dropped; check the returned subscribed_actions.
  3. DELETE /api/v2/webhooks/{id} unsubscribes.
{
"name": "Zapier: new work orders",
"url": "https://hooks.zapier.com/hooks/catch/1/abc",
"subscribed_actions": ["work_order_created", "form_completed"]
}

Subscriptions created this way appear in Settings › Webhooks alongside the rest, deliver through the same path and carry the same signature headers. GET /api/v2/webhooks lists them all, including subscriptions created in settings, so an integration can find an existing one instead of creating a duplicate.

A webhook whose deliveries keep failing is deactivated automatically (active: false) and stops receiving events. Reactivate it from Settings › Webhooks once the endpoint is healthy, and use the webhook_deliveries endpoints to inspect and retry the failed deliveries.

Verifying a delivery

Every request carries two headers:

  • X-Webhook-Signature — an HMAC-SHA256 hex digest of the raw request body, keyed with your webhook’s signing secret.
  • X-Webhook-Timestamp — when the event occurred (ISO 8601).

Recompute the signature over the exact bytes you received and compare before trusting the payload:

expected = OpenSSL::HMAC.hexdigest("SHA256", signing_secret, raw_request_body)
# constant-time compare expected against the X-Webhook-Signature header

Payload

Every delivery has the same envelope: the event’s id, action and created_at, the organisation, the creator who caused it, and the subject it happened to (type and id, plus deleted: true when the record no longer exists). One extra key, named after the subject, carries a snapshot of the record in the same shape the API returns it: work_order, work_order_task, work_order_template, form, report_export, defect, asset, location, company, tool, action_item or work_instruction.

{
"id": "019e7df6-ab7f-...",
"action": "work_order_created",
"created_at": "2026-05-31T12:16:19Z",
"organisation": { "id": "01946a36-84da-..." },
"creator": { "id": "019469dc-ef01-...", "name": "Jane Smith" },
"subject": { "type": "WorkOrder", "id": "01946a34-219e-..." },
"work_order": { "...": "the work order as GET /api/v2/work_orders/{id} returns it" }
}

Events

The full list is available from GET /api/v2/webhooks/events. Categories: work orders, work order tasks, work order templates, reports (form_*), defects, reviews, assets, locations, companies, tools, actions, notes, documents, work instructions and exports.

report_export_completed

Fired when a report export finishes building (see the Create a report export endpoint). The payload carries a short-lived, signed download_url — fetch it promptly. The event covers every report export in your organisation; filter on report_export.exportable or creator if you only want some of them.

{
"action": "report_export_completed",
"created_at": "2026-05-31T12:16:19Z",
"organisation": { "id": "01946a36-84da-..." },
"creator": { "id": "019469dc-ef01-...", "name": "Jane Smith" },
"report_export": {
"id": "019e7df6-ab7f-...",
"status": "completed",
"format": "pdf",
"exportable": { "type": "Form", "id": "01946a34-219e-..." },
"created_at": "2026-05-31T12:16:18Z",
"completed_at": "2026-05-31T12:16:19Z",
"download_url": "https://..."
}
}