Skip to content

Notifications

dbward can notify external systems when events occur — new requests, approvals, failures, emergency access. This page covers webhook-based delivery. For interactive Slack integration (buttons, modals, onboarding), see Slack Integration.

For controlling which events fire on which databases, see Notification Policies.


[[webhooks]]
id = "my-receiver"
url = "https://your-service.com/dbward-events"
format = "generic"
secret = "${WEBHOOK_SECRET}"
events = ["request.created", "request.approved", "execution.completed", "request.break_glass"]
FieldTypeDefaultDescription
idStringUnique identifier for the webhook
urlStringDelivery endpoint (HTTPS required in production)
formatString"generic"Payload format: generic or slack
secretStringHMAC-SHA256 signing key
eventsString[][] (all)Filter events (empty = all events)
EventCategoryDescription
request.createdapprovalNew request submitted
request.break_glassapprovalEmergency request (bypass approval)
request.auto_approvedapprovalAuto-approved by policy
step.approvedapprovalApproval step completed
request.approvedapprovalFully approved (all steps)
request.rejectedapprovalRequest rejected
request.cancelledapprovalRequest cancelled by requester
request.dispatchedapprovalRequest dispatched to agent
request.expiredapprovalRequest TTL expired
request.dispatch_timeoutapprovalNo agent claimed within timeout
execution.startedexecutionAgent started execution
execution.completedexecutionExecution succeeded
execution.failedexecutionExecution failed
execution.lostagentAgent connection lost during execution
user.createduserNew user created
user.updateduserUser updated
user.deleteduserUser soft-deleted
user.suspendeduserUser suspended
user.activateduserUser re-activated
{
"event": "request.created",
"request_id": "c22932a6-ebc6-4eea-93cb-f2215c8c48eb",
"database": "app",
"environment": "production",
"operation": "execute_select",
"actor": "alice",
"requester": "alice",
"detail": "SELECT * FROM users WHERE ...",
"matched_selector": "role:dba"
}

When secret is set, every delivery includes:

x-dbward-signature: sha256=<hex-encoded HMAC-SHA256 of body>

Verify in your receiver:

import hmac, hashlib
expected = hmac.new(secret.encode(), request.body, hashlib.sha256).hexdigest()
actual = request.headers["x-dbward-signature"].removeprefix("sha256=")
assert hmac.compare_digest(expected, actual)
  • Deliveries are persisted before sending (no lost events on crash)
  • Failed deliveries retry up to 10 times with exponential backoff
  • Timeout: 10 seconds per attempt
  • Redirects are disabled (SSRF protection)
  • Internal network addresses are blocked

SQL in webhook payloads is automatically redacted — string and numeric literals are replaced with ?:

SELECT * FROM users WHERE email = ? AND age > ?

This is applied unconditionally to all webhook deliveries. Full SQL (unredacted) is never sent via webhooks.


Use format = "slack" to send Block Kit-formatted messages via Incoming Webhook:

[[webhooks]]
url = "https://hooks.slack.com/services/T.../B.../xxx"
format = "slack"
secret = "${WEBHOOK_SECRET}"

This is a passive, outbound-only integration. For interactive features (approve/reject buttons, modals, slash commands), use the Slack Integration.

The format = "slack" webhook displays redacted SQL (literals replaced with ?) directly in the channel message. If you don’t want SQL visible in Slack:

  1. Use Interactive Slack instead — SQL is only shown inside the Review Modal
  2. Use format = "generic" — receive raw JSON and format it yourself
Webhook (format = "slack")Interactive ([slack])
Setup[[webhooks]] + Incoming Webhook URL[slack] + Bot Token + Signing Secret
DeliveryIncoming Webhook (passive)Bot Token API (chat.postMessage)
Approve/Reject❌ CLI only✅ Buttons + Modal
SQL in message✅ Shown directly (redacted)❌ Only in Review Modal
Thread replies❌ Single message per event✅ Thread + message updates
Mentions✅ @user notifications

Both can be enabled simultaneously.


Run dbward-server validate --config server.toml first — it checks config structure and webhook references. Add --preflight to also check Slack API connectivity (note: webhook URL reachability is not checked).

IssueSolution
No notifications sentCheck [[webhooks]] config, env vars, and events filter
Signature mismatchVerify secret matches between config and receiver
Webhook not deliveredCheck endpoint is reachable, returns 2xx within 10s
Slack webhook shows raw JSONSet format = "slack"

For Slack-specific troubleshooting (buttons, slash commands, account linking), see Slack Integration: Troubleshooting.