Skip to main content
This page is for legacy webhooks only. Legacy webhooks are being retired. If your deliveries include webhook-id, webhook-timestamp, and webhook-signature headers, you have a new webhook. Use Validate webhook signatures instead. To move off legacy webhooks, follow the migration guide.

Overview

Legacy webhooks are the webhooks created in Settings → Webhooks in the Quo app before the new webhook system launched, or with the /v1/webhooks endpoints. Legacy webhooks are not the same thing as version v1 of the API. To tell which kind of webhook you have, check the headers on a delivery. Quo signs each legacy delivery with one header, openphone-signature. Legacy deliveries do not include the webhook-id, webhook-timestamp, or webhook-signature headers. The Send test request option for a legacy webhook uses the same signing key and header format as live deliveries.

Signature format

The header has four fields, separated by semicolons: The signature is HMAC-SHA256 over {timestamp}.{raw-body}. The key is your signing key, decoded from base64.

Get your signing key

  1. In the Quo app, open the webhook’s details page.
  2. Click the ellipsis (⋯) at the top right.
  3. Select Reveal signing secret.
  4. Copy the base64-encoded key and store it as a secret, such as an environment variable.

Verify a request

To verify a delivery:
  1. Split the openphone-signature header on ; and read the timestamp and signature.
  2. Reject the request if the timestamp is more than five minutes from the current time.
  3. Build the signed data: the timestamp, a ., then the raw request body.
  4. Compute an HMAC-SHA256 digest of the signed data with the base64-decoded signing key, and encode it as base64.
  5. Compare your digest with the signature from the header. Accept the request only if they match.
Use the raw request body bytes. If your framework parses the JSON body before you verify it, re-serializing it can change the bytes and make verification fail.
Respond with a 2xx status code within 10 seconds. Quo retries a delivery when your endpoint returns any other status code or does not respond in time.

Example handlers

Troubleshooting

Check that you decode the signing key from base64 before you use it as the HMAC key, and that you sign the raw body rather than a re-serialized copy. Also check that you copied the key from the same webhook that sends the requests.
The timestamp is in milliseconds. If you compare it with a clock in seconds, every request looks stale.
New webhooks, including replacements made with Duplicate as new webhook, use different headers and a whsec_ key. Verify them with Validate webhook signatures.