Documentation Index
Fetch the complete documentation index at: https://www.quo.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
This is the beta webhook API, available in open beta. For the existing webhook system, see Legacy webhooks.
- Update your CRM when an inbound SMS arrives (
message.received). - Trigger a workflow when a call summary is ready (
call.summary.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.
| Field | Meaning |
|---|---|
id | Stable identifier for the event across retries and payload versions. Not a delivery identifier — for delivery-level dedupe, use the webhook-id header. |
apiVersion | Payload version recorded when the webhook was created. |
createdAt | When the underlying event occurred. The send time is in the webhook-timestamp header. |
type | The event name. Discriminates the schema of data. |
data.resource | Primary business object for the event. |
data.context | Surrounding metadata (phone number, conversation, participants, contact lookup, sharing). |
data.links.quo | Quo app deep link, or null when none is available. |
Versioning policy
- Format. Versions are date strings (
YYYY-MM-DD). The current version is2026-03-30. - Stability. A webhook’s version is recorded at creation and never changes for that subscription. Existing deliveries continue using the version they were created with.
- Pinning. Set
x-quo-api-versionwhen callingPOST /webhooks. Future versions may add event types or make breaking payload changes; new deliveries use the older shape until you create a new subscription on the newer version.
Subscription rules
message.*,call.summary.*, andcall.transcript.*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 created with the beta API.
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.
| Attempt | Delay from previous | Cumulative |
|---|---|---|
| 1 | Immediate | 0 |
| 2 | 5 seconds | 5s |
| 3 | 5 minutes | 5m 5s |
| 4 | 30 minutes | 35m 5s |
| 5 | 2 hours | 2h 35m 5s |
| 6 | 5 hours | 7h 35m 5s |
| 7 | 10 hours | 17h 35m 5s |
| 8 | 10 hours | 27h 35m 5s |
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
| Header | Format | Purpose |
|---|---|---|
webhook-id | string | Idempotency key. Stable across retries. |
webhook-timestamp | unix seconds | When Quo signed the request. |
webhook-signature | v1,<base64> (space-separated entries) | HMAC-SHA256 over {webhook-id}.{webhook-timestamp}.{raw-body}. |