KanalKanal API
Getting started

Idempotency

How upserts use your external_id as a natural key.

The API is upsert-based. You don't need to track whether a record already exists in Kanal — you send the full object and Kanal creates or updates it.

The natural key

Every resource is uniquely identified by the pair:

(store_id, external_id)

external_id is your identifier — your order number, checkout token, or customer id. Send the same external_id again and Kanal updates the existing record instead of creating a duplicate.

For customers, external_id is optional. If you omit it, the customer's phone becomes the natural key.

Create vs. update response

POST endpoints tell you which happened via the HTTP status:

StatusMeaning
201 CreatedFirst time Kanal saw this external_id
200 OKAn existing record was updated

Both return the same JSON body, so you can safely treat them the same way.

Partial updates

POST replaces the resource. To change only a few fields on an existing order or checkout, use the PATCH endpoint instead:

Mark an order as paid
curl -X PATCH https://api.getkanal.com/api/v1/stores/123/orders/ORDER-1001 \
  -H "Authorization: Bearer kanal_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "financial_status": "paid" }'

PATCH accepts only the mutable fields (financial_status, fulfillment_status, tags, metadata for orders; status, recovery_url, tags, metadata for checkouts) and leaves everything else untouched.

Safe retries

Because writes are keyed on (store_id, external_id), retrying a failed or timed-out request is always safe — replaying the same payload converges to the same state and never creates a duplicate. Retry network and 5xx errors freely with exponential backoff.

On this page