- Update your CRM when an inbound SMS arrives (
message.received). - Log calls in your system as soon as they end (
call.completed), with AI summaries and transcripts following (call.summary.completed,call.transcript.completed). - Sync contact changes between Quo and your system (
contact.updated).
Common envelope
Every webhook delivery uses the same top-level shape. Thetype field determines the schema of data.
Treat all event, delivery, and resource ids as opaque strings.
Versioning policy
Webhooks follow the same dated versioning as the rest of the API, with one addition: a subscription pins its payload version at creation.- Pinning. Set
Quo-Api-Versionwhen callingPOST /webhooks. That version is recorded for the subscription and used for every delivery it makes. - Stability. A webhook’s version never changes after creation. Existing deliveries keep the shape they were created with, even after newer versions ship.
- Adopting a new version. Create a new subscription on the newer version. Deliveries to the existing subscription are unaffected.
Subscription rules
message.*andcall.*events accept aresourceIdsfilter (phone number ids, or["*"]).contact.*events are workspace-wide. For contact-only webhooks, omitresourceIds.- Mixed subscriptions are supported.
resourceIdsfilters the activity events above; contact events are always delivered workspace-wide. - A workspace can have at most 50 webhooks.
Delivery semantics
Idempotency
Quo will retry deliveries on any non-2xx response, so your endpoint must tolerate seeing the same delivery more than once. Use the webhook-id header as an idempotency key — it is stable across retries and distinct from the envelope id.
Retries
Failed deliveries are retried automatically. Any2xx response marks a delivery accepted; any non-2xx response triggers the next retry. After all retries fail, the delivery is marked failed and not retried further.
If every attempt fails, the delivery is marked failed after roughly 27 hours and 35 minutes from the initial attempt.
You can also trigger a manual retry with
POST /webhooks/:id/events/:eventId/retry.
Ordering
Delivery order is not guaranteed. Events can arrive out of order across event families and, occasionally, within a single resource — for example, acall.transcript.completed may arrive before the corresponding call.summary.completed.
Design handlers to be order-independent:
- Compare
data.resource.updatedAt(orcreatedAtfor terminal events) against your stored state and ignore stale events. - Don’t drive state machines from arrival order. Treat each event as a freshness check on the resource it references.
Headers on every delivery
Always verify the signature before trusting the body. See Validate webhook signatures.