Skip to main content

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.
Use these endpoints to create, manage, test, and inspect webhooks created with the beta API. Endpoints are grouped into CRUD (create/read/update/delete) and Testing & debugging.
Webhooks created through these endpoints are managed through these endpoints and do not appear in the Quo app webhook settings during the beta.
Every request requires your Public API key and the API version header:
Authorization: YOUR_API_KEY
x-quo-api-version: 2026-03-30

Endpoint index

CRUD:
MethodPathPurpose
GET/webhooksList webhooks for the workspace.
POST/webhooksCreate a webhook.
GET/webhooks/:idGet a webhook.
PATCH/webhooks/:idUpdate a webhook.
DELETE/webhooks/:idDelete a webhook.
POST/webhooks/:id/rotateRotate the signing secret.
Testing & debugging:
MethodPathPurpose
POST/webhooks/:id/events/testSend a test event to the webhook URL.
GET/webhooks/:id/eventsList deliveries.
GET/webhooks/:id/events/:eventIdGet delivery detail including all attempts.
POST/webhooks/:id/events/:eventId/retryRetry a delivery.

Supported event types

Event typeWhen it fires
message.receivedAn inbound SMS, MMS, or message was received by a Quo number.
message.deliveredAn outbound message was delivered.
call.summary.completedA call summary finished generating.
call.transcript.completedA call transcript finished processing.
contact.updatedA contact was created or its fields changed.
contact.deletedA contact was deleted.
For payload shapes, see Webhook event payloads.

List webhooks

curl https://api.openphone.com/webhooks \
  -H "Authorization: YOUR_API_KEY" \
  -H "x-quo-api-version: 2026-03-30"
Returns all webhooks created through the beta webhook endpoints for the workspace. This endpoint is not paginated.
{
  "data": [
    {
      "id": "123",
      "orgId": "OR123",
      "label": "Production webhook",
      "status": "enabled",
      "url": "https://example.com/webhooks/quo",
      "createdAt": "2026-04-13T12:00:00.000Z",
      "updatedAt": "2026-04-13T12:00:00.000Z",
      "events": ["call.summary.completed", "contact.updated"],
      "resourceIds": ["PNabc123"],
      "apiVersion": "2026-03-30"
    }
  ]
}

Get a webhook

curl https://api.openphone.com/webhooks/123 \
  -H "Authorization: YOUR_API_KEY" \
  -H "x-quo-api-version: 2026-03-30"
{
  "data": {
    "id": "123",
    "orgId": "OR123",
    "label": "Production webhook",
    "status": "enabled",
    "url": "https://example.com/webhooks/quo",
    "createdAt": "2026-04-13T12:00:00.000Z",
    "updatedAt": "2026-04-13T12:00:00.000Z",
    "events": ["call.summary.completed", "contact.updated"],
    "resourceIds": ["PNabc123"],
    "apiVersion": "2026-03-30"
  }
}

Create a webhook

curl https://api.openphone.com/webhooks \
  -X POST \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "x-quo-api-version: 2026-03-30" \
  -d '{
    "url": "https://example.com/webhooks/quo",
    "events": ["call.summary.completed", "message.received", "contact.updated"],
    "resourceIds": ["PNabc123"],
    "label": "Production webhook",
    "status": "enabled"
  }'
FieldTypeRequired?Description
urlstringYesPublic HTTPS endpoint that receives webhook deliveries.
eventsstring[]YesOne or more supported event types. Message, call summary, call transcript, and contact events can be mixed.
resourceIdsstring[]NoPhone number ids for message, call summary, and call transcript filtering, or ["*"] for all. Defaults to ["*"]. Contact events are always workspace-wide.
labelstringNoHuman-readable label.
status"enabled" | "disabled"NoDefaults to enabled.
The response includes the whsec_… signing secret. Save it as an environment variable — see Validate webhook signatures.
{
  "data": {
    "id": "123",
    "orgId": "OR123",
    "label": "Production webhook",
    "status": "enabled",
    "url": "https://example.com/webhooks/quo",
    "key": "whsec_...",
    "createdAt": "2026-04-13T12:00:00.000Z",
    "updatedAt": "2026-04-13T12:00:00.000Z",
    "events": ["call.summary.completed", "message.received", "contact.updated"],
    "resourceIds": ["PNabc123"],
    "apiVersion": "2026-03-30"
  }
}

Update a webhook

curl https://api.openphone.com/webhooks/123 \
  -X PATCH \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "x-quo-api-version: 2026-03-30" \
  -d '{
    "events": ["call.summary.completed", "contact.updated"],
    "resourceIds": ["PNabc123"],
    "label": "Updated webhook"
  }'
All fields are optional. Provide only the fields you want to change.
FieldTypeDescription
urlstringReplaces the webhook URL.
eventsstring[]Replaces the subscribed event types.
resourceIdsstring[] | nullReplaces the phone number filters for message, call summary, and call transcript events. Send null, [], or ["*"] to clear filtering.
labelstring | nullReplaces the label. Send null to clear it.
status"enabled" | "disabled"Enables or disables delivery.

Delete a webhook

curl https://api.openphone.com/webhooks/123 \
  -X DELETE \
  -H "Authorization: YOUR_API_KEY" \
  -H "x-quo-api-version: 2026-03-30"
