Webhooks¶
This guide explains how to set up an outbound webhook notifier so that ADS calls your HTTP endpoint the moment a chosen set of workgraph nodes finishes — without waiting for the whole run to end. It covers the four setup steps: creating the notifier, configuring it, attaching it to a stored run, and (optionally) narrowing it to specific nodes.
What a webhook notifier does¶
A webhook notifier lets ADS make an HTTP POST to a URL you choose when a stored run's monitored nodes have all succeeded. The typical use is triggering a downstream process (for example, an ETL job) as soon as the deliveries you care about have landed, rather than on a fixed schedule.
Setting one up is a two-part job: you create and configure the notifier (the HTTP target), then attach it to a stored run and choose which nodes trigger it.
Before you start¶
- Access to the environment where your solution is installed, with the latest Toolbelt.
- The URL of the endpoint you want ADS to call.
- Set your context to the correct project before running the commands below (
au3 ctx set --id proj-...).
Step 1: Create the notifier¶
The create command only accepts flat values, so it can't take the nested http object yet. Create the notifier first, then configure it in Step 2.
au3 sln inst workgraph notifier create \
--name 'My Webhook' \
--method webhook \
--description 'Downstream ETL trigger'
Record the sinot-... id it returns — you'll need it in the following steps. A freshly created notifier comes back with enabled: false, a seeded http block (method POST, empty url), and include_event_body: true. That's expected; you'll fill it in next.
Step 2: Configure and enable the notifier¶
The update command takes --spec, which accepts JSON or YAML, so the nested http object goes here. Save the following as notifier.yaml, substituting your notifier id and your endpoint URL:
id: sinot-YOUR-NOTIFIER-ID
name: My Webhook
enabled: true
http:
url: https://your-endpoint.example.com/hook
headers:
X-Admin-Key: your-key-here
ttl: 30000
error_handling:
retry: true
retries: 2
minTimeout: 2000
Apply it:
au3 sln inst workgraph notifier update --spec notifier.yaml
Every update replaces the entire http block. Whatever you send as http becomes the stored http — there is no field-level merge. If you later want to change only the URL, you must still include headers, ttl, and anything else you want to keep, or they will be dropped. Copy the whole block forward every time. The notification block on the stored run (Step 3) behaves the same way.
A few notes on the fields:
http.urlmust be an absolutehttporhttpsURL, and is required before you can enable the notifier.headersare optional and passed through as-is.Content-Type: application/jsonis always set by ADS and cannot be overridden.ttlis the per-request timeout in milliseconds.error_handlingcontrols retries:retryon/off,retries(additional attempts after the first), andminTimeout(backoff base in milliseconds). Only5xxresponses and network errors are retried; a4xxis treated as a permanent failure and is not retried.
Step 3: Attach the notifier to a stored run¶
The webhook fires from a stored run. If you don't already have one, create it:
au3 sln inst workgraph stored-run create --name 'My Webhook Run'
Record the sistrun-... id. Then configure the run to call your notifier when its monitored nodes succeed. Save the following as storedrun.yaml, substituting your ids. (The path_filter here scopes which nodes the run executes — adjust the sections to match your own workgraph.)
id: sistrun-YOUR-STORED-RUN-ID
path_filter:
field: destination.section
op: in
val:
- Address
- Location
notification:
node_selection_succeeded:
enabled: true
notifiers:
- sinot-YOUR-NOTIFIER-ID
Apply it:
au3 sln inst workgraph stored-run update --spec storedrun.yaml
With no node_filter under node_selection_succeeded, the run watches every node it selects for the submission and fires the webhook once, when they have all succeeded. This is the whole-run case. To fire earlier — as soon as specific nodes finish — see Step 4.
Step 4: (Optional) Fire on specific nodes instead of the whole run¶
To have the webhook fire the moment a particular node (or set of nodes) finishes — rather than waiting for the whole run — add a node_filter under node_selection_succeeded. Save as storedrun-filtered.yaml:
id: sistrun-YOUR-STORED-RUN-ID
path_filter:
field: destination.section
op: in
val:
- Address
- Location
notification:
node_selection_succeeded:
enabled: true
notifiers:
- sinot-YOUR-NOTIFIER-ID
node_filter:
field: id
op: eq
val: sideltrf-YOUR-DELIVERY-NODE-ID
Apply it:
au3 sln inst workgraph stored-run update --spec storedrun-filtered.yaml
The node_filter selects which nodes are watched for the trigger. It is separate from the stored run's top-level path_filter, which selects what the run executes. Some useful filter shapes:
- A single delivery node —
{"field":"id","op":"eq","val":"sideltrf-..."}, as above. - All delivery nodes —
{"field":"phase","op":"eq","val":"delivery"}. This is closer to what a real downstream trigger usually watches: fire once every delivery is done.
Finding node ids and checking a filter¶
To see the nodes in your workgraph and their ids:
au3 sln inst workgraph view
The keys under nodes are the ids that node_filter matches; delivery nodes are keyed by their sideltrf- id. Each node exposes name, phase, section, and type, all of which are filterable alongside id.
You can preview exactly what a filter would match before you save it — this is the same resolution the platform uses when it evaluates the trigger:
au3 sln inst workgraph view --node-filter '{"field":"phase","op":"eq","val":"delivery"}'
If that returns the nodes you expected, the filter is correct.
Verifying it works¶
Run the stored run:
au3 sln inst workgraph run --stored-run sistrun-YOUR-STORED-RUN-ID
When the monitored nodes have all succeeded, ADS sends a single POST to your endpoint. If you don't yet have your real endpoint ready, a free request-capture service (such as webhook.site) is a quick way to confirm the call arrives with the expected headers and body.
The workgraph task log records the lifecycle — the gate arming, the nodes succeeding, and the delivery result (status and attempt count) — which is the first place to look if a call doesn't arrive as expected.
One thing that is not a failure: if any watched node fails, the gate never closes and nothing fires. The trigger means "these nodes succeeded," so a failed node is a definite "no." Check the submission state before assuming a webhook was lost.
The request ADS sends¶
What your receiving endpoint can rely on:
- Always an HTTP
POSTwithContent-Type: application/json(always present, never overridable). Any headers you configured are passed through unmodified, andX-Ads-Submission-Idcarries the submission id. - The body is a JSON object. It contains an
ads_eventenvelope unlessinclude_event_bodyisfalse, plus the top-level keys of yourcustom_bodyif you set one. On any key collision,ads_eventwins.
The ads_event envelope carries the event id (unique per delivery, stable across ADS's own HTTP retries — usable as an idempotency key), a fixed type, and the real ADS ids for organization, project, stored_run, submission, and notifier. Match duplicate deliveries on submission, not on id.
Delivery is at most once. A call that exhausts its retries is not retried on a later run; the failure is instead recorded on the stored run and surfaced to support in the post-run health report. Build a pull-based backup on your side if you need an at-least-once guarantee.