Prerequisites
- A Keystone 5 application in the Condo monorepo
- PostgreSQL database with migrations support
- Redis (used by the Bull task queue that drives webhook delivery)
Set required environment variables
The Encryption config notes:
The object key in
WebhookPayload schema stores the request body and signing secret as encrypted text. The encryption manager is instantiated at module-load time, so both variables must be present in every environment — development, CI/CD, and production — including during database migrations.| Field | Value |
|---|---|
algorithm | aes-256-gcm |
secret | Exactly 32 characters |
compressor | brotli |
keyDeriver | pbkdf2-sha512 |
DATA_ENCRYPTION_CONFIG (e.g. myapp_1) must match the value of DATA_ENCRYPTION_VERSION_ID. For local development, bin/prepare.js generates these values automatically.Register webhook schemas
In your Keystone entry point, import
getWebhookModels and add the returned schemas after all domain schemas that use webHooked(). The WebhookSubscription.model field is built from the list of already-registered models at call time.getWebhookModels accepts an optional second argument — an array of custom event type strings:Apply the webHooked plugin to models
For each model you want to observe, import and apply the The plugin registers the model name and wraps the existing
webHooked plugin:afterChange hook to enqueue a sendModelWebhooks task after every mutation.Managing webhooks via the admin UI
Once the schemas are registered, you can manage webhooks through the Keystone admin panel at/admin:
- Create a Webhook — give it a name, set the target URL, and assign a service user whose session will be used to fetch payload data.
- Create a WebhookSubscription — link it to the webhook, choose the model, write the
fieldsstring in GraphQL field-selection syntax (e.g.id status updatedAt property { address }), and optionally addfiltersto narrow which records trigger delivery. - Monitor WebhookPayload records to inspect delivery status, HTTP response codes, and error messages.
Subscription field reference
| Field | Type | Description |
|---|---|---|
webhook | Relationship | Parent Webhook integration config |
url | URL | Override URL (takes precedence over webhook.url) |
model | Select | The model to subscribe to (must be registered with webHooked()) |
fields | Text | GraphQL field-selection string for the payload |
filters | JSON | Where-input filters; only matching records are delivered |
maxPackSize | Integer | Max objects per request (1–100, default 100) |
syncedAt | DateTime | Timestamp of the last successful sync |
failuresCount | Integer | Consecutive delivery failures; resets to 0 on success |
failuresCount increments at most once per hour. Once it reaches the threshold (default 10), delivery is paused and must be manually reset via the admin UI or support.