Webhook Payloads
Context variables available in webhook nodes and the data Talkr sends after a call
Talkr executes webhook nodes asynchronously after a workflow run completes. You configure the target URL, HTTP method, headers, and payload template directly in the workflow definition.
How webhooks work
- A call completes (or a run finishes)
- Talkr executes any
webhooknodes in the workflow asynchronously - The payload template is rendered with the run's context and sent as a JSON
POST(or your configured method) to your endpoint - Non-200 responses are logged but do not block or retry by default (configure
retry_configto change this)
Payload context variables
The following variables are available in your payload_template using double-brace syntax (e.g. {{workflow_run_id}}):
| Variable | Type | Description |
|---|---|---|
workflow_run_id | integer | ID of the completed run |
workflow_run_name | string | Name of the run |
workflow_id | integer | ID of the workflow |
workflow_name | string | Name of the workflow |
campaign_id | integer | null | ID of the campaign this run belongs to (null for ad-hoc runs) |
call_time | string | ISO-8601 UTC timestamp of when the run was created |
initial_context | object | Context passed when the call was initiated |
gathered_context | object | Data extracted during the call by agent nodes |
gathered_context.call_disposition | string | Final call outcome (see Call disposition) |
cost_info | object | Call cost breakdown |
cost_info.call_duration_seconds | number | Call duration in seconds |
annotations | object | QA analysis results (if a qa node is configured) |
recording_url | string | null | Public download URL for the call recording |
transcript_url | string | null | Public download URL for the call transcript |
Call disposition
The final outcome of the call is available as {{gathered_context.call_disposition}}. It holds the disposition set during the call, falling back to the reason the call ended (e.g. user_hangup, voicemail_detected, call_transferred, call_duration_exceeded).
Talkr always includes a top-level call_disposition field in the delivered payload. If your template doesn't set one, it is added automatically from gathered_context.call_disposition; if your template sets it explicitly, your value is kept.
Example payload template
{
"run_id": "{{workflow_run_id}}",
"customer": "{{initial_context.customer_name}}",
"outcome": "{{gathered_context.resolution}}",
"disposition": "{{gathered_context.call_disposition}}",
"duration": "{{cost_info.call_duration_seconds}}",
"recording": "{{recording_url}}"
}Authentication
Webhook requests support the following authentication methods, configured via a stored credential:
| Type | Description |
|---|---|
NONE | No authentication |
API_KEY | Sends the key in a custom header (e.g. X-API-Key) |
BEARER_TOKEN | Sends Authorization: Bearer <token> |
BASIC_AUTH | HTTP Basic authentication (username + password) |
CUSTOM_HEADER | Any custom header key-value pair |
Receiving webhooks
Your endpoint should:
- Accept
POSTrequests withContent-Type: application/json - Respond with a
2xxstatus code promptly (within 30 seconds) - Handle duplicate deliveries idempotently (retries may deliver the same payload more than once)
Minimal example receiver (Python)
from fastapi import FastAPI, Request
app = FastAPI()
@app.post("/webhook/talkr")
async def handle_talkr_webhook(request: Request):
payload = await request.json()
run_id = payload.get("run_id")
outcome = payload.get("outcome")
# process the call result...
return {"status": "ok"}Webhook node in a workflow definition
See Workflow Definition Schema for the full configuration reference.
{
"id": "webhook-1",
"type": "webhook",
"position": { "x": 600, "y": 0 },
"data": {
"name": "Notify CRM",
"enabled": true,
"http_method": "POST",
"endpoint_url": "https://your-service.com/webhook/talkr",
"payload_template": {
"run_id": "{{workflow_run_id}}",
"customer": "{{initial_context.customer_name}}",
"outcome": "{{gathered_context.resolution}}"
}
}
}