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_..."
Receive conversation eventsEnd-to-end walkthrough: configure a webhook and handle each event type.ConversationsThe full conversation record delivered in the completed event.