Webhooks
Webhooks deliver conversation events to your infrastructure as HTTP POST requests. Configure a webhook once and the platform calls your endpoint automatically whenever the event fires — no polling required.
Event types
| Event type | When it fires |
|---|---|
conversation.initiating |
A call has been answered and the agent is about to speak its first message |
conversation.completed |
The call has ended and the full transcript and analysis are available |
Webhook scope
A webhook can be scoped to your entire account or to a single agent:
- Account-wide: fires for every conversation on your account, regardless of which agent handled it. Create without an
agent_id. - Agent-specific: fires only for conversations handled by the specified agent. Create with an
agent_id.
If both apply to a conversation, both fire independently.
Creating a webhook
curl -X POST https://api.simwood.com/convai/v1/webhooks \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"event_type": "conversation.completed",
"url": "https://example.com/hooks/calls",
"request_headers": {
"X-Webhook-Secret": "your-secret-value"
}
}'
To scope to a specific agent, add "agent_id": "<agent-uuid>" to the body.
Request headers
request_headers are included verbatim in every delivery to your endpoint. Use them to pass a shared secret or authentication token so you can verify that requests come from the platform.
One webhook per event type per scope is allowed. Attempting to create a second conversation.completed
webhook at the account level returns 409 Conflict. Create an agent-scoped webhook if you need
different behaviour per agent.
Event payloads
conversation.initiating
Fires when an inbound call arrives, before it is answered. The caller hears ringing while the platform waits for your response — up to the webhook's timeout_ms (default: 5 seconds). Respond within that window to inject per-call context; if your endpoint does not respond in time, the agent answers with its default configuration after the full timeout has elapsed. Return an empty 200 immediately if you have no overrides — this avoids making the caller wait unnecessarily.
{
"type": "conversation.initiating",
"timestamp": 1719820800,
"data": {
"conversation_id": "conv-uuid-...",
"agent_id": "agent-uuid-..."
}
}
Your response body may include any of the following fields to override the agent's default configuration for this call:
| Field | Type | Description |
|---|---|---|
dynamic_variables |
object | Key-value pairs available as {{dynamic_variables.<key>}} in the agent's prompt — use to personalise the conversation with caller-specific data |
conversation_config_override |
object | Overrides to the agent's conversation configuration for this call (e.g. text_only) |
Omit a field entirely to use the agent's default. An empty 200 response is valid if you have no overrides.
conversation.completed
Fires when the call ends. The full transcript and any analysis results are included.
{
"type": "conversation.completed",
"timestamp": 1719820943,
"data": {
"conversation_id": "conv-uuid-...",
"agent_id": "agent-uuid-...",
"status": "done",
"metadata": {
"start_time_unix_secs": 1719820800,
"call_duration_secs": 143
},
"transcript": [
{ "role": "agent", "message": "Hello, thanks for calling.", "time_in_call_secs": 0.0 },
{ "role": "user", "message": "I'd like to cancel my subscription.", "time_in_call_secs": 3.4 }
],
"analysis": {
"data_collection_results": {
"issue_resolved": true
},
"call_successful": "success",
"transcript_summary": "Caller cancelled their subscription."
}
}
}
Delivery and retry
The platform delivers each event with a short timeout. If your endpoint does not respond with a 2xx status, delivery is retried with exponential backoff. The platform tracks consecutive failures per webhook; a webhook that fails repeatedly is marked failing and delivery is suspended until it recovers.
Check the health of a webhook with GET /webhooks/:id.
Managing webhooks
# List all webhooks on the account
curl https://api.simwood.com/convai/v1/webhooks \
-H "Authorization: Bearer sk_live_..."
# Filter by agent
curl "https://api.simwood.com/convai/v1/webhooks?agent_id=<agent-uuid>" \
-H "Authorization: Bearer sk_live_..."
# Filter by event type
curl "https://api.simwood.com/convai/v1/webhooks?event_type=conversation.completed" \
-H "Authorization: Bearer sk_live_..."
# Delete a webhook
curl -X DELETE https://api.simwood.com/convai/v1/webhooks/<webhook-id> \
-H "Authorization: Bearer sk_live_..."