> ## Documentation Index
> Fetch the complete documentation index at: https://developer.klikit.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Integration playbook

> From zero to production, phase by phase. Branched paths for POS systems and aggregator marketplaces.

This is the **how do I do this** page. The [Quickstart](/partner-api/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 are                                                                       | Read                            | Skip         |
| ----------------------------------------------------------------------------- | ------------------------------- | ------------ |
| A **POS / kitchen system** receiving klikit orders                            | Phases 1, 2, 3-POS, 4, 5        | 3-Aggregator |
| An **aggregator / marketplace** consuming klikit menus and pushing visibility | Phases 1, 2, 3-Aggregator, 4, 5 | 3-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](/partner-api/authentication).
2. **Pick your environment.** The development environment **is** your
   sandbox — there is no separate staging tier. See
   [Environments](/partner-api/concepts/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
   [scopes](/partner-api/concepts/scopes) — `orders: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](/partner-api/concepts/envelope) and
   [error codes](/partner-api/concepts/errors).** 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.

```bash theme={null}
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`.

```bash theme={null}
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`](/partner-api/api-reference/listOrderStatuses)
  — 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](/partner-api/concepts/idempotency).

```bash theme={null}
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.

```bash theme={null}
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](/partner-api/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.

| Event                         | When it fires                 | Subscribe if                                |
| ----------------------------- | ----------------------------- | ------------------------------------------- |
| `klikit.order.created.v2`     | A new order lands             | You're a POS (mandatory)                    |
| `klikit.order.status.updated` | An order moves to a new state | You're a POS (recommended)                  |
| `klikit.order.cart.updated`   | The cart changes pre-checkout | You preview baskets pre-checkout (optional) |

The whole webhook story has its own section:

* [Webhooks overview](/partner-api/webhooks/overview) — concepts and
  five-things-you-must-get-right.
* [Verify signatures](/partner-api/webhooks/verify) — HMAC recipe in 5
  languages.
* [Event catalogue](/partner-api/webhooks/events) — payload shapes per
  event.
* [Node](/partner-api/examples/node-receiver) and
  [Python](/partner-api/examples/python-receiver) reference receivers.

**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`:

<AccordionGroup>
  <Accordion title="Credentials & secrets">
    * 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.
  </Accordion>

  <Accordion title="Retries & idempotency">
    * 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`.
  </Accordion>

  <Accordion title="Webhook receiver">
    * 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.
  </Accordion>

  <Accordion title="Logging & support">
    * 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 [integrations@klikit.io](mailto:integrations@klikit.io) and have us
      find the request end-to-end.
    * On webhook deliveries, you log `x-klikit-event-id` for the same
      reason.
  </Accordion>

  <Accordion title="Data freshness">
    * 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.
  </Accordion>

  <Accordion title="Observability">
    * 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.
  </Accordion>

  <Accordion title="Sign-off">
    * 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.
  </Accordion>
</AccordionGroup>

When all of those are checked, you're done. Flip the base URL.

***

## Where to next

<CardGroup cols={2}>
  <Card title="Quickstart" icon="bolt" href="/partner-api/quickstart">
    5-minute hands-on, if you haven't already.
  </Card>

  <Card title="Webhooks integration guide" icon="webhook" href="/partner-api/webhooks/overview">
    Full receiver-side recipe.
  </Card>

  <Card title="API reference" icon="book" href="/partner-api/api-reference">
    Endpoint-by-endpoint, with real prod responses embedded.
  </Card>

  <Card title="Reference receivers" icon="code" href="/partner-api/examples/node-receiver">
    Copy-paste Node and Python webhook servers.
  </Card>
</CardGroup>
