Webhook Notifications¶
Get notified when syncs complete, fail, go stale, or when governance events are detected — via Slack or any HTTP endpoint.
Prerequisites
- A webhook URL (Slack incoming webhook or custom HTTP endpoint)
- At least one schedule configured
Quick Start¶
-
Add a webhook:
-
Choose a format (Slack or generic JSON) and paste your webhook URL.
-
Test it:
You should see a test notification arrive at your endpoint.
Detailed Steps¶
Adding a Webhook¶
The interactive wizard configures webhook delivery:
$ dango schedule webhook add
🔔 Webhook Setup
─────────────────
Webhook name: slack_alerts
Webhook URL: https://hooks.slack.com/services/T.../B.../xxx
Format:
1. slack — Slack Block Kit (colored sidebar, structured fields)
2. generic — Plain JSON payload
Choice [1]: 1
✅ Webhook 'slack_alerts' added to schedules.yml
Event Types¶
Dango sends notifications for 7 event types:
| Event Type | Description | Category |
|---|---|---|
sync_completed | A scheduled sync finished successfully | success |
sync_failed | A sync failed after all retry attempts | failure |
sync_stale | No sync has run within the stale threshold | stale |
sync_retrying | A sync failed and is being retried | failure |
schema_drift_detected | Breaking schema change detected in a source | governance |
pii_detected | PII found in synced data | governance |
metric_alert | A monitoring metric exceeded its alert threshold | analysis |
Event Categories¶
Events are grouped into 5 categories that control which notifications are sent:
| Category | Events | Default |
|---|---|---|
success | sync_completed | Enabled |
failure | sync_failed, sync_retrying | Enabled |
stale | sync_stale | Enabled |
governance | schema_drift_detected, pii_detected | Enabled |
analysis | metric_alert | Enabled |
Global Event Toggles¶
Control which event categories trigger notifications for all webhooks:
# .dango/schedules.yml
notifications:
webhooks:
- name: slack_alerts
url: "https://hooks.slack.com/services/T.../B.../xxx"
format: slack
# Global toggles — apply to ALL webhooks
on_success: true # sync_completed events
on_failure: true # sync_failed, sync_retrying events
on_stale: true # sync_stale events
on_governance: true # schema_drift_detected, pii_detected events
on_analysis: true # metric_alert events
stale_threshold_hours: 24 # Hours without a sync before "stale" fires
Reducing noise
Set on_success: false if you only want alerts on problems. Success notifications can be noisy when syncs run frequently.
Per-Schedule Overrides¶
Override global toggles for individual schedules using the notify_on field:
schedules:
- name: critical_sync
type: sync
cron: "*/15 * * * *"
sources: [stripe]
notify_on: # Only notify on these events for this schedule
- failure
- stale
- name: hourly_marts
type: dbt
cron: "0 * * * *"
notify_on: [] # Disable all notifications for this schedule
Configuration Reference¶
notifications Block in schedules.yml¶
notifications:
# Webhook endpoints
webhooks:
- name: slack_alerts # Unique name
url: "https://hooks.slack.com/services/..." # Webhook URL (must start with http:// or https://)
format: slack # "slack" or "generic"
- name: pagerduty
url: "https://events.pagerduty.com/integration/..."
format: generic
# Global event category toggles
on_success: true # Send notifications for successful syncs
on_failure: true # Send notifications for failed syncs and retries
on_stale: true # Send notifications when syncs go stale
on_governance: true # Send notifications for schema drift and PII
on_analysis: true # Send notifications for metric alerts
stale_threshold_hours: 24 # Hours without a sync before a source is considered stale
Slack Integration¶
Dango formats Slack messages using Block Kit with colored sidebars:
| Event | Color | Hex |
|---|---|---|
| Sync Completed | Green | #2eb886 |
| Sync Failed | Red | #e01e5a |
| Sync Stale | Amber | #ecb22e |
| Sync Retrying | Gray | #aaaaaa |
| Schema Drift Detected | Dark amber | #e0a514 |
| PII Detected | Red | #e01e5a |
| Metric Alert | Dark amber | #e0a514 |
Setting up a Slack webhook:
- Go to your Slack workspace and create a new app (or use an existing one)
- Enable Incoming Webhooks in your app settings
- Click Add New Webhook to Workspace and select a channel
- Copy the webhook URL (starts with
https://hooks.slack.com/services/) - Use
dango schedule webhook addand paste the URL with formatslack
Generic Webhooks¶
For non-Slack endpoints, use format: generic. The payload is a JSON object:
{
"event": "sync_completed",
"schedule": "daily_sync",
"sources": ["stripe", "google_sheets"],
"duration_seconds": 145.2,
"rows_loaded": 12500,
"timestamp": "2026-05-15T06:02:30+00:00",
"dashboard_url": "https://your-domain.com/",
"error": null,
"stale_hours": null,
"attempt_number": null,
"next_retry_at": null,
"metadata": null
}
| Field | Type | Present When |
|---|---|---|
event | string | Always — the event type value (e.g., sync_completed) |
schedule | string | Always — the schedule name |
sources | list | Always (may be empty for dbt schedules) |
duration_seconds | float | sync_completed |
rows_loaded | int | sync_completed |
error | string | sync_failed, schema_drift_detected, pii_detected |
stale_hours | float | sync_stale |
attempt_number | int | sync_retrying |
next_retry_at | datetime | sync_retrying |
timestamp | datetime | Always — ISO 8601 UTC |
dashboard_url | string | When configured |
metadata | object | metric_alert (contains summary, flagged_count, total_count) |
Retry Logic¶
Webhook delivery retries on transient failures:
| Attempt | Delay Before | Retried On |
|---|---|---|
| 1 | — | First delivery attempt |
| 2 | 5 seconds | 5xx status, timeout, connection error |
| 3 | 15 seconds | Final attempt |
| (give up) | — | All 3 attempts exhausted, discarded |
- HTTP timeout: 10 seconds per request
- Retryable errors: 5xx server errors, connection errors, DNS failures, timeouts
- Non-retryable: 4xx client errors (bad URL, invalid token) — no retry, discarded immediately
- Never blocks: Webhook failures never block the sync pipeline. Delivery is fire-and-forget.
Verification¶
After adding a webhook, test it:
Check that:
- The test notification appears at your endpoint
- The format is correct (Slack Block Kit or JSON)
- The channel/destination is right
Debugging delivery
If webhooks aren't arriving, check the Dango logs for webhook_delivery_failed entries. Common causes: expired Slack webhook URL, firewall blocking outbound HTTPS, or incorrect URL.
Troubleshooting¶
Webhook not receiving notifications
- Run
dango schedule webhook test <name>— does the test message arrive? - Verify the URL is correct in
.dango/schedules.yml - Check that the relevant event category is enabled (e.g.,
on_success: true) - Ensure
dango startis running
Slack formatting issues
- Verify
format: slackis set in the webhook config - Slack incoming webhooks only support their own Block Kit format — don't use
format: genericfor Slack
Timeout errors
- Dango waits 10 seconds for a webhook response. If your endpoint is slow, webhook delivery will fail
- Check your endpoint's response time — it should respond within a few seconds
Event not triggering
- Check global toggles (
on_success,on_failure, etc.) in thenotificationsblock - Check per-schedule
notify_onoverrides — an empty list disables all notifications for that schedule sync_staleonly fires when no sync has run withinstale_threshold_hours(default: 24)
Next Steps¶
- Scheduled Syncs — set up the schedules that trigger these notifications
- Schema Drift — understand
schema_drift_detectedevents - PII Scanning — understand
pii_detectedevents - Monitoring Metrics — understand
metric_alertevents