Notifications and outbound webhooks
Notification channels define where alerts go. Alert rules choose a run event, optionally restrict it to one flow, and send to one or more channels. Use this to notify operators about failures or deliver run status to your application.
On this page
Configure a channelCreate an alert ruleTest deliveryReceive a generic webhookDelivery behaviorManage and troubleshootSupported destinations are Slack incoming webhooks, email, PagerDuty, and a generic HTTP webhook. These are separate from saved integration connectors.
Configure a channel
Channel reads require notifications.read; creation, deletion, rule changes, and tests require notifications.write. Use an authenticated token for these requests.
curl --fail-with-body "$DAGY_API_URL/channels" \
-H "Authorization: Bearer $DAGY_TOKEN" \
-H 'Content-Type: application/json' \
--data '{
"name":"Development run callback",
"channel_type":"webhook",
"config_json":"{\"url\":\"https://example.com/dagy/events\",\"secret\":\"YOUR_SIGNING_SECRET\"}"
}'config_json is a JSON-encoded string, not a nested object. When using a programming language, serialize the channel configuration once, then include that string in the request body. The 201 response contains the channel_id; keep it for the alert rule.
channel_type | Fields inside config_json | Prerequisite |
|---|---|---|
slack | webhook_url | An incoming webhook for the destination Slack channel |
webhook | url; optional secret or signing_secret | A reachable endpoint accepting JSON POST requests |
pagerduty | routing_key | A PagerDuty Events API integration key |
email | from_email, to_email; optional region, subject | Sender access configured for email delivery in your Dagy environment |
For email, to_email may be one address or a list. Email channels are not SMTP connectors; supplying a sender address alone does not provision email delivery. Confirm the sender is available with your administrator.
Channel configuration is returned by channel read operations. Limit notifications.read to people who may access destination URLs and credentials. Do not assume the credential-redaction behavior of saved connectors also applies here.
Create an alert rule
curl --fail-with-body "$DAGY_API_URL/alert-rules" \
-H "Authorization: Bearer $DAGY_TOKEN" \
-H 'Content-Type: application/json' \
--data '{
"name":"Order processing failed",
"trigger":"on_failure",
"flow_name":"process-orders",
"channel_ids":["YOUR_CHANNEL_ID"]
}'The response is 201 with a rule_id. Omit flow_name to match all flows in the workspace. Rules without a destination in channel_ids deliver nothing.
| Trigger | Current behavior |
|---|---|
on_failure | Automatic notifications are emitted by supported run completion paths |
on_success | Automatic notifications are emitted by supported run completion paths; cancelled runs can also be classified under this trigger |
on_retry | Accepted rule value; automatic retry notification emission is not implemented |
on_sla_breach | Accepted rule value; automatic duration/SLA evaluation is not implemented |
sla_seconds is accepted as rule configuration but does not activate a running duration monitor. For a production duration alarm or complete coverage across execution modes, monitor the runs API from your observability system and evaluate the condition there. Validate notifications using the execution mode your integration actually uses.
Test delivery
POST /alert-rules/{rule_id}/test sends real notifications using a synthetic test-run ID. It evaluates all rules matching the selected rule's trigger and flow, so more than one rule can send a message. Use a development destination before testing production paging rules.
curl --fail-with-body -X POST \
"$DAGY_API_URL/alert-rules/$RULE_ID/test" \
-H "Authorization: Bearer $DAGY_TOKEN"{"dispatched":1,"test":true}dispatched counts successful sends. A zero result can mean no matching destination, invalid configuration, disabled records, unavailable delivery, or provider rejection. The test result does not include detailed delivery history.
Receive a generic webhook
The destination receives a JSON POST similar to:
{
"event":"on_failure",
"flow_name":"process-orders",
"message":"Flow run FAILED\nRule: Order processing failed\nFlow: process-orders\nRun: run-example\nOrg: org-example",
"org_id":"org-example",
"rule_id":"rule-example",
"rule_name":"Order processing failed",
"run_id":"run-example"
}Headers include Content-Type: application/json and User-Agent: dagy-notifications/1. When the channel has a signing secret, X-Dagy-Signature contains sha256= followed by the hexadecimal HMAC-SHA256 of the exact request body bytes.
Verify the signature before parsing or acting on the payload:
import hashlib
import hmac
def valid_dagy_signature(raw_body: bytes, header: str, secret: str) -> bool:
digest = hmac.new(secret.encode("utf-8"), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(header, "sha256=" + digest)Use your web framework's raw-body accessor. Reformatting or reserializing JSON before verification changes the signed bytes. Keep the secret in your application's secret store.
The signature proves possession of the secret; the payload has no delivery ID or signed timestamp. Apply your own replay policy and deduplicate effects, for example using (org_id, rule_id, run_id, event) when only one action per matching run is intended. Retrieve authoritative run status before making a decision that depends on whether a run succeeded or was cancelled.
Delivery behavior
Notifications are best effort. HTTP destinations have a 10-second timeout, failures do not fail the flow, and there is no documented durable retry, replay, or redelivery API. Respond promptly with a successful HTTP status and queue longer processing in your application.
Do not make the notification the sole record of a critical run outcome. Persist the run ID when starting work and reconcile completion through the runs API.
PagerDuty events use event_action: trigger with a deduplication key based on the rule and run. Failure alerts have critical severity; other events use informational severity. Dagy does not send an automatic PagerDuty resolve event.
Manage and troubleshoot
GET /channels and GET /alert-rules return items arrays. Read an individual record with GET /channels/{id} or GET /alert-rules/{id}. Delete either with DELETE; successful deletion returns {"deleted":true}. There is no update operation for channels or rules: create a replacement and remove the old record.
| Problem | Check |
|---|---|
| Rule test sends nothing | Confirm config_json is a JSON string, credentials are valid, and channel IDs belong to this workspace |
403 on management request | Confirm the required notification permission |
404 | Confirm the channel/rule ID still exists |
| Webhook signature fails | Use raw body bytes and the exact configured secret |
| SLA/retry alert never fires | These triggers have no automatic emitter; use external run monitoring |
| Missed or duplicate alert | Reconcile run status and make receiver actions idempotent |
For events that start a flow, see inbound webhooks and sensors.