Receive conversation events
This guide walks through configuring a webhook and handling the two event types the platform delivers: conversation.initiating (when a call is answered) and conversation.completed (when a call ends).
You'll need an API key with convai:read and convai:write, and a publicly accessible HTTPS
endpoint to receive webhook deliveries.
1. Configure a webhook
Create a webhook by posting to /webhooks. The platform will POST to your url whenever the specified event fires. Use request_headers to pass a shared secret so your endpoint can verify deliveries.
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-shared-secret"
}
}'
To also receive initiating events, create a second 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.initiating",
"url": "https://example.com/hooks/calls",
"request_headers": {
"X-Webhook-Secret": "your-shared-secret"
}
}'
These webhooks fire for every conversation on your account. To scope them to a single agent, add "agent_id": "<agent-uuid>" to either request body.
2. Handle conversation.initiating
The initiating event fires when an inbound call arrives, before it is answered. The caller hears ringing while the platform waits for your response. You have up to the webhook's configured timeout_ms (default: 5 seconds) to reply — use this window to look up caller-specific data and return it as overrides for this call.
Your endpoint receives:
{
"type": "conversation.initiating",
"timestamp": 1719820800,
"data": {
"conversation_id": "conv-uuid-...",
"agent_id": "agent-uuid-..."
}
}
Respond with any combination of the following fields to override the agent's default configuration for this call:
{
"dynamic_variables": {
"customer_name": "Jane Smith",
"account_status": "premium",
"outstanding_balance": "£42.00"
},
"conversation_config_override": {
"text_only": false
}
}
| Field | Type | Description |
|---|---|---|
dynamic_variables |
object | Key-value pairs injected into the agent's prompt as {{dynamic_variables.<key>}} |
conversation_config_override |
object | Overrides to the agent's conversation configuration for this call |
Omit a field to use the agent's default. An empty 200 response is valid if you have no overrides.
If your endpoint does not respond within timeout_ms, the agent answers with its default
configuration. Keep your handler fast — a simple database lookup or cache read is ideal; avoid
anything that may block.
3. Handle conversation.completed
The completed event fires when the call ends and the transcript is ready. Your endpoint receives the full conversation record:
{
"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. How can I help you today?", "time_in_call_secs": 0.0 },
{ "role": "user", "message": "I'd like to check my account balance.", "time_in_call_secs": 3.4 },
{ "role": "agent", "message": "Your current balance is £42.00.", "time_in_call_secs": 6.1 }
],
"analysis": {
"data_collection_results": {
"issue_resolved": true,
"customer_intent": "check account balance"
},
"call_successful": "success",
"transcript_summary": "Caller asked for their account balance. Agent provided it."
}
}
}
Respond with 2xx to acknowledge. The platform retries on non-2xx responses with exponential backoff.
4. Check webhook health
After a few calls, confirm deliveries are landing:
curl https://api.simwood.com/convai/v1/webhooks/<webhook-id> \
-H "Authorization: Bearer sk_live_..."
The response includes a health field (healthy, degraded, or failing) and consecutive_failures. A failing webhook has its deliveries suspended until it recovers — investigate your endpoint if the health degrades.