Webhook
A webhook node sends an HTTP request when the call finishes. It is how what happened on the call reaches the system that has to act on it, without anybody opening a dashboard.
Like the QA node, it sits beside the conversation rather than in it: no incoming edges, no outgoing edges. You can have several, pointing at different systems.
Fields
namestringdefault: Webhook
Short label shown on the canvas and in run logs.
enabledbooleandefault: true
Switch the webhook off without deleting it.
http_methodGET | POST | PUT | PATCH | DELETEdefault: POST
Verb for the outbound request.
endpoint_urlurlrequired
Where the request goes.
credential_uuidcredential
A stored credential, applied as the Authorization header. Use this rather than
hard-coding a token into a custom header — credentials are encrypted at rest and
can be rotated without editing every agent that uses them.
custom_headersobject[]
Additional headers to send.
payload_templatejson
The request body. Values are rendered against the run context.
Available variables
Anything in this list can appear in the payload template.
| Variable | What it is |
|---|---|
{{workflow_run_id}} | Unique ID of this run. The one to store. |
{{workflow_id}} | ID of the agent |
{{workflow_name}} | Name of the agent |
{{campaign_id}} | Campaign this run belongs to; empty for ad-hoc calls |
{{call_time}} | ISO-8601 UTC timestamp of when the call started |
{{initial_context.*}} | What you sent in |
{{gathered_context.*}} | What the agent extracted |
{{annotations.qa_*}} | Results from a QA node |
{{cost_info.call_duration_seconds}} | Call duration |
{{recording_url}} | Full call recording |
{{user_recording_url}} | Caller audio only |
{{bot_recording_url}} | Agent audio only |
{{transcript_url}} | Transcript |
{ "call_id": "{{workflow_run_id}}", "campaign_id": "{{campaign_id}}", "called_at": "{{call_time}}", "first_name": "{{initial_context.first_name}}", "rsvp": "{{gathered_context.rsvp}}", "duration_seconds": "{{cost_info.call_duration_seconds}}", "recording_url": "{{recording_url}}", "transcript_url": "{{transcript_url}}"}Store the run ID
Whatever else the payload carries, include {{workflow_run_id}}.
It is the only thing that ties a row in your system back to a specific call in Decibyl — the recording, the transcript, the QA result, the cost. Support requests that quote a run ID get answered; ones that say “a call yesterday afternoon” mostly do not.
Several webhooks
Because a node is one request to one URL, sending the same call to two systems means two nodes. That is usually better than one endpoint of yours fanning out: each has its own payload shaped for its receiver, its own credential, and can be switched off on its own.
Webhook → CRM full payload, everything the record needsWebhook → Slack three fields, for a channel people watchWebhook → data warehouse the wide one, for analysis laterTesting without a backend
Open webhook.site, take the unique URL it gives you, and paste it into the endpoint field. Run a call. You see the exact bytes Decibyl sends, which is much faster than guessing at the template and reading your own server logs.
Swap in the real URL once the shape is right.
Rules
- No incoming and no outgoing edges.
- Fires once, when the run completes. A call that never connected does not produce one.
- Any number per agent.