Skip to main content

Delivery, signatures & retries

Every event is delivered as an HTTP POST with a JSON body using the standard envelope { event, organization_id, data }. Endpoints are managed in Settings → Webhooks in the dashboard, which also gives you a self-serve portal with full delivery history, per-attempt response codes, and manual replay. Headers. Each delivery carries three headers: Signature verification. Every endpoint has its own signing secret, available from the webhooks portal. Verify the signature on every delivery before trusting the payload; reject anything that fails verification or falls outside your timestamp tolerance. Retries. A delivery is considered failed on any non-2xx response or timeout. Failed deliveries are retried automatically with exponential backoff over several hours; after the automatic schedule is exhausted, manual replay remains available from the portal. Return a 2xx as fast as possible — enqueue the event and process it asynchronously rather than doing work inline. Idempotency. Dedupe on the svix-id header. Phone-call events additionally carry a producer-side idempotency key of the form <event_type>.<session_id> — each phone event type fires at most once per session. Ordering is not guaranteed. Retries mean events can arrive out of order; use the timestamp field in the payload, not arrival order.
conversation.started This event is triggered when a new conversation is started, regardless of the channel.

conversation.closed This event is triggered when a conversation is closed, a conversation can be marked as resolved or not resolved, and can be closed by a human or an AI. closed_by identifies what triggered the close, while assignee identifies who the conversation was assigned to at close time. They are independent: a workflow or AI close on a conversation assigned to a human agent still carries that agent’s details in assignee, so you can attribute the resolution to the assigned agent even when they didn’t close it themselves.

conversation.handoff_to_human This event is triggered when a conversation is handed off to a human agent. Note that a handoff event can happen for multiple reasons; for example, a human agent might decide to take over the conversation, or the AI might decide to hand off the conversation to a human agent.
conversation.contact_response When a contact sends a message to your inbox.
conversation.ai_response When an AI responds to a contact message,

conversation.agent_response When a human agent responds from the Open inbox,
conversation.third_party_agent_response When a third-party software agent responds to a previously handed-off conversation, Open will notify you. In some configurations, Open might also initiate the handoff to a third-party agent, such as Zendesk or Intercom. Even while the third-party agent handles the conversation, Open continues to monitor and send events to your webhooks.

conversation.handoff_to_third_party_failed Triggered when a handoff to a third-party platform (e.g. Zendesk, Intercom) fails.

workflow.run.succeeded Triggered when a workflow run completes successfully.

workflow.run.failed Triggered when a workflow run fails.

workflow.dispatch_failed Triggered when a phone call could not hand one of its lifecycle stages to the workflow engine at all — so the workflows listening on those triggers never ran, and no workflow.run.failed can follow (there is no run). This is the only signal for that failure mode; a stage whose workflows did run but failed produces workflow.run.failed instead, never both.

csat.requested Triggered when a CSAT survey is sent to a contact (via email, SMS, WhatsApp, Slack, or shown in the web widget).

csat.score_submitted Triggered when a customer submits or updates a CSAT score for a conversation.

Phone Call Events

These events are fired for phone calls — both calls handled by AI phone agents and human-only direct-ring calls (see is_human_call). They apply to both inbound and outbound calls. When a phone call starts, a conversation.started event is co-fired alongside phone_call.started. Phone calls do not emit conversation.closed — its chat-centric shape (closed_by, is_from_third_party, contact_reason, …) doesn’t map cleanly to a phone interaction. Listen on phone_call.ended instead, which carries the equivalent resolution and context fields below.
phone_call.started Triggered when a phone call is initiated — either an inbound call is received or an outbound call is placed. Also co-fires a conversation.started event.

phone_call.answered Triggered when the remote party picks up the call (SIP participant joined).

phone_call.ended Triggered when a phone call ends normally. This event carries all end-of-call context — resolution status, who hung up, the resolved contact, the agent’s configured languages, the call summary, and the session’s custom_data (SIP X-headers + call metadata) — so listeners do not need a separate conversation.closed event for phone calls. It is sent after the session’s post-call workflows (the Call Finished trigger) have run, so anything those workflows merge into the session’s custom data is on the payload — an end-of-call analysis, a classification, a score. Expect it a few seconds after the hangup, once those workflows finish.

phone_call.transferred Triggered when the AI agent transfers a call to another destination (phone number, SIP URI, or graceful hangup).

phone_call.failed Triggered when a phone call fails to connect. The failure_category field indicates the type of failure.