SiftDocs
Automate

Webhooks

Webhooks send a signed HTTPS request to your server when something happens in Sift. An endpoint can subscribe to action events, such as a tag added or a status change. A notification rule can also send to an endpoint.

At a glance

Available to Super Admins✅
Public HTTPS endpoints✅ required
Subscribe to action events✅ tags, status, assignee, work queue, fields, forms, moderation
Only for actions matching a saved search✅ optional
Send from notification rules✅
Generated signing secret✅ shown once, 24-hour overlap on rotation
Delivery log, send test, and redeliver✅
Automatic retries for temporary failures✅ for up to 24 hours
Order of events for one action✅ in order per endpoint
Exactly-once delivery❌ at least once

Set it up

  1. Go to Settings → Developer access → Webhooks.
  2. Select New endpoint. Enter a name and a public HTTPS URL, and pick the events to receive.
  3. Copy the signing secret. Sift shows it only once.
  4. Optional: open the endpoint and choose a saved search under Only for actions matching. Events for other actions are not sent.
  5. Select Send test. The endpoint must return a status from 200 through 299.

To send from a rule, open Settings → Workflows → Notifications, edit a notification, and select the endpoint under Webhooks.

Events

EventSent when
action.createdA new action opens
action.tag_added / action.tag_removedA person, rule, AI, or API call changes a tag
action.status_changedThe action's status changes
action.assignedThe assignee changes
action.queue_changedThe action moves to another work queue
action.field_changedA custom field value changes
form.submittedAn action form is submitted
moderation.decidedA moderation decision is recorded
workflow.notificationA notification rule sends to the endpoint
webhook.testYou select Send test

An event request body looks like this. change describes what happened. action is the action's state when Sift built the event; a retry sends the same body.

{
  "id": "evt_qy1b3lsr19x0qjoljxgiys9k",
  "type": "action.tag_added",
  "apiVersion": "2026-11-01",
  "occurredAt": "2026-10-28T18:55:19.175Z",
  "orgId": "org_...",
  "data": {
    "action": {
      "id": "act_...",
      "displayId": "ACME-1842",
      "url": "https://app.getsift.ai/app/record/act_...?entity=action",
      "status": "OPEN",
      "platform": "CUSTOM_API",
      "channel": "social-ai-api-DEV",
      "queueId": "queue_...",
      "assigneeId": null,
      "externalId": "post-184",
      "sourceId": "src_...",
      "tags": [{ "id": "tag_...", "name": "Remove post" }],
      "customFields": []
    },
    "change": {
      "tag": { "id": "tag_...", "name": "Remove post" },
      "actor": { "type": "USER", "id": "user_...", "name": "Dana Kim" }
    }
  }
}

apiVersion is a date. New fields can appear without a new date. A breaking change ships with a new date.

Rule notification format

A notification rule 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",
      "externalId": "feedback-184",
      "sourceId": "src_feedback",
      "customFields": [
        {
          "fieldName": "decision",
          "displayName": "Decision",
          "fieldType": "string",
          "value": "Remove",
          "provenance": { "source": "human", "at": "2026-09-01T18:01:40.000Z" }
        }
      ]
    }
  }
}

action.customFields lists the action's custom field values at the time the workflow fired, one entry per value, with the field's current display name and type. Fields with no value are absent. Only fields registered under Settings → Custom fields appear; Sift's own bookkeeping keys never do. action.externalId is the item's id in the source system and action.sourceId is the Custom API source id; both are null for other platforms. A subscriber can act on a tag change without a second read.

action.status is the operational status of the action, 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 action has no operational status. action.easyId is the action 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

Every request carries Standard Webhooks headers. Use any Standard Webhooks library with the endpoint's signing secret.

webhook-id: evt_...                 (stable for retries; use it to drop duplicates)
webhook-timestamp: 1793210097       (seconds; reject requests older than five minutes)
webhook-signature: v1,<base64> v1,<base64>
x-sift-event: action.tag_added
x-sift-signature: sha256=<hex>      (HMAC-SHA256 of the body, for receivers built before Standard Webhooks)
import { Webhook } from "standardwebhooks"

export function verifySiftWebhook(rawBody, headers, secret) {
  // Throws when the signature or timestamp is wrong.
  return new Webhook(secret).verify(rawBody, headers)
}

Verify the raw body before you parse JSON. After you rotate a secret, the old secret also signs for 24 hours, so webhook-signature can hold two signatures. Accept the request if one matches.

Delivery and retries

Sift sends an event about a second after the change. Delivery is at least once: use webhook-id to drop a duplicate. Events for one action reach an endpoint in the order they happened.

Sift retries network failures, timeouts, 408, 425, 429, and 5xx responses for up to 24 hours. Other 4xx responses are terminal. A 410 Gone turns the endpoint off. Return a 2xx response only after your system accepts the event.

Each endpoint shows its deliveries for the last days. Select Redeliver on a failed event to send the same body again. If every delivery fails for five days, Sift turns the endpoint off and emails your admins. Turn it on again from the endpoint.

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 2xx response.
  • Use webhook-id as the unique key for your handler.
  • Turn the endpoint off before planned maintenance if you do not want retries.
  • Rotate the secret after a team member or integration loses access.

On this page