Skip to main content
This is the how do I do this page. The Quickstart shows you how to make a first call; this page shows you the order to do things in, what to ship in week 1 vs week 4, and how to know you’re done.

Who reads which path

You areReadSkip
A POS / kitchen system receiving klikit ordersPhases 1, 2, 3-POS, 4, 53-Aggregator
An aggregator / marketplace consuming klikit menus and pushing visibilityPhases 1, 2, 3-Aggregator, 4, 53-POS
Phase 4 (webhooks) is for both. Phase 5 (production checklist) is for both.

Phase 1 — Foundation

The flat work: get credentials, understand the contract, point at the right environment.
  1. Get credentials from your klikit integration contact. You’ll receive a partner_key, a secret_key, and (if you’ll receive webhooks) a webhook_secret. Treat them like passwords; rotate via support if you suspect a leak. See Authentication.
  2. Pick your environment. The development environment is your sandbox — there is no separate staging tier. See Environments.
    • Dev: https://api.dev.shadowchef.co/v1/partner
    • Prod: https://gateway-enterprise.klikit.io/v1/partner
  3. Confirm scopes. Your credential is granted a fixed subset of scopesorders:read, menus:read, menus:oos, etc. Hit one endpoint per scope you need and confirm 200 before designing around it.
  4. Read the response envelope and error codes. Both are short. Doing this now saves a week of “but the response shape is weird” tickets.
Done when: curl -u "$KEY:$SECRET" $BASE/brands returns 200 with a real data block.

Phase 2 — Map your business

Before any integration logic, build a local picture of what you’re working with. Klikit’s hierarchy is business → brands → branches, and every other id you’ll see references one of those three.

GET /v1/partner/brands

Returns the brand catalogue for your business. Each entry has id, business_id, title, logo, banner. Cache this; it changes weekly, not hourly.
curl -sS -u "$KEY:$SECRET" "$BASE/brands"

GET /v1/partner/branches

Returns the physical/virtual stores under your business — addresses, opening hours, currency, supported order types, payment methods, geo coordinates. Paginated with page/size. Critical fields: id, brand_id, currency_code, lat, long, status, payment_methods, available_times.
curl -sS -u "$KEY:$SECRET" "$BASE/branches?page=1&size=20"
Done when: you have a local table mapping {brand_id, branch_id} → your internal store id. This mapping is the joinkey for everything in phase 3.

Phase 3 — Pick your starting module

This is the branch in the road.

Path A — POS / kitchen system

You want orders to flow from klikit into your POS, and status updates to flow back. Two modules to wire, in this order. A1. Read orders
  • GET /v1/partner/orders?page=1&size=20 returns the order list, reverse-chronological. Use from / to (max 90-day window) to bound by created_at.
  • GET /v1/partner/orders/{id} returns the full order — cart, customer, payment, fulfillment details. Use this on every order you intend to process; the list response is rich but the detail call is canonical.
  • Decode status via GET /orders/statuses — IDs are stable across releases.
A2. Write order status
  • PATCH /v1/partner/orders/{id}/status transitions an order through accepted → ready → picked_up (or terminal rejected / cancelled). Cancellations need a reason_code. Always send Idempotency-Key — see Idempotency.
curl -X PATCH -u "$KEY:$SECRET" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"status":"accepted"}' \
  "$BASE/orders/12345/status"
Done when: you can ingest a test order from dev, mark it accepted, then ready, then picked_up, with the changes reflecting in klikit’s admin UI.

Path B — Aggregator / marketplace

You want klikit menus on your surface, and you want to be able to toggle items in/out of stock and hide branches. Three modules, in this order. B1. Read menus
  • GET /v1/partner/menus?brand_id=&branch_id= returns the store-level menu — sections → categories → items → modifier groups → modifier options — with all store-specific overrides applied. This is what to display to your customers.
  • GET /v1/partner/menus (no params) returns the business-level menu — no store overrides. Useful for cataloguing across stores.
