POST from klikit to a URL you host. Whenever something
happens on klikit that you care about — a new order, a status change, a cart
edit — klikit sends you the details. You don’t poll. You just answer the
phone when it rings.
The mental model
You host an endpoint
e.g.
https://api.yourcompany.com/integrations/klikit/webhooks. It needs
to be HTTPS, publicly reachable from klikit’s egress IPs, and capable of
handling a few requests per second per branch you operate.Your klikit operator registers the URL
They map your URL to a
(brand, branch, event) tuple. One URL per tuple
today — there’s no self-service registration. Send your URL +
environment to [email protected].An event happens on klikit
A customer places an order. An operator marks one as
READY. A cart is
edited mid-checkout. Klikit’s outbound webhook delivery service picks
up the event.Klikit POSTs to your URL
JSON body, signed with your webhook secret in the
x-klikit-signature
header. See Verify signatures for the
exact recipe.What you’ll receive
All three event types share the same JSON envelope:| Header | Purpose |
|---|---|
x-klikit-signature | hex(HMAC-SHA256(your webhook_secret, raw request body)) |
x-klikit-event-id | Unique per delivery attempt. Use for idempotency. |
x-klikit-event-type | One of the three event names. See Event catalogue. |
Content-Type | Always application/json. |
The three event types
klikit.order.created.v2
A new order just landed. Ring the kitchen.
klikit.order.status.updated
An order moved to a new state.
klikit.order.cart.updated
A cart was edited before checkout.
Five things you must get right
1. Read the raw body before parsing it
1. Read the raw body before parsing it
The HMAC is computed over the exact bytes klikit sent. If you parse the
JSON and re-serialise before verifying, key reordering or whitespace
differences will break the signature. Most frameworks have a “capture
the raw body” hook — see the reference receivers
for how.
2. Compare signatures in constant time
2. Compare signatures in constant time
Use
crypto.timingSafeEqual (Node), hmac.compare_digest (Python), or
your language’s equivalent. A naïve == is vulnerable to timing
side-channels.3. Be idempotent on x-klikit-event-id
3. Be idempotent on x-klikit-event-id
Klikit retries on any non-2xx, so the same
x-klikit-event-id will
arrive twice in some failure modes. Store the IDs you’ve already
processed (Redis SETNX, Postgres unique index, etc.) and silently
return 2xx for repeats.4. Acknowledge fast, do work async
4. Acknowledge fast, do work async
Klikit’s delivery timeout is 10 seconds. If your endpoint takes 11
seconds to push to a slow POS and then returns 200, klikit has already
counted it as a timeout and queued a retry — you’ll process every order
twice. Reply 200 immediately, then queue the work.
5. Return JSON or empty
5. Return JSON or empty
Klikit ignores the body of your response, but if you do return a body,
make it valid JSON to avoid logging noise on both sides.
Where to go from here
Verify signatures
Copy-pasteable HMAC verification in Node, Python, Go, PHP, and shell.
Event catalogue
What each event means, when it fires, what the payload looks like.
Troubleshooting
Symptom → cause table for the common integration failures.
Reference Node receiver
~80 lines, runs as-is, demonstrates all five musts.