Returns 204 No Content on success.

Rotate the signing secret

curl https://api.openphone.com/webhooks/123/rotate \
  -X POST \
  -H "Authorization: YOUR_API_KEY" \
  -H "x-quo-api-version: 2026-03-30"
{
  "data": { "key": "whsec_..." }
}
Store the new key and use it for future signature verification. See Validate webhook signatures.

Send a test event

Sends a real, signed delivery to your webhook URL — the same as a production event — and returns the sample payload inline so you can inspect it without waiting for the delivery to land.
curl https://api.openphone.com/webhooks/123/events/test \
  -X POST \
  -H "Authorization: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "x-quo-api-version: 2026-03-30" \
  -d '{ "eventType": "message.received" }'
eventType must be one of the supported event types. The response is the sample payload sent to your webhook URL. Delivery is asynchronous; use GET /webhooks/:id/events to find the delivery id and inspect what your endpoint returned.
{
  "id": "EV-test-message-received",
  "apiVersion": "2026-03-30",
  "createdAt": "2026-03-30T18:00:00.000Z",
  "type": "message.received",
  "data": {
    "resource": {
      "id": "ACsampleactivity0000000000000000",
      "direction": "incoming",
      "text": "Hello from Quo! This is a sample message.",
      "status": "received",
      "createdAt": "2026-03-30T18:00:00.000Z"
    },
    "context": {
      "phoneNumberId": "PNsamplephonenumber000000000000",
      "conversationId": "CNsampleconversation000000000000",
      "userId": "USsampleus",
      "contacts": { "ids": ["CTsampleContact01234"], "lookupStatus": "matched" },
      "senderIdentifier": "+15555551234",
      "recipientIdentifiers": ["+15555555678"]
    },
    "links": { "quo": "https://my.quo.com/..." }
  }
}

List deliveries

curl "https://api.openphone.com/webhooks/123/events?limit=10" \
  -H "Authorization: YOUR_API_KEY" \
  -H "x-quo-api-version: 2026-03-30"
ParameterTypeDescription
limitnumberPage size.
afterstringCursor from the previous response’s nextCursor.
status"success" | "pending" | "sending" | "failed"Filter by delivery status.
eventTypesstring[]Restrict results to specific event types.
createdBeforeISO-8601 stringOnly include deliveries created before this time.
createdAfterISO-8601 stringOnly include deliveries created after this time.
Delivery statuses:
StatusMeaning
successAt least one delivery attempt returned a 2xx response.
pendingDelivery is queued and has not attempted yet.
sendingDelivery is in progress or waiting for a retry attempt.
failedAll retry attempts have been exhausted without a 2xx response.
{
  "data": [
    {
      "id": "msg_2abcDEFghiJKLmnoPQRstu",
      "eventType": "message.received",
      "status": "success",
      "nextAttemptAt": null,
      "createdAt": "2026-04-13T12:00:00.000Z"
    }
  ],
  "nextCursor": "eyJsYXN0SWQiOiJtc2dfMmFiY0RFRmdoaUpLTG1ub1BRUnN0dSJ9"
}

Get delivery detail

curl https://api.openphone.com/webhooks/123/events/msg_2abcDEFghiJKLmnoPQRstu \
  -H "Authorization: YOUR_API_KEY" \
  -H "x-quo-api-version: 2026-03-30"
Delivery detail includes the request body and all attempts, ordered most-recent first.
{
  "data": {
    "id": "msg_2abcDEFghiJKLmnoPQRstu",
    "eventType": "message.received",
    "createdAt": "2026-04-13T12:00:00.000Z",
    "requestBody": {
      "id": "EV123",
      "apiVersion": "2026-03-30",
      "createdAt": "2026-04-13T12:00:00.000Z",
      "type": "message.received",
      "data": {
        "resource": {
          "id": "AC-message",
          "direction": "incoming",
          "text": "hello",
          "status": "received",
          "createdAt": "2026-04-13T12:00:00.000Z"
        },
        "context": {
          "phoneNumberId": "PN123",
          "conversationId": "CN123",
          "userId": "US123",
          "contacts": { "ids": ["CT123"], "lookupStatus": "matched" },
          "senderIdentifier": "+15550001111",
          "recipientIdentifiers": ["+15550002222"]
        },
        "links": { "quo": "https://my.quo.com/inbox/..." }
      }
    },
    "attempts": [
      {
        "id": "atmpt_2abcDEFghiJKLmnoPQRstu",
        "timestamp": "2026-04-13T12:00:01.000Z",
        "status": "success",
        "responseStatusCode": 200,
        "responseBody": "{\"ok\":true}",
        "responseDurationMs": 123,
        "triggerType": "scheduled",
        "url": "https://example.com/webhooks/quo"
      }
    ]
  }
}

Retry a delivery

curl https://api.openphone.com/webhooks/123/events/msg_2abcDEFghiJKLmnoPQRstu/retry \
  -X POST \
  -H "Authorization: YOUR_API_KEY" \
  -H "x-quo-api-version: 2026-03-30"
The retry is queued asynchronously and returns 202 Accepted. Use GET /webhooks/:id/events/:eventId to inspect the new attempt.

See also