Skip to Content
Orders

Orders

Use the Orders API to import sales from another system, create orders from a custom checkout, track fulfillment, record partial or full payment, schedule future orders, and retrieve receipts.

All endpoints use the /v1/orders prefix and authenticate with an API key. Amounts are expressed in the business currency as decimal numbers, not minor units.

Endpoints

MethodEndpointScopePurpose
GET/v1/ordersorders:readList and filter orders
GET/v1/orders/:idorders:readRetrieve one order
POST/v1/ordersorders:writeCreate an order
PATCH/v1/orders/:idorders:writeUpdate status, payment, customer, or scheduling
POST/v1/orders/:id/confirmorders:writeConfirm a scheduled order
POST/v1/orders/:id/requeryorders:readRefresh an automated payment
POST/v1/orders/:id/receiptorders:readGenerate a receipt URL
DELETE/v1/orders/:idorders:writeDelete an order and restore inventory

Order resource

Order reads and successful create, update, confirmation, and payment refresh operations return the same order shape.

{ "id": "5037c85a-44c6-4c3a-bd7d-3e21e73915e1", "shortCode": "482193", "status": "pending", "paymentStatus": "partial", "summary": "2x Jollof Rice", "items": [ { "id": "2b783a34-5b8b-43b7-a441-dcb8ae7db843", "productId": "7a59174f-3207-42a6-8fab-5b8d8b2929fb", "variantId": "f91718fb-1487-4ada-a44c-794b1ba5a3d3", "productName": "Jollof Rice", "variantName": "Large", "quantity": 2, "unitPrice": 3500, "originalUnitPrice": 4000, "discountAmount": 1000, "subtotalAmount": 7000, "taxAmount": 0, "totalPrice": 7000, "imageUrl": "https://cdn.example.com/jollof-rice.jpg", "modifiers": [ { "modifierGroupId": "4f7f9ff4-19e4-4cbb-b7c6-45275e70fc6f", "modifierOptionId": "f494ef42-178a-4e16-bcf2-481a52d55833", "name": "Extra chicken", "priceDelta": 1000 } ], "components": [] } ], "totalAmount": 7000, "subtotalAmount": 8000, "discountAmount": 1000, "serviceChargeAmount": 0, "amountPaid": 4000, "remainingAmount": 3000, "currency": "NGN", "paymentMethod": "transfer", "customer": { "id": "3cadb42d-571b-4979-94b4-c094c60820c4", "name": "Ada Lovelace", "phoneNumber": "+2348012345678", "whatsappNumber": "+2348012345678" }, "store": { "id": "837ceae4-43c2-4bbb-830c-1099d36b9d05", "name": "Lekki" }, "channel": "checkout", "channelFulfilledAt": null, "isAutomated": false, "deposit": null, "scheduledFor": null, "scheduledConfirmedAt": null, "serviceMode": "takeaway", "tableSessionId": null, "tableLabel": null, "kitchenTicketId": null, "kitchenTicketStatus": null, "recordedBy": { "id": "4e3d75bb-4208-4dd4-a292-2c27ecb99185", "name": "API integration" }, "servedBy": null, "tags": [], "notes": "Pack cutlery separately", "receiptUrl": null, "cancellation": null, "occurredAt": "2026-07-14T10:30:00.000Z", "date": "2026-07-14T10:30:00.000Z", "createdAt": "2026-07-14T10:30:02.000Z", "entrySource": "live", "recoverySessionId": null, "academicTerm": null }

Status values

StatusMeaning
scheduledCreated for future fulfillment and not yet confirmed
pendingCreated but not fully paid or otherwise awaiting completion
completedFully paid or explicitly completed
cancelledCancelled with an optional recorded reason
refundedPreviously refunded through a supported refund workflow

paymentStatus is calculated from the order totals:

Payment statusRule
pendingamountPaid is zero
partialamountPaid is greater than zero and less than totalAmount
paidamountPaid is equal to or greater than totalAmount

Setting an order status to refunded does not move money. The public update endpoint therefore does not accept refunded. Use the applicable payment provider refund workflow, then consume the resulting order or transaction update.

List orders

GET /v1/orders?status=pending,scheduled&channel=whatsapp,voice&limit=25

Query parameters

Comma-separated filters use lowercase values.

