Testing locally with ngrok
ngrok creates a public URL that tunnels to your local development server. Step 1: Start your local webhook endpoint (e.g., on port 3000). Step 2: Start ngrok:https://abc123.ngrok.io) and register it as a webhook endpoint:
Remember to update the webhook URL when your ngrok session restarts (the URL changes each time unless you use a paid plan with reserved domains).
Testing with webhook.site
webhook.site provides an instant URL that captures and displays webhook payloads — no local server needed.- Visit webhook.site and copy your unique URL.
- Register it as a Chameleon webhook endpoint.
- Trigger an Experience and inspect the payload on the webhook.site dashboard.
Verifying webhook signatures
Every Chameleon webhook includes anX-Chameleon-Signature header containing a SHA256-HMAC of the request body, signed with your Webhook Secret.
Always verify signatures in production to ensure webhooks are genuinely from Chameleon.
Verification steps
- Retrieve your Webhook Secret from Settings → Webhooks.
- Compute the SHA256-HMAC of the raw request body using your secret.
- Compare the computed signature with the
X-Chameleon-Signatureheader. - Reject the request if signatures don’t match (respond with
400). - Optionally, check that
sent_atis within a few minutes of the current time to prevent replay attacks.
Node.js example
Rails example
Python example
Retry behavior
When Chameleon doesn’t receive a2xx response from your webhook endpoint:
- Chameleon retries a total of 9 times over approximately 43 hours.
- Retries use exponential backoff, giving you time to fix errors without losing webhooks.
- Chameleon sends webhooks from specific IP addresses — you can allowlist these in your firewall.
Debugging checklist
If webhooks aren’t arriving as expected:- Check the endpoint URL — Ensure it’s HTTPS and publicly accessible (not
localhost). - Check the response code — Your endpoint must respond with a
2xxstatus code. Non-2xx triggers retries. - Respond quickly — Process webhooks asynchronously. Return
200immediately, then handle the payload in a background job. - Check the topics — Verify the webhook is registered for the topics you expect. See webhook topics.
- Check the Chameleon dashboard — View webhook delivery status at Settings → Webhooks.
- Verify the signature — If you’re rejecting requests, ensure your verification code uses the correct secret and processes the raw (not parsed) body.
- Check IP allowlisting — If your server restricts incoming IPs, add the Chameleon IP addresses.
- Outgoing Webhooks — full reference for topics, schemas, and payload examples
- Webhook API — manage webhook endpoints via REST API

