-
Notifications
You must be signed in to change notification settings - Fork 321
Description
What?
Support web hooks that trigger before and after CRUD operations on an entity.
- Allows an external service to enforce custom business rules.
- Allows centralized validation across multiple APIs or services.
- Enables auditing and compliance logging of data access and mutations.
- Enables integration with messaging or event systems.
- Enables cache invalidation or search index updates after data changes.
- Enables security checks such as fraud detection or policy enforcement.
- Enables observability and telemetry for downstream monitoring systems.
Note
This feature supports any HTTP webhook endpoint, including services that publish events to external systems or HTTP-triggered Azure Functions.
Process flow
sequenceDiagram
participant Client
participant DAB
participant Before as Before Hook
participant DB as Database
participant After as After Hook
Client->>DAB: Request
DAB->>Before: POST
alt stop
Before-->>DAB: stop
DAB-->>Client: Error response
else non-2xx
Before-->>DAB: non-2xx
DAB-->>Client: Error response
else 2xx
Before-->>DAB: Continue
DAB->>DB: CRUD
DB-->>DAB: Result
DAB-->>Client: Response
DAB-->>+After: POST (async)
end
Before
Outbound payload (to the webhook)
{
"action": "create | read | update | delete | execute",
"entity": "Book",
"timestamp": "2026-03-14T18:22:11Z",
"correlationId": "7b9c5c3e-21d3-4c64-a9e2-4e2e4b0f4f7c",
"source": "rest | graphql | mcp",
"userRole": "authenticated",
"requestData": {
"id": 10,
"title": "Dune",
"author": "Frank Herbert"
}
}| Field | Description |
|---|---|
action |
Operation that triggered the hook: create, read, update, delete, or execute. |
entity |
Entity name defined in the DAB configuration. |
timestamp |
UTC time when the event occurred. |
correlationId |
Unique identifier used to correlate the webhook with the original API request. |
source |
API surface that triggered the operation: rest, graphql, or mcp. |
userRole |
Role assigned to the caller after DAB authorization. |
requestData |
Data submitted in the API request that triggered the operation. For read, this may contain query parameters or filter information rather than entity data. |
Inbound payload (from the webhook)
Important
A webhook may return HTTP status 200 with no payload. In this case, the request proceeds unchanged.
{
"correlationId": "7b9c5c3e-21d3-4c64-a9e2-4e2e4b0f4f7c",
"updateRequestData": {
"title": "New value"
}
}| Field | Description |
|---|---|
correlationId |
Identifier matching the original webhook request so DAB can associate the response with the correct operation. Generated from the OpenTelemetry trace or span context. |
updateRequestData |
Optional object containing field changes the webhook wants to apply before the operation continues. |
The before-hook can return updateRequestData to mutate the request.
- Any values in
updateRequestDatanot in the request are ignored. - Any fields, including the primary key fields can be modified.
- Request substitutions occur before mutation, so authentication is not impacted.
Abort example
{
"correlationId": "7b9c5c3e-21d3-4c64-a9e2-4e2e4b0f4f7c",
"stop": {
"reason": "error message"
}
}| Field | Description |
|---|---|
correlationId |
Identifier matching the original webhook request so DAB can associate the response with the correct operation. Generated from the OpenTelemetry trace or span context. |
stop |
Indicates the operation should not continue. |
stop.reason |
Human readable explanation for why the request should be rejected. Returned to the client as the error message. |
Automatic outbound headers
x-dab-action: create
x-dab-entity: Book
x-dab-source: rest
x-dab-correlation-id: 7b9c5c3e-21d3-4c64-a9e2-4e2e4b0f4f7c
Note
This is valuable for programmability, but also for telemetry and logging.
After
Outbound payload (to the webhook)
{
"action": "create | read | update | delete | execute",
"entity": "Book",
"timestamp": "2026-03-14T18:22:11Z",
"correlationId": "7b9c5c3e-21d3-4c64-a9e2-4e2e4b0f4f7c",
"source": "rest | graphql | mcp",
"userRole": "authenticated",
"result": "success | error",
"responseData": {
"id": 10,
"title": "Dune",
"author": "Frank Herbert"
}
}| Field | Description |
|---|---|
action |
Operation that triggered the hook: create, read, update, delete, or execute. |
entity |
Entity name defined in the DAB configuration. |
timestamp |
UTC time when the event occurred. |
correlationId |
Identifier used to correlate the webhook with the originating API request. Generated from the OpenTelemetry trace or span context. |
source |
API surface that triggered the operation: rest, graphql, or mcp. |
userRole |
Role assigned to the caller after DAB authorization. |
result |
Outcome of the database operation: success or error. |
responseData |
Record returned from the operation or the final persisted state of the entity. For read, this may contain query result metadata or returned records. |
Inbound payload (from the webhook)
After is fire and forget, so there is no inbound payload.
Automatic outbound headers
x-dab-action: create
x-dab-entity: Book
x-dab-source: rest
x-dab-correlation-id: 7b9c5c3e-21d3-4c64-a9e2-4e2e4b0f4f7c
Note
These headers are identical to those sent for the before webhook.
Configuration
{
"entities": {
"Book": {
"webhooks": {
"before": {
"enabled": true,
"url": "https://example.com/hooks/before",
"actions": ["*"],
"timeout-seconds": 5,
"abort-on-failure": true
},
"after": {
"enabled": true,
"url": "https://example.com/hooks/after",
"actions": ["delete"]
},
"headers": {
"x-api-key": "@env('WEBHOOK_SECRET')"
}
}
}
}
}Important
This feature supports read, but it is not recommended due to potential performance and event rate impact.
| Property | Default | Description |
|---|---|---|
before.enabled |
false |
Enables the before webhook. Disabled by default to avoid unexpected request interception. |
before.url |
"" |
Endpoint DAB calls before executing the operation. Required when before.enabled is true. |
before.actions |
[] |
Operations that trigger the before webhook: create, read, update, delete, execute. Empty means no actions are enabled. |
before.timeout-seconds |
5 |
Maximum time DAB waits for the webhook response before continuing or failing the request. |
before.abort-on-failure |
true |
Determines behavior when the webhook cannot be reached or returns a non-2xx response. Does not apply when the webhook explicitly returns stop. |
after.enabled |
false |
Enables the after webhook, which runs asynchronously after the operation completes. |
after.url |
"" |
Endpoint DAB calls after the operation completes. Required when after.enabled is true. |
after.actions |
[] |
Operations that trigger the after webhook: create, read, update, delete, execute. Empty means no actions are enabled. |
headers |
{} |
Optional HTTP headers included with webhook requests. Applied to both before and after hooks. |
abort-on-failure
| Failure scenario | Example | Should abort? |
|---|---|---|
| Connection refused | Webhook endpoint is down | Yes |
| DNS resolution failure | URL is misconfigured | Yes |
| Timeout exceeded | Endpoint hangs beyond timeout-seconds |
Yes |
| HTTP 5xx | Webhook server error | Yes |
| HTTP 4xx | Webhook explicitly rejects the operation | Yes |
| HTTP 2xx | Success | No |
Note
The contract is simple: anything other than a 2xx response, or an inability to get one, is treated as a failure.
Important
The abort-on-failure setting is independent of a stop instruction returned in a before webhook response. A stop always rejects the request regardless of the abort-on-failure value.
Command Line
dab update Book --webhooks.before.enabled true
dab update Book --webhooks.before.url "https://example.com/hooks/before"
dab update Book --webhooks.before.actions "create,read,update,delete,execute"
dab update Book --webhooks.before.timeout-seconds 5
dab update Book --webhooks.before.abort-on-failure true
dab update Book --webhooks.after.enabled true
dab update Book --webhooks.after.url "https://example.com/hooks/after"
dab update Book --webhooks.after.actions "create,read,update,delete,execute"
dab update Book --webhooks.headers "x-api-key:@env('WEBHOOK_SECRET')"