Browse documentation
Integrate

Webhooks

Event notification - subscribing to what happens in a deployment, verifying what you receive, and building a receiver that survives production.

Webhooks let a deployment tell your system that something happened, instead of your system asking repeatedly whether anything has. They are the right tool whenever your reaction should be prompt and the event is infrequent relative to how often you would otherwise poll.

Typical subscriptions

  • a financial transaction posted, or a period closed
  • an approval granted, rejected or escalated
  • a payment or disbursement completing
  • stock falling below reorder level
  • a goods receipt posted, or a transfer arriving
  • a stock-count variance exceeding tolerance
  • a record reaching a particular status in a workflow

Which events a deployment publishes depends on the modules it runs; the operator provides the list when your subscription is set up.

How delivery works

Your endpoint receives an HTTP POST carrying an event type, an event identifier, a timestamp and a payload. Delivery is at least once - that is the only guarantee any webhook system can honestly make - so your receiver must tolerate duplicates.

Failed deliveries are retried with increasing backoff. Persistent failure eventually stops delivery and raises the problem with the operator rather than retrying silently forever.

Verifying what you receive

Every payload is signed with a secret shared when your subscription is created, along with a timestamp.

Verify the signature before parsing anything else. An unverified webhook endpoint is an unauthenticated write into your system, and anyone who learns the URL can call it.

Reject stale timestamps. A valid signature on an old payload is a replay; a tolerance window of a few minutes closes it.

Keep the secret out of your repository, and rotate it if it is ever exposed.

Building a receiver that survives production

Be idempotent. Record the event identifier and ignore one you have already processed. This is not optional - retries and duplicates will happen.

Acknowledge fast, process afterwards. Return 2xx as soon as you have stored the event, and do the real work asynchronously. Doing the work first turns any slowness on your side into a sender timeout and another delivery attempt.

Do not assume ordering. Events can arrive out of order. Where sequence matters, use the timestamp and identifiers in the payload rather than arrival order.

Treat the payload as a notification, not as the record. For anything sensitive or material, use the event as a prompt to fetch the current state over REST or GraphQL. The authoritative value is the one you read back, not the one that was pushed.

Return errors honestly. A 5xx tells the sender to retry. Returning 200 for something you failed to process means the event is gone.

Monitor your endpoint. Silence is ambiguous - it means either nothing happened or your receiver has been failing since Tuesday.

What is deliberately not in a payload

Payloads carry identifiers and event metadata, and keep sensitive content to a minimum. Where the detail matters, you fetch it over an authenticated interface. This keeps sensitive data out of a channel that terminates on infrastructure the deployment’s operator does not control.

Setting one up

Subscriptions are configured by the operator of the deployment. You will need to provide an HTTPS endpoint, the events you want, and a contact for delivery failures - and you will receive the signing secret and the payload specification for those events.

If you are evaluating d1kit for a build of your own, get in touch.

Last reviewed July 2026.

Something wrong or missing on this page? Tell us - the docs are maintained alongside the framework.