Workflow webhooks
Workflow webhooks send a signed HTTPS request when a workflow notification runs. Use them to send Sift events to an internal service, automation tool, or data pipeline.
At a glance
| Available to Super Admins | ✅ |
| Public HTTPS endpoints | ✅ required |
| Multiple destinations per notification | ✅ |
| Generated signing secret | ✅ shown once |
| Test, disable, rotate, and delete controls | ✅ |
| Automatic retries for temporary failures | ✅ for up to 24 hours |
| Exactly-once delivery or strict ordering | ❌ |
Set it up
- Go to Settings → Workflows.
- Open Notifications and create or edit a notification.
- Select Manage webhooks in the destination section.
- Enter a name and a public HTTPS endpoint.
- Copy the signing secret. Sift shows it only once.
- Select the webhook destination and save the notification.
Use Send test before you save the notification. The endpoint must return a status from 200 through 299.
Request format
Sift sends a JSON envelope. The data object contains the workflow notification.
{
"subjectType": "workflow_webhook",
"subjectId": "organization",
"orgId": "org_...",
"deliveredAt": "2026-09-01T18:02:11.000Z",
"data": {
"id": "workflow-notification:...",
"type": "workflow.notification",
"version": 1,
"occurredAt": "2026-09-01T18:02:11.000Z",
"orgId": "org_...",
"message": "Optional custom message",
"workflow": {
"id": "wf_...",
"executionId": "wfx_...",
"triggerId": "trg_...",
"name": "Escalate buying signals"
},
"action": {
"id": "act_...",
"easyId": "ACME-1842",
"status": "OPEN",
"queueId": "queue_...",
"assigneeId": null,
"platform": "x"
}
}
}action.status is the operational status of the case, as shown in the inbox: OPEN, RESPONDED, WAITING_FOR_USER, RESOLVED, CLOSED, DISMISSED, SNOOZED, or a custom status token such as CUSTOM_STATUS_1. It is null when the case has no operational status. action.easyId is the case ID with your organization prefix, as shown in the app.
Fields can be absent when they do not apply to the action or workflow. Additive fields can appear in version 1. Use the version field before you depend on a new payload version.
Verify the signature
Sift signs the exact request body with HMAC-SHA256. The signature uses the secret shown when you create or rotate the destination.
X-Sift-Signature: sha256=<hex digest>
X-Sift-Subject-Type: workflow_webhook
X-Sift-Idempotency-Key: <stable delivery key>Verify the raw body before you parse JSON. This Node.js example uses a timing-safe comparison.
import { createHmac, timingSafeEqual } from "node:crypto"
export function verifySiftWebhook(rawBody, signature, secret) {
const expected = Buffer.from(
`sha256=${createHmac("sha256", secret).update(rawBody).digest("hex")}`
)
const received = Buffer.from(signature ?? "")
return received.length === expected.length && timingSafeEqual(received, expected)
}Reject the request if the signature is missing or invalid. Rotate the secret if you think it was exposed. Old signatures stop working after rotation.
Delivery and retries
Sift uses at-least-once delivery. Your endpoint can receive the same event more than once. Store the X-Sift-Idempotency-Key value and ignore a key that you already processed.
Sift retries network failures, timeouts, 408, 425, 429, and 5xx responses for up to 24 hours. Other 4xx responses are terminal. Return a 2xx response only after your system accepts the event.
Endpoint safety
Webhook endpoints must use HTTPS and resolve only to public addresses. Sift rejects URLs with credentials, private or reserved addresses, mixed public and private DNS results, and redirects.
Tips
- Keep the signing secret in your secret manager.
- Respond quickly. Process long work after you return a
2xxresponse. - Use the idempotency key as the unique key for your handler.
- Disable the destination before planned endpoint maintenance if you do not want retries.
- Rotate the secret after a team member or integration loses access.