ParameterTypeDescription
statusenum listscheduled, pending, completed, cancelled, refunded
payment_statusenum listpaid, partial, pending
channelenum listFilter by one or more order channels
service_modeenum listdine_in, takeaway, room_service
payment_methodenumcash, transfer, pos, cloove_pay, credit, other
customer_iduuidOrders linked to a customer
store_iduuidOrders for one store, including business-level orders
store_idsuuid listComma-separated store IDs
recorded_by_iduuidOrders created by a user
staff_iduuidOrders recorded or served by a user
served_by_user_iduuidOrders assigned to a server or waiter
table_session_iduuidOrders charged to a restaurant table session
academic_term_iduuidOrders associated with an academic term
tag_idsuuid listOrders containing any listed tag
start_dateISO date or timestampOrders occurring on or after this value
end_dateISO date or timestampOrders occurring on or before this value
searchstringMatch an order short code or customer name
is_automatedbooleanWhether the order has an automated deposit
channel_fulfilledbooleanWhether a channel order has been treated
scheduled_onlybooleanReturn scheduled orders in fulfillment order
pageintegerPage number, default 1
limitintegerItems per page, default 50, maximum 100

Response

{ "message": "Orders retrieved", "data": [], "meta": { "total": 0, "page": 1, "perPage": 25, "totalPages": 1, "hasMore": false }, "summary": { "todayOrders": 4, "todayRevenue": 42000, "totalOrders": 138, "filteredOrders": 12, "totalRevenue": 184000, "averageOrderValue": 15333.33, "pendingOrdersCount": 6, "pendingOutstandingAmount": 27000, "completedOrdersCount": 7, "completedRevenue": 157000, "cancelledOrdersCount": 1, "cancelledRevenue": 0 } }

filteredOrders and the revenue fields respect the supplied filters. totalOrders and pendingOrdersCount are business workload counts and are not reduced by every list filter.

Retrieve an order

GET /v1/orders/5037c85a-44c6-4c3a-bd7d-3e21e73915e1

This endpoint returns the complete order resource, including line items, customer, store, payment, scheduling, restaurant, staff, deposit, and cancellation data.

A missing order, a deleted order, or an order belonging to another business returns:

{ "error": "not_found", "message": "Order not found." }

Create an order

POST /v1/orders Idempotency-Key: 90ed7ca0-dd71-4550-8bea-62b99d551d41 Content-Type: application/json

Always use a unique UUID as the Idempotency-Key. Repeating a successful request with the same key returns the original order with 200 OK. A new order returns 201 Created.

Core fields

FieldTypeRequiredDescription
itemsarrayYesOne or more product or fee lines
payment_methodenumNoDefaults to cash
amount_paidnumberNoAmount already collected
discount_amountnumberNoOrder-level discount
promotion_iduuidNoPromotion applied to the order
customer_iduuidNoExisting customer
customer_namestringNoFinds or creates a customer when no ID is supplied
store_iduuidNoStore used for inventory and reporting
store_namestringNoStore name when integrating by name
channelenumNoSource channel for the order
tagsstring arrayNoTag IDs, slugs, or names
notesstringNoOrder note, up to 2,000 characters
scheduled_forISO timestampNoFuture fulfillment time
occurred_atISO timestampNoOriginal sale time when importing historical orders

Valid channels are in_person, whatsapp, instagram, tiktok, telegram, twitter, storefront, dashboard, checkout, voice, and other.

Line item fields

FieldTypeRequiredDescription
product_namestringYesDisplay name captured on the order
quantitynumberYesPositive quantity
product_iduuidProduct linesCatalog product used for pricing and inventory
variant_iduuidNoSelected product variant
custom_pricenumberNoUnit price override
line_typeenumNoproduct or fee, default product
modifiersarrayNoSelected modifier options

Catalog-backed lines should include product_id. Fee lines can omit it and use line_type: "fee" with a custom_price.

Modifier fields

FieldTypeRequiredDescription
modifier_group_iduuidYesProduct modifier group
modifier_option_iduuidYesSelected option
namestringYesSnapshot label shown on the order
price_deltanumberNoExpected price addition; server catalog rules remain authoritative

Restaurant and hotel fields

FieldTypeDescription
service_modeenumdine_in, takeaway, or room_service
service_charge_amountnumberService charge applied to the order
table_session_iduuidActive restaurant table session
table_labelstringTable label when no session is supplied
coversintegerNumber of guests
send_to_kitchenbooleanRoute the order to the kitchen workflow
served_by_user_iduuidServer or waiter responsible for the order
hotel_reservation_iduuidReservation receiving the order
hotel_room_iduuidRoom receiving the order

School field

academic_term_id associates the order with an academic term. It is optional for other business types.

Product and variant example

{ "items": [ { "product_id": "7a59174f-3207-42a6-8fab-5b8d8b2929fb", "variant_id": "f91718fb-1487-4ada-a44c-794b1ba5a3d3", "product_name": "Jollof Rice", "quantity": 2, "modifiers": [ { "modifier_group_id": "4f7f9ff4-19e4-4cbb-b7c6-45275e70fc6f", "modifier_option_id": "f494ef42-178a-4e16-bcf2-481a52d55833", "name": "Extra chicken", "price_delta": 1000 } ] } ], "payment_method": "transfer", "amount_paid": 4000, "discount_amount": 1000, "customer_id": "3cadb42d-571b-4979-94b4-c094c60820c4", "store_id": "837ceae4-43c2-4bbb-830c-1099d36b9d05", "channel": "checkout", "service_mode": "takeaway", "notes": "Pack cutlery separately" }

