How a Sanity webhook works
Webhooks are created per project in the API section of the project settings at sanity.io/manage, and can also be managed through the CLI or the project APIs. Draft and version triggers are opt-in settings.
Two GROQ parts shape each webhook. The filter, the part between *[ and ] in a query, decides which document changes trigger the webhook, and an empty filter matches all documents. The projection defines the request body, so the receiver gets only the fields it needs. Without a projection, the payload is the whole document as it looks after the change. Filters and projections cannot use sub-queries, so a webhook cannot pull in related documents through a nested query.
The HTTP method is configurable: POST, PUT, PATCH, DELETE or GET. The Webhooks API offers document webhooks, with one call per changed document, and transaction webhooks, with one call per transaction. Sanity prefers document webhooks.
Delivery, security and reliability
At-least-once delivery. Receivers should de-duplicate with the
idempotency-keyheader sent on every request.Signed payloads. With a secret set, Sanity signs each payload and sends the result in a
sanity-webhook-signatureheader. The secret itself is never sent. The signature is an HMAC-SHA256 over the timestamp and the raw request body, so it must be checked before the body is parsed. The@sanity/webhookpackage providesisValidSignatureand Express-style middleware to verify signed requests.One request at a time. Each webhook sends requests one by one, so a slow endpoint makes the delivery queue fall behind. A request times out after 30 seconds, so handlers should acknowledge fast and process asynchronously.
Retries. Failed deliveries with a 429 or 500-range response are retried twice, 30 seconds apart. Responses in the 400 range are not retried.
Sanity advises against relying on webhooks alone and recommends periodic sync jobs filtered on _updatedAt. The Sanity webhooks documentation covers each setting. For the platform itself, read what Sanity is and how it works, or compare it in Sanity vs Contentful.
How Pagepro uses Sanity webhooks
In translation pipelines from Pagepro's Sanity development team, a webhook listens to every base-language publish. The translation agent runs only when a target-language draft already exists, and only on the fields that were edited, which keeps token costs bounded. So creating that draft is the editor's explicit opt-in.
Sources
- GROQ-powered webhooksSanity · sanity.io
- Webhooks API referenceSanity · sanity.io
- Webhook best practicesSanity · sanity.io
- @sanity/webhook (webhook toolkit)Sanity · github.com