Skip to main content
Webhook deliveries are wakeups, not data. The payload tells you that new events are readable on the feed; it never carries event contents. On receiving one, poll GET /api/v1/events from your last cursor — see the events & webhooks overview for the feed model.

The wakeup payload

Deliveries are an HTTPS POST to your subscription URL with a minimal JSON body:
  • latestCursor is the highest feed cursor readable at send time — if it is beyond the last cursor you processed, you have events to fetch.
  • eventCount is how many events were promoted in the batch that triggered this wakeup, and entities summarizes which entity families they touch. Both are hints for scheduling, not a contract: always resume from your own cursor rather than counting.

Request headers

Verifying signatures

Compute HMAC-SHA256 over the literal string <timestamp>.<rawBody> — the timestamp from X-Webhook-Timestamp, a dot, then the raw request body bytes (before any JSON parsing) — using the signing secret returned when the subscription was created (or last rotated). Compare against the hex digest after the sha256= prefix using a constant-time comparison.
Receivers must verify the signature and should reject timestamps older than 5 minutes.

Endpoint requirements

  • The subscription URL must be HTTPS, on a host present in your API key’s webhook allowed hosts allowlist. The allowlist is fail-closed: while it is empty, no subscription URL is accepted and no deliveries are attempted.
  • The URL is re-validated against the allowlist at delivery time, not just at subscription time.
  • Respond with a 2xx status within 10 seconds. Anything else — timeout, non-2xx, connection failure — counts as a failed delivery.
  • Return quickly: acknowledge first, then poll the feed asynchronously. Doing feed processing inline in the webhook handler is the most common cause of timeouts.

Retry semantics

Wakeups are best-effort and lossy by design. There is no delivery queue to drain and no replay endpoint — none is needed, because the event feed is the source of truth and cursor-resume makes a missed wakeup harmless. Poll GET /api/v1/events on every wakeup and on your own schedule (we recommend at least every 5 minutes) regardless of webhook health. Because the polling loop is your source of truth, it also doubles as your health check: if wakeups stop arriving but the feed keeps advancing, your endpoint (or its allowlist entry) needs attention.