Outbound webhooks
Notify your own systems the moment a workflow execution finishes — with signed, retried deliveries you can trust
What outbound webhooks do
An outbound webhook lets MagOneAI push a notification to your system when a workflow execution finishes — succeeded or failed. Instead of polling for status, your backend receives an HTTP POST the moment a run ends, so you can update a record, kick off downstream work, or alert a channel.
This is the opposite direction from the API trigger. The API trigger lets an external system start a workflow. Outbound webhooks let MagOneAI tell an external system that a workflow finished. If you want to launch a run from outside, use the trigger; if you want to be notified when a run ends, use an outbound webhook.
How subscriptions work
You attach one or more webhook subscriptions to a use case. Each subscription has:
- A target URL — the HTTPS endpoint MagOneAI delivers to.
- A list of events it cares about.
- An optional trigger-type filter — only notify for runs started a certain way.
- A signing secret — used to sign every delivery so you can verify it came from MagOneAI.
A use case can have several subscriptions, so you can route workflow.failed to an alerting endpoint and workflow.completed to your application without them stepping on each other.
Events
| Event | Fires when |
|---|---|
workflow.completed | An execution finishes successfully |
workflow.failed | An execution ends in failure |
Subscribe to one or both per subscription.
Filtering by trigger type
A subscription can optionally filter which runs notify it by how the run was triggered — manual / in-app, chat, schedule, or API. Leave the filter empty to receive notifications for all trigger types.
Use a trigger-type filter to keep noise down. For example, notify only on schedule runs if you only care about your unattended nightly jobs, not the manual runs you launch from Studio while testing.
Set up a webhook
Open the use case's webhooks
Go to the use case you want to be notified about and open its webhook subscriptions.
Add a subscription
Enter the target URL MagOneAI should POST to, and choose the events (workflow.completed, workflow.failed, or both).
Optionally filter by trigger type
Pick the trigger types that should notify this subscription, or leave it empty for all of them.
Save the signing secret
On creation, MagOneAI shows the signing secret once. Copy it and store it securely (e.g. in your secret manager) — you'll need it to verify deliveries, and it isn't shown again.
Send a test event
Use Send test event to deliver a sample payload to your endpoint. Confirm your endpoint receives it, verifies the signature, and returns a 2xx before you rely on it.
Manage subscriptions from the use case: create, list, delete, send a test event, and view delivery history for each one.
The delivery payload
Each delivery is an HTTP POST with a JSON body describing the execution that finished. The exact fields may grow over time, so write your receiver to ignore unknown keys. A delivery looks roughly like this:
{
"event": "workflow.completed",
"execution_id": "exec_01HX...",
"use_case_id": "uc_01HX...",
"status": "completed",
"trigger_type": "schedule",
"output": {
"summary": "Processed 42 records"
}
}event—workflow.completedorworkflow.failed.execution_id— the run that finished; use it to drill into execution history.use_case_id— the use case the run belongs to.status— the terminal status of the execution.trigger_type— how the run was started (manual / in-app, chat, schedule, API).output— the workflow's output for completed runs.
Verifying deliveries
Every delivery is signed so your receiver can confirm it genuinely came from MagOneAI and wasn't tampered with. Each request carries these headers:
| Header | Contents |
|---|---|
X-MagOne-Signature | t=<unix_timestamp>,v1=<hex HMAC-SHA256> |
X-MagOne-Event | The event name, e.g. workflow.completed |
X-MagOne-Webhook-Id | The subscription that produced this delivery |
The signature is computed Stripe-style: take the timestamp t from the header, build the signed string as the timestamp, a literal ., then the raw request body, and compute an HMAC-SHA256 of that string keyed with your subscription's signing secret. Compare the resulting hex digest to v1.
signed_string = "<t>." + raw_request_body
v1 = HMAC_SHA256(signing_secret, signed_string) // compare to header, hexAlways verify the signature and check that the timestamp is recent before trusting a delivery. Compute the HMAC over the raw body (not a re-serialized copy), compare digests in constant time, and reject deliveries whose timestamp is too old — this is what prevents an attacker from replaying a captured request. Treat any delivery that fails verification as untrusted.
Reliability and delivery history
MagOneAI retries failed deliveries automatically, and records every attempt so you can see what happened.
If your endpoint doesn't return a success response, MagOneAI retries the delivery — up to 5 attempts with exponential backoff spread over roughly 30 minutes. Make your endpoint respond quickly with a 2xx once it has accepted the event; do the heavy work asynchronously so a slow handler doesn't cause needless retries.
Because deliveries are retried, your endpoint may receive the same event more than once. Use the execution_id (together with the event) to de-duplicate, so processing the same notification twice is safe.
Each attempt is logged against the subscription — including the response status code and the response body — so you can inspect delivery history when something isn't arriving. Use it to confirm test events landed, diagnose 4xx/5xx responses from your endpoint, and see whether a delivery eventually succeeded on retry.
Good patterns
- Test before you depend on it. Send a test event and confirm your endpoint verifies the signature and returns 2xx before wiring webhooks into anything important.
- Verify every delivery. Never act on a payload you haven't authenticated — check the signature and the timestamp first.
- Respond fast, process later. Acknowledge with a 2xx immediately and handle the work asynchronously to avoid retry storms.
- De-duplicate by
execution_id. Retries mean at-least-once delivery; idempotent handling keeps repeats harmless.