Customer orders and order management
Delete kitchen dispatch item
Remove a single item from an order. Disallowed when the item is already paid or has a settlement in progress.
path Parameters
idKitchen dispatch item UUID
Delete kitchen dispatch item › Responses
Successfully deleted item
statusGet split order items
Get all items that were split from an order item for bill splitting
path Parameters
idKitchen dispatch item UUID (the split_of_kitchen_dispatch_item reference)
Get split order items › Responses
Successfully retrieved split items
statusSplit order item
Split an order item into multiple parts for bill splitting with equal pricing
path Parameters
idKitchen dispatch item UUID
Split order item › Request Body
numberOfPartsNumber of parts to split the item into (2-10)
tabIdTab UUID that the item belongs to
Split order item › Responses
Successfully split the item
statusToggle takeaway status
Void a kitchen dispatch item
Set item_state to "aborted" on a kitchen dispatch item. Requires orders.void permission. Rejects when the parent tab has any purchases. When reasonCode is "other", reasonNote is required.
path Parameters
idKitchen dispatch item UUID
Void a kitchen dispatch item › Request Body
reasonCodeReason code from the locked enum
reasonNoteOptional free-text note; REQUIRED when reasonCode is "other"
quantityCentsOptional partial-void quantity in basis-points (null = full quantity). Stored only in audit.
suppressKorrbongWhen true, suppress the order.reversed webhook so printer-service does not print a KORRBONG correction ticket. Used by cafe-mode void-and-replace flows.
Void a kitchen dispatch item › Responses
Successfully voided the item
statusVoid one or more kitchen dispatch items
Set item_state to "aborted" on multiple kitchen dispatch items in one request. Items may span multiple parent dispatches; one order.reversed event is emitted per affected KD. Requires orders.void permission. Rejects when ANY affected tab has purchases. When reasonCode is "other", reasonNote is required.
Void one or more kitchen dispatch items › Request Body
reasonCodeReason code from the locked enum, applied to every item in the batch
Kitchen dispatch items to void
reasonNoteOptional free-text note; REQUIRED when reasonCode is "other"
suppressKorrbongWhen true, suppress the order.reversed webhook so printer-service does not print a KORRBONG per affected dispatch. Used by cafe-mode void-and-replace flows.
Void one or more kitchen dispatch items › Responses
Successfully voided all items in the batch
statusList orders
Retrieve a paginated list of orders with filtering capabilities.
Hybrid Dual-Fetch Architecture:
- PostgreSQL for recent orders (<30 minutes old) - ensures freshness
- BigQuery for historical orders (>30 minutes old) - scalability
- Automatic merge when date range spans both sources
KDS/Real-Time Mode:
- Use
forcePostgres=trueto always query PostgreSQL only - This ensures fresh state data for Kitchen Display Systems
- Recommended for any real-time display needing immediate state updates
Default Behavior:
- Returns last 24 hours if no date filters specified
- Sorted by created_at descending (newest first)
- Items not included by default (use includeItems=true)
Performance Notes:
- BigQuery queries typically take 1-3 seconds
- For real-time displays, use forcePostgres=true or /api/v1/orders/stream endpoint
Permissions: 🔵 orders.read
query Parameters
pagePage number
limitItems per page (max 1000)
includeItemsInclude order items in response. Items are returned FLAT with parentKitchenDispatchItemId for hierarchy building.
includeNotesInclude tab notes attached to each order (notes are polymorphic, keyed by tab uuid). Used by the KDS.
forcePostgresForce PostgreSQL only (skip BigQuery). Use for KDS/real-time displays where state must be fresh.
excludeAbortedTabsHide KDs whose parent tab was force-closed (aborted). Use for the active KDS so staff don't see orphan tickets they cannot advance. Leave off for order history and audit views.
dailyOrderNumberFilter by daily order number
stateFilter by state(s)
tabTypeFilter by tab type(s)
tableIdFilter by table/QR code ID
tabMemberEmailFilter by tab member email (partial match)
minPriceMinimum total price in cents
maxPriceMaximum total price in cents
sourceFilter by order source/channel (POS, ONLINE, QR, KIOSK)
itemIdFilter orders containing a specific inventory item ID
printerGroupIdsFilter by prep group (printer group) IDs
startDateFilter orders created after this date (default: 24 hours ago)
endDateFilter orders created before this date (default: now)
sortField to sort by
orderSort order
List orders › Responses
Default Response
statusCancel order
Cancel a kitchen dispatch (order) by setting its state to aborted. Only early-stage orders can be cancelled.
Permissions: 🟠 inventory.update
path Parameters
kitchenDispatchIdKitchen dispatch UUID to cancel
Cancel order › Responses
Order cancelled successfully
statusSync (atomic void + insert) lines on a kitchen dispatch
Atomically void a set of existing kitchen_dispatch_items AND insert a set of new ones in ONE transaction, ONE webhook fan-out.
Cafe-mode "edit committed items" primitive. The earlier two-call shape (POST /void-batch + POST /append-to-dispatch in parallel) is replaced — clients describe the diff, the server applies it atomically.
Maps cleanly to actions:
+on a committed line →{ voids: [], inserts: [oneItem] }−on a committed line →{ voids: [kdiId], inserts: [] }- Variant edit →
{ voids: [originalKdiId], inserts: [newSpec] }
Guards:
- Dispatch must exist, belong to the supplied tab + location, and be in an appendable state (
pending/accepted/in_preparation/ready_to_deliver). - Tab must not be closed/abandoned.
- Voids: any tab purchase rejects with 422
TAB_HAS_PAYMENTS. Already-aborted items pass through (idempotent,wasAlreadyAborted: truein the response). - Voided items not on this dispatch reject with 404
KITCHEN_DISPATCH_ITEM_NOT_FOUND. - Inserts: items + variants validated identically to
/orders/create.
Side effects (one fan-out):
order.reversedwebhook (printer KORRBONG) — skipped whensuppressKorrbong: true(cafe mode).order.updatedwebhook withchanges.syncedLines(KDS / cross-device refetch).tab.updatedwebhook withchanges.kitchenDispatchSynced(cashier tab refetch).inventory.updatedper ministock change.- Per-item
kitchen_dispatch_item.voidedplatform_event for the audit trail.
Permissions: 🟢 inventory.create
path Parameters
kitchenDispatchIdUUID of the kitchen dispatch to sync
Sync (atomic void + insert) lines on a kitchen dispatch › Request Body
tabIdUUID of the tab the dispatch belongs to (validated server-side)
locationIdorder_channelvoidsKDI UUIDs to set to item_state=aborted. Already-aborted ids pass through.
New items to insert into the dispatch (same shape as /orders/create items[]).
suppressKorrbongWhen true, skip the order.reversed webhook so printer-functions does not print a KORRBONG. Cafe-mode locations pass this; merchant locations omit it.
voidReasonCodeReason for the voids. Defaults to "customer_change".
voidReasonNoteRequired when voidReasonCode === "other".
Sync (atomic void + insert) lines on a kitchen dispatch › Responses
Lines synced successfully
statusGet order by ID
Retrieve detailed information about a specific order including all items.
Items are always included in the response for single order queries.
Permissions: 🔵 orders.read
path Parameters
orderIdOrder ID (kitchen_dispatch.uuid)
Get order by ID › Responses
Default Response
statusAdvance order item states
Advance item-level states for a kitchen dispatch (order).
Item-Level State Tracking:
- Each item independently tracks its own state
- The overall order state is automatically derived as the earliest non-not_sent item state
- Forward-only: items can only advance forward, never backward
Filtering Options:
- No filter: advance ALL items in the order
- printerGroupId: advance only items in a specific prep group
- coursingOrder: advance only items in a specific course
Valid Target States:
- pending, accepted, in_preparation, ready_to_deliver, delivered, rejected
Webhook:
- Emits order.updated with targetItemState and optional printerGroupId
Permissions: 🟠 inventory.update
path Parameters
orderIdOrder ID (kitchen_dispatch.uuid)
Advance order item states › Request Body
stateTarget state to advance items to
printerGroupIdOptional: advance only items in this prep group (printer group)
coursingOrderOptional: advance only items in this course
Advance order item states › Responses
Default Response
statusEdit items on a staged order
Edit item quantities on a kitchen dispatch in staged_awaiting_payment state.
Replaces the cancel→re-commit pattern previously used for storefront-web pay_upfront tab editing.
Per item:
quantityCents > 0— UPDATE quantity, adjust ministock deltaquantityCents === 0— DELETE the item (and its children), restore ministock
Guards:
- Dispatch must be in
staged_awaiting_paymentstate - No item on the dispatch may have
paid_amount > 0 - Ministock checked for quantity increases
- Location access validated
Side effects:
- Tab total recalculated
- Emits
order.updatedwebhook
Permissions: 🟠 inventory.update
path Parameters
orderIdKitchen dispatch UUID to edit
Edit items on a staged order › Request Body
Items to edit. Set quantityCents to 0 to remove an item.
Edit items on a staged order › Responses
Items edited successfully
statusUpdate item status
Update the status of a kitchen dispatch item or modification. Requires staff authentication (JWT). User ID for audit trail is extracted from the auth token.
path Parameters
orderIdKitchen dispatch (order) UUID
itemIdKitchen dispatch item UUID
Update item status › Request Body
Item status: COMPLETED, UNAVAILABLE, or null (reset)
modificationIdIf provided, update this modification (variant) instead of the item
Update item status › Responses
Status updated successfully
statusGet item status logs
Get the status change history for a kitchen dispatch item
path Parameters
orderIdKitchen dispatch (order) UUID
itemIdKitchen dispatch item UUID
Get item status logs › Responses
Status logs retrieved successfully
statusBatch update item statuses
Batch update the status of multiple kitchen dispatch items and/or modifications. Requires staff authentication (JWT). User ID for audit trail is extracted from the auth token.
path Parameters
orderIdKitchen dispatch (order) UUID
Batch update item statuses › Responses
Batch update completed
statusUpdate serving center state
Update the state of a specific serving center for an order.
Serving Center State Management:
- Each serving center independently tracks its state for each order
- The overall order state is derived as the earliest (most backward) state across all serving centers
- When all serving centers advance, the overall order state advances too
Valid Serving Center States (forward-only):
- pending → accepted → in_preparation → ready_to_deliver → delivered
- rejected (terminal)
Constraints:
- Cannot set serving center state earlier than the overall order state
- Forward-only transitions (can't go backward)
Webhook:
- Emits order.updated with servingCenterId and servingCenterState
- Used by common-functions to send serving center SMS notifications
Replaces: GraphQL mutation updateServingCenterKitchenDispatchState from Karma-Merchant-API
Permissions: 🟠 inventory.update
path Parameters
orderIdOrder ID (kitchen_dispatch.uuid)
Update serving center state › Request Body
servingCenterIdThe serving center ID to update state for
stateThe new serving center state
Update serving center state › Responses
Default Response
statusUpdate order state
Update the state of an order (kitchen dispatch).
Event Sourcing:
- Inserts an event into kitchen_dispatch_events table
- PostgreSQL trigger automatically updates kitchen_dispatches.latest_state
- Emits order.updated webhook for real-time UI updates
Valid State Transitions:
not_sent→ pending, delivered, abortedpending→ accepted, rejected, abortedscheduled→ accepted, pending, abortedaccepted→ in_preparation, ready_to_deliver, abortedin_preparation→ ready_to_deliverready_to_deliver→ deliveredrejected→ rejected_and_acknowledgedaborted→ rejected_and_acknowledged (KDS bump on voided dispatch)staged_awaiting_payment→ pending, aborted
Terminal States (no transitions):
- delivered, rejected_and_acknowledged
Idempotency:
- Calling with current state returns 200 success (no-op)
- Safe for retries in distributed systems
Permissions: 🟠 orders.update
path Parameters
orderIdOrder ID (kitchen_dispatch.uuid)
Update order state › Request Body
stateThe new state to transition to
Update order state › Responses
Default Response
statusAppend items to an existing kitchen dispatch
Append items to an EXISTING kitchen_dispatch so they show up on the same KDS card the barista is already on.
Used by the cafe-mode "edit committed items" flow — instead of a void creating a fresh ticket, the cashier voids the original line and appends the replacement against the same dispatch ID.
Guards:
- Dispatch must exist and belong to the supplied tab.
- Dispatch state must be one of:
pending,accepted,in_preparation,ready_to_deliver. Any other state (terminal, held, merged, staged) is rejected with 409DISPATCH_NOT_APPENDABLE. - Tab must not be closed/abandoned.
- Items + variants validated via the same path as
/orders/create.
Side effects:
- New
kitchen_dispatch_itemsinserted under the existing dispatch. - Ministock decremented for items that track it.
order.items_addedwebhook emitted (resource id = dispatch id).tab.updatedwebhook emitted withkitchenDispatchUpdated: { dispatchId, itemCount }.
Permissions: 🟢 inventory.create
Append items to an existing kitchen dispatch › Request Body
kitchenDispatchIdUUID of the kitchen dispatch to append to
tabIdUUID of the tab the dispatch belongs to (validated server-side)
locationIdLocation ID (validated against dispatch)
order_channelSource channel (POS-only flows pass POS so price-override gating works)
Items to append (same shape as /orders/create items)
Append items to an existing kitchen dispatch › Responses
Items appended successfully
statusCreate order
Unified Order Creation API - handles all order creation from POS, Storefront, Kiosk, and QR code orders
Permissions: 🟢 inventory.create
Create order › Request Body
locationIdLocation ID
order_channelSource of the order
order_typeService model - TAKEAWAY (pickup, fresh prep), OTC (over the counter), QR (customer scanned QR code or POS table order), TABLE (waiter service), SURPLUS (pre-prepared discounted item, anytime pickup).
order_destinationWhere the order should be routed
Items to include in the order
order_destination_idUUID of the destination (QR code, tab, or kitchen dispatch)
tab_memberUser identification for the order
vouchersVoucher codes to apply
desiredPickupTimeUnix timestamp for desired pickup time
holdIf true, order will be held (not_sent) and not sent to kitchen automatically
Create order › Responses
Order created successfully
statusStream orders (SSE)
Stream orders using Server-Sent Events for real-time displays.
Use Case: Kitchen Display Systems (KDS) and real-time dashboards where latency matters.
How It Works:
- PostgreSQL results are sent first (~100ms) - recent orders
- BigQuery results follow when ready (~1-3 seconds) - historical orders
- Completion event sent when all data is received
SSE Events:
postgres: Orders from PostgreSQL (recent data)bigquery: Orders from BigQuery (historical data)error: Error from a specific sourcecomplete: All data has been sent
Client Example:
Code
Headers Required:
Accept: text/event-streamX-Location-Id: {locationId}
Permissions: 🔵 orders.read
query Parameters
pagePage number
limitItems per page (max 1000)
includeItemsInclude order items in response. Items are returned FLAT with parentKitchenDispatchItemId for hierarchy building.
includeNotesInclude tab notes attached to each order (notes are polymorphic, keyed by tab uuid). Used by the KDS.
forcePostgresForce PostgreSQL only (skip BigQuery). Use for KDS/real-time displays where state must be fresh.
excludeAbortedTabsHide KDs whose parent tab was force-closed (aborted). Use for the active KDS so staff don't see orphan tickets they cannot advance. Leave off for order history and audit views.
dailyOrderNumberFilter by daily order number
stateFilter by state(s)
tabTypeFilter by tab type(s)
tableIdFilter by table/QR code ID
tabMemberEmailFilter by tab member email (partial match)
minPriceMinimum total price in cents
maxPriceMaximum total price in cents
sourceFilter by order source/channel (POS, ONLINE, QR, KIOSK)
itemIdFilter orders containing a specific inventory item ID
printerGroupIdsFilter by prep group (printer group) IDs
startDateFilter orders created after this date (default: 24 hours ago)
endDateFilter orders created before this date (default: now)
sortField to sort by
orderSort order
Stream orders (SSE) › Responses
Server-Sent Events stream (text/event-stream)
Server-Sent Events stream (text/event-stream)
Webhook: Order (kitchen dispatch) created
Fired when items are committed to the kitchen (POST /api/v1/inventory/commit). One event per dispatch.
This is an outbound webhook event. Karma POSTs this payload to the URL you registered via POST /api/v1/webhooks/subscriptions. Your endpoint should respond 2xx within 30 seconds to acknowledge delivery.
Webhook: Order (kitchen dispatch) created › Request Body
idUnique webhook delivery ID
eventresourceresourceIdString ID of the affected resource
timestampISO 8601 timestamp when the event was emitted
apiVersionWebhook: Order (kitchen dispatch) created › Responses
Acknowledged. Karma considers any 2xx response a successful delivery; non-2xx triggers retry with exponential backoff.
Webhook: Items added to an existing order
Fired when items are added to a kitchen dispatch that already exists.
This is an outbound webhook event. Karma POSTs this payload to the URL you registered via POST /api/v1/webhooks/subscriptions. Your endpoint should respond 2xx within 30 seconds to acknowledge delivery.
Webhook: Items added to an existing order › Request Body
idUnique webhook delivery ID
eventresourceresourceIdString ID of the affected resource
timestampISO 8601 timestamp when the event was emitted
apiVersionWebhook: Items added to an existing order › Responses
Acknowledged. Karma considers any 2xx response a successful delivery; non-2xx triggers retry with exponential backoff.
Webhook: Order updated
Fired on any KDS state transition or detail change. changes describes what shifted.
This is an outbound webhook event. Karma POSTs this payload to the URL you registered via POST /api/v1/webhooks/subscriptions. Your endpoint should respond 2xx within 30 seconds to acknowledge delivery.
Webhook: Order updated › Request Body
idUnique webhook delivery ID
eventresourceresourceIdString ID of the affected resource
timestampISO 8601 timestamp when the event was emitted
apiVersionWebhook: Order updated › Responses
Acknowledged. Karma considers any 2xx response a successful delivery; non-2xx triggers retry with exponential backoff.
Webhook: Order requires payment
Fired when an order needs payment (e.g. INSTANT flow, or tab settlement).
This is an outbound webhook event. Karma POSTs this payload to the URL you registered via POST /api/v1/webhooks/subscriptions. Your endpoint should respond 2xx within 30 seconds to acknowledge delivery.
Webhook: Order requires payment › Request Body
idUnique webhook delivery ID
eventresourceresourceIdString ID of the affected resource
timestampISO 8601 timestamp when the event was emitted
apiVersionWebhook: Order requires payment › Responses
Acknowledged. Karma considers any 2xx response a successful delivery; non-2xx triggers retry with exponential backoff.
Webhook: Order completed
Fired when an order is marked complete in the KDS.
This is an outbound webhook event. Karma POSTs this payload to the URL you registered via POST /api/v1/webhooks/subscriptions. Your endpoint should respond 2xx within 30 seconds to acknowledge delivery.
Webhook: Order completed › Request Body
idUnique webhook delivery ID
eventresourceresourceIdString ID of the affected resource
timestampISO 8601 timestamp when the event was emitted
apiVersionWebhook: Order completed › Responses
Acknowledged. Karma considers any 2xx response a successful delivery; non-2xx triggers retry with exponential backoff.
Webhook: Order cancelled
Fired when an order is cancelled. Includes the cancelling user and an optional reason.
This is an outbound webhook event. Karma POSTs this payload to the URL you registered via POST /api/v1/webhooks/subscriptions. Your endpoint should respond 2xx within 30 seconds to acknowledge delivery.
Webhook: Order cancelled › Request Body
idUnique webhook delivery ID
eventresourceresourceIdString ID of the affected resource
timestampISO 8601 timestamp when the event was emitted
apiVersionWebhook: Order cancelled › Responses
Acknowledged. Karma considers any 2xx response a successful delivery; non-2xx triggers retry with exponential backoff.
Webhook: Order reversed (void)
Fired when a kitchen dispatch is reversed — e.g. void requested or booking unseated. Carries full item snapshots so subscribers (printer-service) can produce KORRBONG void tickets.
This is an outbound webhook event. Karma POSTs this payload to the URL you registered via POST /api/v1/webhooks/subscriptions. Your endpoint should respond 2xx within 30 seconds to acknowledge delivery.
Webhook: Order reversed (void) › Request Body
idUnique webhook delivery ID
eventresourceresourceIdString ID of the affected resource
timestampISO 8601 timestamp when the event was emitted
apiVersionWebhook: Order reversed (void) › Responses
Acknowledged. Karma considers any 2xx response a successful delivery; non-2xx triggers retry with exponential backoff.
Webhook: Order item status changed
Fired in batches when item or modification statuses are updated (COMPLETED, UNAVAILABLE, or reset). Used by KDS UI for real-time updates.
This is an outbound webhook event. Karma POSTs this payload to the URL you registered via POST /api/v1/webhooks/subscriptions. Your endpoint should respond 2xx within 30 seconds to acknowledge delivery.
Webhook: Order item status changed › Request Body
idUnique webhook delivery ID
eventresourceresourceIdString ID of the affected resource
timestampISO 8601 timestamp when the event was emitted
apiVersionWebhook: Order item status changed › Responses
Acknowledged. Karma considers any 2xx response a successful delivery; non-2xx triggers retry with exponential backoff.