Webhooks

Kazinex Workflows can send real-time HTTP POST notifications to external systems when key events occur. This enables you to integrate Workflows with project management platforms, BI dashboards, custom notification systems, and automation pipelines — without polling the API.
How webhooks work
When a configured event occurs in Workflows:
- Workflows sends an HTTP POST request to your configured endpoint URL.
- The request body is a JSON payload describing the event and the affected record.
- A cryptographic signature header (
X-Kazinex-Signature) is included so your server can verify the request is genuine. - Your server should respond with HTTP
200 OKwithin 10 seconds. - If the response is not
200, Workflows retries automatically (see Retry policy).
Configuring a webhook endpoint
- Go to Settings → Webhooks (project-level or org-level).
- Click Add Endpoint.
- Fill in the endpoint form:
| Field | Description |
|---|---|
| Endpoint URL | The HTTPS URL your server will receive POST requests at. Must use HTTPS. |
| Description | A label for this endpoint (e.g., Procore Sync, BI Dashboard Trigger). |
| Secret | A string you define. Workflows uses it to compute the HMAC-SHA256 signature. Store this securely. |
| Events | Select which events trigger this endpoint. See Event types. |
| Active | Toggle the endpoint on or off without deleting it. |
- Click Save Endpoint.
- Use Send Test to fire a sample payload to your endpoint immediately and verify it is reachable.
Event types
| Event key | When it fires | Main payload fields |
|---|---|---|
workflow.created | A workflow instance is started | workflow_id, document_id, template_id, started_by, started_at |
workflow.completed | The final step of a workflow is completed | workflow_id, document_id, final_decision, completed_at, duration_hours |
workflow.step_completed | Any individual step is completed | workflow_id, step_id, step_name, step_type, assignee_id, action, responded_at, on_time |
document.created | A new document is uploaded to the register | document_id, document_number, title, revision, uploaded_by, created_at |
document.status_changed | A document status changes | document_id, document_number, previous_status, new_status, changed_by, changed_at |
transmittal.issued | A transmittal is issued to recipients | transmittal_id, transmittal_number, subject, purpose, issued_by, issued_at, recipient_count |
transmittal.acknowledged | A recipient acknowledges a transmittal | transmittal_id, transmittal_number, recipient_name, recipient_email, acknowledged_at |
Payload schema
All webhook payloads share a common envelope:
{
"event": "workflow.completed",
"event_id": "evt_01HXY2Z9...",
"timestamp": "2025-06-01T14:32:00Z",
"project_id": "proj_abc123",
"project_name": "Demo Infrastructure Project",
"data": {
// event-specific fields
}
}
Example: workflow.completed
{
"event": "workflow.completed",
"event_id": "evt_01HXY2Z9abc",
"timestamp": "2025-06-01T14:32:00Z",
"project_id": "proj_abc123",
"project_name": "Demo Infrastructure Project",
"data": {
"workflow_id": "wf_00112",
"document_id": "doc_00456",
"document_number": "DEMO-CIV-DWG-001",
"document_title": "Site Plan - Area A",
"revision": "B",
"template_id": "tmpl_0099",
"template_name": "Technical Review - Standard v2",
"final_decision": "approved",
"completed_at": "2025-06-01T14:32:00Z",
"duration_hours": 72
}
}
Example: document.status_changed
{
"event": "document.status_changed",
"event_id": "evt_01HXY2Z9def",
"timestamp": "2025-06-01T14:32:01Z",
"project_id": "proj_abc123",
"project_name": "Demo Infrastructure Project",
"data": {
"document_id": "doc_00456",
"document_number": "DEMO-CIV-DWG-001",
"document_title": "Site Plan - Area A",
"revision": "B",
"previous_status": "under_review",
"new_status": "approved",
"changed_by": "j.smith@example.com",
"changed_at": "2025-06-01T14:32:01Z"
}
}
Verifying the signature
Workflows includes an X-Kazinex-Signature header with every request. Use this to verify the payload has not been tampered with.
Algorithm: HMAC-SHA256
Input: Raw request body as a UTF-8 byte string
Key: Your endpoint secret
Header format: sha256=<hex_digest>
Node.js verification example
const crypto = require('crypto');
function verifySignature(rawBody, secret, signatureHeader) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(rawBody, 'utf8')
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signatureHeader),
Buffer.from(expected)
);
}
Security: Always verify the signature before processing any webhook payload. Reject any request where the signature does not match. Use a timing-safe comparison to prevent timing attacks.
Retry policy
If your endpoint does not return HTTP 200 OK within 10 seconds, Workflows retries the delivery:
| Attempt | Delay after previous attempt |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
After 3 failed retries, the event delivery is marked Failed and no further retries are attempted. The failed delivery appears in the webhook delivery log (see Monitoring deliveries).
Workflows does not retry on HTTP 4xx responses (these indicate a permanent failure, such as invalid endpoint configuration).
Monitoring deliveries
- Go to Settings → Webhooks → [Endpoint name] → Delivery Log.
- The log shows all delivery attempts for the past 30 days:
| Column | Description |
|---|---|
| Event | The event type fired |
| Timestamp | When the event occurred |
| Status | Success (200), Failed, Pending |
| Response code | The HTTP status code your server returned |
| Duration (ms) | How long your server took to respond |
- Click any row to see the full payload that was sent and your server's response body.
- Use Resend on a failed event to manually retry the delivery.
Failure handling
If webhook deliveries are consistently failing:
- Check that your endpoint URL is correct and accessible from the internet.
- Ensure your server responds within 10 seconds (process asynchronously if needed — accept the webhook, queue the work, return 200 immediately).
- Verify your firewall allows inbound HTTPS from Kazinex Workflows IP ranges (contact support for the current IP list).
- Check the response code in the delivery log — a
401suggests a signature mismatch or auth issue; a404suggests a routing problem; a5xxsuggests a server error.
Security recommendations
- Use HTTPS endpoints only (HTTP endpoints are rejected).
- Rotate your endpoint secret every 90 days. Update the secret in Settings before rotating on your server to avoid downtime.
- Only subscribe to events you actively consume. Unused subscriptions waste resources and add noise to your delivery log.
- Do not expose your endpoint secret in client-side code or public repositories.