curl -sS -u "$KEY:$SECRET" "$BASE/menus?brand_id=1100&branch_id=1293"
B2. Push availability (out-of-stock)
  • PATCH /v1/partner/items/{partner_item_id}/availability flips a single item in or out of stock. Bulk variant available. Send Idempotency-Key on every call.
B3. Push visibility
  • Branch and brand visibility toggles let you hide a store or an entire brand from your surface without affecting other partners. See the API reference under visibility.
Done when: a menu pulled at 9am, after an OOS toggle at 9:01, shows the item correctly flagged at 9:02 either via re-pull or via webhook (phase 4).

Phase 4 — Add real-time (webhooks)

Polling works for development. Production wants pushes. Klikit emits three webhook event types and you subscribe by giving your klikit operator a receiver URL per (brand, branch, event) tuple.
EventWhen it firesSubscribe if
klikit.order.created.v2A new order landsYou’re a POS (mandatory)
klikit.order.status.updatedAn order moves to a new stateYou’re a POS (recommended)
klikit.order.cart.updatedThe cart changes pre-checkoutYou preview baskets pre-checkout (optional)
The whole webhook story has its own section: Done when: your receiver verifies the signature, deduplicates on x-klikit-event-id, and acknowledges with 2xx in <1s. Test by asking your operator to replay a failed delivery from hookit.webhook_logs.

Phase 5 — Production readiness checklist

Before you flip the base URL from api.dev.shadowchef.co to gateway-enterprise.klikit.io:
  • Production credentials issued by your klikit contact (separate from dev).
  • webhook_secret stored in your secrets manager, not in source.
  • Rotation runbook on file. Old secret stays valid for 15 minutes after rotation — schedule rotations during low-traffic windows.
  • Every write call sends a fresh Idempotency-Key (UUID) per logical action.
  • Retries reuse the same key on the same action; never regenerate mid-retry.
  • Exponential backoff with jitter: 500ms → 30s, max 5 attempts.
  • You only retry on RATE_LIMITED, DOWNSTREAM_UNAVAILABLE, INTERNAL, and network timeouts. You do not retry on REQUEST_INVALID or FORBIDDEN_SCOPE.
  • Endpoint is HTTPS, publicly reachable from klikit’s egress, returns 2xx within 1 second (process async).
  • HMAC-SHA256 verification of x-klikit-signature against the raw request body (not the parsed-and-reserialised JSON).
  • Idempotency keyed on x-klikit-event-id in a persistent store (Redis SETNX, Postgres unique index — not an in-memory Set).
  • 10-second timeout budget understood; processing pushed to a durable queue if downstream is slow.
  • Every klikit response’s top-level request_id is captured in your logs alongside the operation it represented.
  • You can quote any request_id to [email protected] and have us find the request end-to-end.
  • On webhook deliveries, you log x-klikit-event-id for the same reason.
  • Brands and branches cached locally with a re-fetch interval that matches your business reality (daily is usually fine).
  • Menus refreshed on webhook signal or, if not subscribed, polled at a cadence your klikit operator agrees with (typically every 5 minutes for active stores).
  • Order list polled with from / to no wider than 90 days per call.
  • You alert on a sustained 5xx rate from klikit (DOWNSTREAM_UNAVAILABLE, INTERNAL).
  • You alert on rising 4XX (especially FORBIDDEN_SCOPE — usually means a scope was revoked).
  • Webhook delivery success rate visible on a dashboard; failures paged.
  • At least one end-to-end test in production with your klikit contact observing, against a real (or staging) branch.
  • Cancellation path tested with a real reason_code.
  • Rotation, replay, and dispute runbooks reviewed with your klikit contact.
When all of those are checked, you’re done. Flip the base URL.

Where to next

Quickstart

5-minute hands-on, if you haven’t already.

Webhooks integration guide

Full receiver-side recipe.

API reference

Endpoint-by-endpoint, with real prod responses embedded.

Reference receivers

Copy-paste Node and Python webhook servers.