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 signature is HMAC-SHA256 over
{timestamp}.{raw-body}. The key is your signing key, decoded from base64.
Get your signing key
- In the Quo app, open the webhook’s details page.
- Click the ellipsis (⋯) at the top right.
- Select Reveal signing secret.
- Copy the base64-encoded key and store it as a secret, such as an environment variable.
Verify a request
To verify a delivery:- Split the
openphone-signatureheader on;and read the timestamp and signature. - Reject the request if the timestamp is more than five minutes from the current time.
- Build the signed data: the timestamp, a
., then the raw request body. - Compute an HMAC-SHA256 digest of the signed data with the base64-decoded signing key, and encode it as base64.
- 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.
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
Every request fails verification
Every request fails verification
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.
Requests fail the timestamp check
Requests fail the timestamp check
The timestamp is in milliseconds. If you compare it with a clock in seconds, every request looks stale.
New webhooks fail verification
New webhooks fail verification
New webhooks, including replacements made with Duplicate as new webhook, use different headers and a
whsec_ key. Verify them with Validate webhook signatures.