> ## 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.

# Migrate from legacy webhooks

> Move webhooks created through the v1 API to new webhooks.

New webhooks replace legacy webhooks that you created with the `/v1/webhooks` endpoints. Event names do not change, but the payload shape, the signature headers, and the signing secret do.

## What changes

| Area | Legacy | New |
| - | - | - |
| Payload | `data.object` | `data.resource`, `data.context`, and `data.links` |
| Signature | `OpenPhone-Signature` header | `webhook-id`, `webhook-timestamp`, and `webhook-signature` headers |
| Signing secret | Legacy key | `whsec_…` key. The [`svix`](https://www.npmjs.com/package/svix) library verifies it. |
| API endpoints | One `/v1/webhooks/*` endpoint for each event family | One `POST /webhooks` with an `events` array |

## Update your endpoint

Before you enable a new webhook, make these changes:

* Parse the new payloads. See [Webhook event payloads](/docs/2026-03-30/webhooks-event-payloads).
* Verify the new signature headers. Code that verifies the legacy `OpenPhone-Signature` header rejects every new delivery. See [Validate webhook signatures](/docs/2026-03-30/webhooks-signature-validation).

Your endpoint continues to receive legacy deliveries until you switch. Accept both formats at the same URL, or give the new webhook a different URL.

## Migrate a v1 API webhook

<Steps>
  <Step title="Find your legacy webhooks">
    Call `GET /v1/webhooks` to get the URL, events, and `resourceIds` of each webhook. You can combine webhooks that send to the same URL into one new webhook.
  </Step>

  <Step title="Create the replacement, disabled">
    ```bash theme={null}
    curl https://api.quo.com/webhooks \
      -X POST \
      -H "Authorization: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -H "Quo-Api-Version: 2026-03-30" \
      -d '{
        "url": "https://example.com/webhooks/quo",
        "events": ["message.received", "call.completed"],
        "resourceIds": ["PN123"],
        "status": "disabled"
      }'
    ```

    Keep the `key` field from the response. It is the new signing secret.
  </Step>

  <Step title="Test your endpoint">
    For each event type that you subscribe to, send a test event with [`POST /webhooks/:id/events/test`](/docs/2026-03-30/webhook-events/send-a-test-event-to-a-webhook). Put the event type in `eventType`, for example `{ "eventType": "message.received" }`.

    Quo sends a signed request with sample data to your URL. Make sure that your endpoint verifies the signature and returns a `2xx` response. `GET /webhooks/:id/events` shows each test delivery and the response from your endpoint.
  </Step>

  <Step title="Switch to the replacement">
    <Warning>
      Do not delete the legacy webhook until your tests pass. You cannot restore a deleted v1 webhook.
    </Warning>

    Delete the legacy webhook, then enable the replacement immediately. Events that occur between the two calls are not delivered.

    ```bash theme={null}
    curl https://api.quo.com/v1/webhooks/{legacyId} \
      -X DELETE \
      -H "Authorization: YOUR_API_KEY"

    curl https://api.quo.com/webhooks/{id} \
      -X PATCH \
      -H "Authorization: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -H "Quo-Api-Version: 2026-03-30" \
      -d '{ "status": "enabled" }'
    ```
  </Step>
</Steps>
