Symptom → cause
Every request fails verification with 401 invalid signature
Every request fails verification with 401 invalid signature
Three likely causes, in order of probability:
-
You’re hashing the parsed body, not the raw body. Most web
frameworks parse JSON automatically and then
JSON.stringifyit back for you — but the bytes differ from what klikit sent (key order, whitespace). Capture the raw bytes before parsing. See the reference Node receiver for theexpress.json({ verify })trick, or the Python one forrequest.get_data(cache=True). -
Wrong secret. Confirm
KLIKIT_WEBHOOK_SECRETin your env matches what your operator gave you. Don’t paste it through a shell that might strip a trailing newline. - Reverse proxy is rewriting the body. Some WAFs / API gateways re-encode JSON. If you’re behind one, turn off body transformation for the webhook path, or verify before the proxy in front of your app.
My handler gets called twice for the same order
My handler gets called twice for the same order
This means your previous delivery returned non-2xx or timed out, so
klikit retried. The retry uses the same Use a persistent store (Redis SETNX, Postgres unique index) — an
in-memory set evaporates on every restart and lets duplicates back in.
x-klikit-event-id. Make
your handler idempotent on that header:Klikit support says deliveries are failing but I don't see them in my logs
Klikit support says deliveries are failing but I don't see them in my logs
Klikit’s webhook delivery service has a hard 10-second timeout. If
your endpoint is slow but eventually returns 200, klikit has already
counted it as a timeout, given up, and queued a retry. Your access logs
will show the 200 — but klikit’s view is “delivery failed”.Fix: acknowledge in
<1 second by replying 200 first, then doing
the actual work on a background queue. The reference receivers both do
this via setImmediate (Node) or a thread (Python).The x-klikit-* headers don't reach my app
The x-klikit-* headers don't reach my app
Almost always a reverse-proxy or CDN stripping unknown headers. Common
culprits:
- nginx with
underscores_in_headers off(the default) drops headers with underscores — but klikit uses hyphens, so checkproxy_pass_request_headers onand that you aren’t strippingx-*. - Cloudflare strips some headers in WAF rules — check Rules → Transform Rules.
- AWS API Gateway has an explicit allow-list for forwarded headers.
tcpdump or your proxy’s access log with full headers to confirm
klikit is sending them; then walk back through your stack to find
where they get dropped.I changed something and now klikit isn't delivering at all
I changed something and now klikit isn't delivering at all
Most likely your URL changed but the registration didn’t. Webhook URLs
are registered out-of-band by your klikit operator. If you migrated
domains or paths, send the new URL + the brand/branch ids to
[email protected] and we’ll
update the registration.To replay anything that was attempted against the old URL in the
meantime, ask your operator to replay from
hookit.webhook_logs.I want to test against the dev environment without exposing my server
I want to test against the dev environment without exposing my server
Two options:
- Forward your local port to a public URL with
ngrokorcloudflared tunnel, and give your klikit operator the temporary URL. The tunnel terminates TLS for you, and the local Node / Python reference receiver runs as-is. - Run the reference receiver locally and replay captured deliveries
with
curl(see Verify signatures for the recipe). This validates the verifier without needing klikit to reach you.
Still stuck?
Open a ticket with [email protected] and include:- The
x-klikit-event-idof a failing delivery (we can look it up inhookit.webhook_logs). - The HTTP status your endpoint returned, or whether the delivery timed out.
- A small reproducer if you have one — even pseudo-code helps.