Fee line example

{ "items": [ { "product_name": "Delivery fee", "quantity": 1, "custom_price": 1500, "line_type": "fee" } ], "payment_method": "cash" }

Scheduled order example

{ "items": [ { "product_id": "7a59174f-3207-42a6-8fab-5b8d8b2929fb", "product_name": "Event platter", "quantity": 3 } ], "scheduled_for": "2026-08-20T18:30:00.000Z", "customer_name": "Grace Hopper", "channel": "voice" }

scheduled_for must be a valid future timestamp. The new order enters scheduled status.

Update an order

PATCH /v1/orders/5037c85a-44c6-4c3a-bd7d-3e21e73915e1 Content-Type: application/json

Only supplied fields are changed.

FieldTypeDescription
statusenumscheduled, pending, completed, or cancelled
customer_iduuidAssign an existing customer
customer_namestringFind or create a customer by name
payment_methodenumChange the recorded payment method
amount_paidnumberSet the cumulative amount collected
total_amountnumberCorrect the order total
academic_term_iduuid or nullAssign or clear an academic term
scheduled_forISO timestamp or nullSchedule a recent order or update its schedule
cancellation_reasonstringReason stored when changing to cancelled
channel_fulfilledbooleanMark a WhatsApp or Voice order treated or reopen it

Record a partial payment

{ "payment_method": "transfer", "amount_paid": 4000 }

amount_paid is cumulative. If an order total is 7000 and a second payment brings the collected amount to 7000, send 7000, not the payment delta.

Cancel an order

{ "status": "cancelled", "cancellation_reason": "Customer changed their mind" }

The response includes the stored cancellation audit block. Completed automated bank transfer orders cannot be cancelled through this endpoint because a payment reversal may be required.

Mark a channel order fulfilled

{ "channel_fulfilled": true }

Send false to return the order to the channel fulfillment queue.

Confirm a scheduled order

POST /v1/orders/5037c85a-44c6-4c3a-bd7d-3e21e73915e1/confirm Idempotency-Key: b802662c-3b05-4f9b-859c-14468eb6d485 Content-Type: application/json
{ "payment_method": "pos", "amount_paid": 7000 }
FieldTypeDescription
payment_methodenumFinal payment method
amount_paidnumberAmount collected; defaults to the full order total

A fully paid order becomes completed. A partially paid order becomes pending. Only orders currently in scheduled status can be confirmed.

Refresh an automated payment

POST /v1/orders/5037c85a-44c6-4c3a-bd7d-3e21e73915e1/requery

Use this endpoint for an order with isAutomated: true when your application needs to refresh its virtual account payment state. The response returns the updated order resource.

Do not poll continuously. Prefer webhooks for normal payment updates and requery only after a customer reports payment or when recovering from a missed event.

Generate a receipt

POST /v1/orders/5037c85a-44c6-4c3a-bd7d-3e21e73915e1/receipt
{ "message": "Order receipt generated", "data": { "url": "https://storage.example.com/receipts/signed-receipt.pdf" } }

Receipt URLs can be signed and time-limited. Store the order ID and generate another URL when a previous link expires.

Delete an order

DELETE /v1/orders/5037c85a-44c6-4c3a-bd7d-3e21e73915e1

Deletion soft-deletes the order, restores tracked variant inventory, and removes its active debt record. It is intended for incorrectly recorded orders.

Orders with automated deposits cannot be deleted and return 409 Conflict:

{ "error": "order_not_deletable", "message": "Orders with automated deposits (like bank transfers) cannot be deleted." }

Use cancellation for a valid order that will not be fulfilled. Use deletion only when the record itself should not remain in sales reporting.

Errors

HTTP statusErrorWhen it occurs
400request_failedA domain rule prevents the operation
400order_not_recordedOrder creation fails
401unauthorizedAPI key is missing or invalid
403forbiddenAPI key lacks the required scope
404not_foundOrder is missing, deleted, or belongs to another business
409order_not_deletableAn automated-deposit order cannot be deleted
422validation_errorA request field or list filter is invalid
429rate_limit_exceededDeveloper API rate limit is exceeded

See API conventions for the shared error envelope, retry rules, pagination, and idempotency behavior.

Creating an order emits an order.created webhook. Status and payment changes may emit additional order or payment events. Verify webhook signatures and process event IDs idempotently.

Last updated on