Orders

17 operations. Every schema and example on this page is generated from the platform contract.

List a store's Order & Collect orders (live queue or history).

Merchant lists their store orders: scope=active is the live fulfilment queue; scope=history is terminal orders newest-first, keyset-paged by the `before` + `before_id` cursor (send both, a mixed basket's parent and legs share a created_at to the microsecond, so the timestamp alone cannot identify a page boundary). Same per-order shape as the fulfilment ops.

Parameters

store_idstring · uuidqueryrequired

Store whose orders to list (also authorises the merchant).

scopeenumqueryoptional

active = the live queue (default); history = terminal orders, newest-first.

activehistory
limitintegerqueryoptional

Page size (default 50, max 100).

beforestringqueryoptional

Keyset cursor (an order created_at) for history pagination.

before_idstringqueryoptional

The id half of the history cursor, the id of the SAME row `before` came from. Send both together. A mixed basket's parent and legs share a created_at to the microsecond, so created_at alone cannot say where a page ended: omitting this makes the server fall back to an inclusive bound and re-serve the boundary row, which is safe but returns rows you already have (de-dupe by id).

Response, 200

ordersarray of objectrequired
17 child fields
idstringrequired
store_idstringrequired
order_typestringrequired
fulfilment_statusstring, nullableoptional
collection_codestring, nullableoptional
payment_methodenumoptional
pay_nowbank_transfercash
order_page_pathstring, nullableoptional
payment_due_atstring, nullableoptional
collection_modestring, nullableoptional
requested_collection_atstring, nullableoptional
accepted_atstring, nullableoptional
preparing_atstring, nullableoptional
ready_atstring, nullableoptional
collected_atstring, nullableoptional
customer_namestring, nullableoptional
customer_emailstring, nullableoptional
customer_phonestring, nullableoptional
scopeenumrequired
activehistory
curl -G "https://www.membber.com/api/v1/orders" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  --data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066"
Response, 200
{
  "orders": [
    {
      "id": "00000d1b-0000-4000-8000-d0c500000000",
      "store_id": "6659c139-0000-4000-8000-d0c500000066",
      "order_type": "<order_type>",
      "fulfilment_status": "<fulfilment_status>",
      "collection_code": "EXAMPLE10",
      "payment_method": "pay_now",
      "order_page_path": "<order_page_path>",
      "payment_due_at": "<payment_due_at>",
      "collection_mode": "<collection_mode>",
      "requested_collection_at": "<requested_collection_at>",
      "accepted_at": "<accepted_at>",
      "preparing_at": "<preparing_at>",
      "ready_at": "<ready_at>",
      "collected_at": "<collected_at>",
      "customer_name": "Alex Example",
      "customer_email": "alex@example.com",
      "customer_phone": "+44 7700 900123"
    }
  ],
  "scope": "active"
}

Create a native mini-store order + Stripe PaymentIntent.

Customer creates an in-app order; returns a destination-charge PaymentIntent + ephemeral key for the native Apple Pay / card sheet. Idempotent via the body `idempotency_key` (order-level replay in the service).

Request body

store_codestringrequired

Public store code.

store_idstring · uuidrequired

Store id.

idempotency_keystringrequired

Client-generated order idempotency key (UUID v4).

itemsarray of objectrequired

Basket lines.

2 child fields
menu_item_idstringrequired
quantityintegerrequired
fulfilmentobjectoptional

Fulfilment selection (defaults to counter collection).

2 child fields
modestringrequired
table_numberstring, nullableoptional
tip_penceinteger, nullableoptional
promo_codestring, nullableoptional
voucher_idstring, nullableoptional
order_typeenumoptional
buy_nowcollect
collection_modeenumoptional
nowscheduled
slot_idstring, nullableoptional
requested_collection_atstring, nullableoptional
device_fingerprintstring, nullableoptional
payment_methodenumoptional
pay_nowbank_transfercash
fulfilment_groupsarray of objectoptional

Mixed-cart groups: take-now lines + one or more collect groups.

5 child fields
roleenumrequired
nowcollect
itemsarray of objectrequired
2 child fields
menu_item_idstringrequired
quantityintegerrequired
collection_modeenumoptional
nowscheduled
requested_collection_atstring, nullableoptional
slot_idstring, nullableoptional

Response, 200

order_idstringrequired
order_numberstringrequired
statusstringrequired
requires_paymentbooleanrequired
client_secretstring, nullablerequired
ephemeral_keystring, nullablerequired
stripe_customer_idstring, nullablerequired
connected_account_idstringrequired
payment_intent_idstring, nullablerequired
amount_pencenumberrequired
currencystringrequired
merchant_namestringrequired
collection_codestring, nullableoptional
payment_methodenumoptional
pay_nowbank_transfercash
order_page_pathstring, nullableoptional
payment_due_atstring, nullableoptional
childrenarray of objectoptional

Collect children of a £0 mixed order (empty/absent for a normal order).

8 child fields
order_idstringrequired
order_numberstringrequired
order_typestringrequired
collection_codestring, nullablerequired
fulfilment_statusstringrequired
prep_minutesnumber, nullablerequired
requested_collection_atstring, nullablerequired
total_pencenumber, nullablerequired
curl -X POST "https://www.membber.com/api/v1/orders" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
  -H "Content-Type: application/json" \
  -d '{
    "store_code": "EXAMPLE10",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "idempotency_key": "1f0e2d3c-4b5a-4678-9abc-def012345678",
    "items": [
      {
        "menu_item_id": "ca65a6e7-0000-4000-8000-d0c5000000ca",
        "quantity": 1
      }
    ]
  }'
Response, 200
{
  "order_id": "4991ffac-0000-4000-8000-d0c500000049",
  "order_number": "<order_number>",
  "status": "<status>",
  "requires_payment": true,
  "client_secret": "<client_secret>",
  "ephemeral_key": "<ephemeral_key>",
  "stripe_customer_id": "847b302a-0000-4000-8000-d0c500000084",
  "connected_account_id": "231b6f63-0000-4000-8000-d0c500000023",
  "payment_intent_id": "0b6642a5-0000-4000-8000-d0c50000000b",
  "amount_pence": 1500,
  "currency": "GBP",
  "merchant_name": "<merchant_name>",
  "collection_code": "EXAMPLE10",
  "payment_method": "pay_now",
  "order_page_path": "<order_page_path>",
  "payment_due_at": "<payment_due_at>",
  "children": [
    {
      "order_id": "4991ffac-0000-4000-8000-d0c500000049",
      "order_number": "<order_number>",
      "order_type": "<order_type>",
      "collection_code": "EXAMPLE10",
      "fulfilment_status": "<fulfilment_status>",
      "prep_minutes": 1,
      "requested_collection_at": "<requested_collection_at>",
      "total_pence": 1500
    }
  ]
}

Get one Order & Collect order by id.

Merchant fetches a single order (items, fulfilment state, totals). Store-scoped, a store cannot read another store's order (returns 404).

Parameters

orderIdstringpathrequired
store_idstring · uuidqueryrequired

Store the order belongs to (also authorises the merchant).

Response, 200

orderobjectrequired

A guest order row (Order & Collect).

17 child fields
idstringrequired
store_idstringrequired
order_typestringrequired
fulfilment_statusstring, nullableoptional
collection_codestring, nullableoptional
payment_methodenumoptional
pay_nowbank_transfercash
order_page_pathstring, nullableoptional
payment_due_atstring, nullableoptional
collection_modestring, nullableoptional
requested_collection_atstring, nullableoptional
accepted_atstring, nullableoptional
preparing_atstring, nullableoptional
ready_atstring, nullableoptional
collected_atstring, nullableoptional
customer_namestring, nullableoptional
customer_emailstring, nullableoptional
customer_phonestring, nullableoptional
curl -G "https://www.membber.com/api/v1/orders/b80cf509-0000-4000-8000-d0c5000000b8" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  --data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066"
Response, 200
{
  "order": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "order_type": "<order_type>",
    "fulfilment_status": "<fulfilment_status>",
    "collection_code": "EXAMPLE10",
    "payment_method": "pay_now",
    "order_page_path": "<order_page_path>",
    "payment_due_at": "<payment_due_at>",
    "collection_mode": "<collection_mode>",
    "requested_collection_at": "<requested_collection_at>",
    "accepted_at": "<accepted_at>",
    "preparing_at": "<preparing_at>",
    "ready_at": "<ready_at>",
    "collected_at": "<collected_at>",
    "customer_name": "Alex Example",
    "customer_email": "alex@example.com",
    "customer_phone": "+44 7700 900123"
  }
}

Take the cash and hand the order over, in one tap.

For an order the buyer is paying in cash at collection. Records the payment and the hand-over in ONE transaction, so a crash between them cannot leave a collected order nobody paid for. Sends the receipt, and deliberately not the collection text, the buyer is standing there holding the box.

Parameters

orderIdstringpathrequired

Request body

store_idstring · uuidrequired

Store that owns the order.

Response, 200

orderobjectrequired

A guest order row (Order & Collect).

17 child fields
idstringrequired
store_idstringrequired
order_typestringrequired
fulfilment_statusstring, nullableoptional
collection_codestring, nullableoptional
payment_methodenumoptional
pay_nowbank_transfercash
order_page_pathstring, nullableoptional
payment_due_atstring, nullableoptional
collection_modestring, nullableoptional
requested_collection_atstring, nullableoptional
accepted_atstring, nullableoptional
preparing_atstring, nullableoptional
ready_atstring, nullableoptional
collected_atstring, nullableoptional
customer_namestring, nullableoptional
customer_emailstring, nullableoptional
customer_phonestring, nullableoptional
amount_pencenumberrequired

What was taken, so the screen can say it back to her.

curl -X POST "https://www.membber.com/api/v1/orders/b80cf509-0000-4000-8000-d0c5000000b8/cash-handover" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
  -H "Content-Type: application/json" \
  -d '{
    "store_id": "6659c139-0000-4000-8000-d0c500000066"
  }'
Response, 200
{
  "order": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "order_type": "<order_type>",
    "fulfilment_status": "<fulfilment_status>",
    "collection_code": "EXAMPLE10",
    "payment_method": "pay_now",
    "order_page_path": "<order_page_path>",
    "payment_due_at": "<payment_due_at>",
    "collection_mode": "<collection_mode>",
    "requested_collection_at": "<requested_collection_at>",
    "accepted_at": "<accepted_at>",
    "preparing_at": "<preparing_at>",
    "ready_at": "<ready_at>",
    "collected_at": "<collected_at>",
    "customer_name": "Alex Example",
    "customer_email": "alex@example.com",
    "customer_phone": "+44 7700 900123"
  },
  "amount_pence": 1500
}

Mark a drop order collected, or that they did not come.

Drop orders only (any other order is a 404). `collected` hands it over: refused with NOT_PAID and the amount when it is still to pay. `didnt_come` closes it after its collection window has ended: refused with COLLECTION_NOT_OVER and `collection_ends_at` before then, on the drop's own clock; an audit row names who said it. Idempotent: the same outcome again changes nothing. Requires the payments permission. People only: an AI agent key is refused.

Parameters

orderIdstringpathrequired

Request body

store_idstring · uuidrequired

Store that owns the order.

outcomeenumrequired

`collected`: handed over. `didnt_come`: they did not come (after the window).

collecteddidnt_come

Response, 200

orderobjectrequired

A guest order row (Order & Collect).

17 child fields
idstringrequired
store_idstringrequired
order_typestringrequired
fulfilment_statusstring, nullableoptional
collection_codestring, nullableoptional
payment_methodenumoptional
pay_nowbank_transfercash
order_page_pathstring, nullableoptional
payment_due_atstring, nullableoptional
collection_modestring, nullableoptional
requested_collection_atstring, nullableoptional
accepted_atstring, nullableoptional
preparing_atstring, nullableoptional
ready_atstring, nullableoptional
collected_atstring, nullableoptional
customer_namestring, nullableoptional
customer_emailstring, nullableoptional
customer_phonestring, nullableoptional
outcomeenumrequired
collecteddidnt_come
curl -X POST "https://www.membber.com/api/v1/orders/b80cf509-0000-4000-8000-d0c5000000b8/drop-collection" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
  -H "Content-Type: application/json" \
  -d '{
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "outcome": "collected"
  }'
Response, 200
{
  "order": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "order_type": "<order_type>",
    "fulfilment_status": "<fulfilment_status>",
    "collection_code": "EXAMPLE10",
    "payment_method": "pay_now",
    "order_page_path": "<order_page_path>",
    "payment_due_at": "<payment_due_at>",
    "collection_mode": "<collection_mode>",
    "requested_collection_at": "<requested_collection_at>",
    "accepted_at": "<accepted_at>",
    "preparing_at": "<preparing_at>",
    "ready_at": "<ready_at>",
    "collected_at": "<collected_at>",
    "customer_name": "Alex Example",
    "customer_email": "alex@example.com",
    "customer_phone": "+44 7700 900123"
  },
  "outcome": "collected"
}

Advance an Order & Collect order's fulfilment state.

Staff transition of a collect order: accepted → preparing → ready → collected, or cancelled. Backed by the idempotent advance_order_fulfilment RPC (single writer; outbox event in same tx).

Parameters

orderIdstringpathrequired

Request body

store_idstring · uuidrequired

Store that owns the order.

to_statusenumrequired

Target fulfilment state.

acceptedpreparingreadycollectedcancelled

Response, 200

orderobjectrequired

A guest order row (Order & Collect).

17 child fields
idstringrequired
store_idstringrequired
order_typestringrequired
fulfilment_statusstring, nullableoptional
collection_codestring, nullableoptional
payment_methodenumoptional
pay_nowbank_transfercash
order_page_pathstring, nullableoptional
payment_due_atstring, nullableoptional
collection_modestring, nullableoptional
requested_collection_atstring, nullableoptional
accepted_atstring, nullableoptional
preparing_atstring, nullableoptional
ready_atstring, nullableoptional
collected_atstring, nullableoptional
customer_namestring, nullableoptional
customer_emailstring, nullableoptional
customer_phonestring, nullableoptional
curl -X PATCH "https://www.membber.com/api/v1/orders/b80cf509-0000-4000-8000-d0c5000000b8/fulfilment" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
  -H "Content-Type: application/json" \
  -d '{
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "to_status": "accepted"
  }'
Response, 200
{
  "order": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "order_type": "<order_type>",
    "fulfilment_status": "<fulfilment_status>",
    "collection_code": "EXAMPLE10",
    "payment_method": "pay_now",
    "order_page_path": "<order_page_path>",
    "payment_due_at": "<payment_due_at>",
    "collection_mode": "<collection_mode>",
    "requested_collection_at": "<requested_collection_at>",
    "accepted_at": "<accepted_at>",
    "preparing_at": "<preparing_at>",
    "ready_at": "<ready_at>",
    "collected_at": "<collected_at>",
    "customer_name": "Alex Example",
    "customer_email": "alex@example.com",
    "customer_phone": "+44 7700 900123"
  }
}

The audit story of one order.

Who did what to this order, when, and why, refunds, status corrections and overrides, newest first. Answers the four questions a merchant asks after a refund, from audit rows that were previously written and never read.

Parameters

orderIdstringpathrequired
store_idstring · uuidqueryoptional

Response, 200

entriesarray of objectrequired
5 child fields
atstringrequired
titlestringrequired

A merchant-readable sentence, never a raw action code.

detailstring, nullablerequired

The reason a human typed, when there was one.

actorstring, nullablerequired

Who did it, where a name can be resolved.

amount_pencenumber, nullablerequired
curl -G "https://www.membber.com/api/v1/orders/b80cf509-0000-4000-8000-d0c5000000b8/log" \
  -H "Authorization: Bearer $MEMBBER_TOKEN"
Response, 200
{
  "entries": [
    {
      "at": "<at>",
      "title": "Morning class",
      "detail": "<detail>",
      "actor": "<actor>",
      "amount_pence": 1500
    }
  ]
}

Record an Order & Collect delay and notify the customer of the new time.

Staff records that a collect order is running late (delayMinutes) or sets an explicit newReadyAt, with an optional note. Persists a revised ETA on the order (never the actual ready_at or the booked slot), then notifies the customer on the existing channels: push for a linked customer, email fallback for a guest. Writes an append-only order_status_events audit row (kind running_late). Not money-moving; a short per-order dedupe window keeps a double-tap from spamming.

Parameters

orderIdstringpathrequired

Request body

store_idstring · uuidrequired

Store that owns the order (also authorises the merchant).

delayMinutesintegeroptional

Minutes the order is running late (1-480). New ETA = current ETA + this.

newReadyAtstring · date-timeoptional

Explicit new expected ready/collection time (ISO 8601). Overrides delayMinutes.

notestring, nullableoptional

Optional short merchant message shown to the customer with the new time.

Response, 200

okbooleanrequired
newEtastring, nullablerequired
notifiedenumrequired
pushemailnone
channel_detailstringoptional
curl -X POST "https://www.membber.com/api/v1/orders/b80cf509-0000-4000-8000-d0c5000000b8/notify-delay" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
  -H "Content-Type: application/json" \
  -d '{
    "store_id": "6659c139-0000-4000-8000-d0c500000066"
  }'
Response, 200
{
  "ok": true,
  "newEta": "<newEta>",
  "notified": "push",
  "channel_detail": "<channel_detail>"
}

Correct a Mark as paid that was wrong.

Puts the order back to awaiting payment. A CORRECTION, not an undo: the receipt and the payment text have already gone and are not recalled, which is why the app asks for a reason. Refused once the order has been collected or handed over, the box is in somebody’s hands, so a refund is the honest instrument.

Parameters

orderIdstringpathrequired
store_idstring · uuidqueryrequired

Store that owns the order.

reasonstring, nullablequeryoptional

Why it was wrong. Recorded on the audit row, because the buyer has already had the receipt.

Response, 200

orderobjectrequired

A guest order row (Order & Collect).

17 child fields
idstringrequired
store_idstringrequired
order_typestringrequired
fulfilment_statusstring, nullableoptional
collection_codestring, nullableoptional
payment_methodenumoptional
pay_nowbank_transfercash
order_page_pathstring, nullableoptional
payment_due_atstring, nullableoptional
collection_modestring, nullableoptional
requested_collection_atstring, nullableoptional
accepted_atstring, nullableoptional
preparing_atstring, nullableoptional
ready_atstring, nullableoptional
collected_atstring, nullableoptional
customer_namestring, nullableoptional
customer_emailstring, nullableoptional
customer_phonestring, nullableoptional
curl -X DELETE "https://www.membber.com/api/v1/orders/b80cf509-0000-4000-8000-d0c5000000b8/offline-payment?store_id=6659c139-0000-4000-8000-d0c500000066" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678"
Response, 200
{
  "order": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "order_type": "<order_type>",
    "fulfilment_status": "<fulfilment_status>",
    "collection_code": "EXAMPLE10",
    "payment_method": "pay_now",
    "order_page_path": "<order_page_path>",
    "payment_due_at": "<payment_due_at>",
    "collection_mode": "<collection_mode>",
    "requested_collection_at": "<requested_collection_at>",
    "accepted_at": "<accepted_at>",
    "preparing_at": "<preparing_at>",
    "ready_at": "<ready_at>",
    "collected_at": "<collected_at>",
    "customer_name": "Alex Example",
    "customer_email": "alex@example.com",
    "customer_phone": "+44 7700 900123"
  }
}

Mark a bank transfer or cash order as paid.

The shop says the money arrived on an order the buyer is paying by bank transfer or in cash. Sends the confirmation text and the receipt, the window, the address and the collection code the buyer could not be given while the money was outstanding. Idempotent: a second call returns `already_recorded` and sends nothing. Refused on a card order, whose money lives with Stripe. A RELEASED order is accepted and comes back flagged `late_payment_needs_review`, because the boxes went back on sale when it was released.

Parameters

orderIdstringpathrequired

Request body

store_idstring · uuidrequired

Store that owns the order.

sourceenumoptional

Who is saying the money arrived. Defaults to the merchant.

merchantsweep
notestring, nullableoptional

The merchant’s own note, if she left one (a reference, or which account it came into).

Response, 200

orderobjectrequired

A guest order row (Order & Collect).

17 child fields
idstringrequired
store_idstringrequired
order_typestringrequired
fulfilment_statusstring, nullableoptional
collection_codestring, nullableoptional
payment_methodenumoptional
pay_nowbank_transfercash
order_page_pathstring, nullableoptional
payment_due_atstring, nullableoptional
collection_modestring, nullableoptional
requested_collection_atstring, nullableoptional
accepted_atstring, nullableoptional
preparing_atstring, nullableoptional
ready_atstring, nullableoptional
collected_atstring, nullableoptional
customer_namestring, nullableoptional
customer_emailstring, nullableoptional
customer_phonestring, nullableoptional
outcomeenumrequired

`already_recorded` when somebody got there first, a second phone in the same kitchen, or a second tap.

recordedalready_recorded
late_payment_needs_reviewbooleanrequired

The transfer landed AFTER the order was released and its boxes went back on sale. The money is the shop’s and the order is paid, but the stock may be gone, so the merchant has to decide: make another, or refund.

recorded_by_namestring, nullablerequired

Whose hand it was, for "Marked paid by Romi".

curl -X POST "https://www.membber.com/api/v1/orders/b80cf509-0000-4000-8000-d0c5000000b8/offline-payment" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
  -H "Content-Type: application/json" \
  -d '{
    "store_id": "6659c139-0000-4000-8000-d0c500000066"
  }'
Response, 200
{
  "order": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "order_type": "<order_type>",
    "fulfilment_status": "<fulfilment_status>",
    "collection_code": "EXAMPLE10",
    "payment_method": "pay_now",
    "order_page_path": "<order_page_path>",
    "payment_due_at": "<payment_due_at>",
    "collection_mode": "<collection_mode>",
    "requested_collection_at": "<requested_collection_at>",
    "accepted_at": "<accepted_at>",
    "preparing_at": "<preparing_at>",
    "ready_at": "<ready_at>",
    "collected_at": "<collected_at>",
    "customer_name": "Alex Example",
    "customer_email": "alex@example.com",
    "customer_phone": "+44 7700 900123"
  },
  "outcome": "recorded",
  "late_payment_needs_review": true,
  "recorded_by_name": "<recorded_by_name>"
}

Record money the shop handed back herself, in cash or by transfer.

For an order whose money never went through Stripe. Refuses any order carrying a PaymentIntent, that money is Stripe’s to return, and any order that was never paid, which is released rather than refunded. Clamps to what is outstanding. On a full refund it frees the collection slot, puts the stock back on sale and reverses the loyalty in the same transaction, and the buyer is told the money is coming back in cash or by transfer, never "to your card". Idempotent on `attempt_id`.

Parameters

orderIdstringpathrequired

Request body

store_idstring · uuidrequired

Store that owns the order.

amount_penceintegeroptional

How much she handed back. Omit for the whole outstanding balance, which is what cancelling means and what the server would work out anyway. Clamped to what is actually left.

reasonstringoptional

Why, in her words. Audited, and kept on the order.

attempt_idstring · uuidoptional

Idempotency key. A retry carrying the same one finds its own earlier work rather than paying twice.

Response, 200

orderobjectrequired

A guest order row (Order & Collect).

17 child fields
idstringrequired
store_idstringrequired
order_typestringrequired
fulfilment_statusstring, nullableoptional
collection_codestring, nullableoptional
payment_methodenumoptional
pay_nowbank_transfercash
order_page_pathstring, nullableoptional
payment_due_atstring, nullableoptional
collection_modestring, nullableoptional
requested_collection_atstring, nullableoptional
accepted_atstring, nullableoptional
preparing_atstring, nullableoptional
ready_atstring, nullableoptional
collected_atstring, nullableoptional
customer_namestring, nullableoptional
customer_emailstring, nullableoptional
customer_phonestring, nullableoptional
outcomeenumrequired
recordedalready_recorded
amount_pencenumberrequired

What THIS refund returned. Not the running total.

full_refundbooleanrequired

True when nothing is left outstanding, which also ends the order.

recorded_by_namestring, nullablerequired

Whose hand it was, for "Refunded by Romi".

curl -X POST "https://www.membber.com/api/v1/orders/b80cf509-0000-4000-8000-d0c5000000b8/offline-refund" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
  -H "Content-Type: application/json" \
  -d '{
    "store_id": "6659c139-0000-4000-8000-d0c500000066"
  }'
Response, 200
{
  "order": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "order_type": "<order_type>",
    "fulfilment_status": "<fulfilment_status>",
    "collection_code": "EXAMPLE10",
    "payment_method": "pay_now",
    "order_page_path": "<order_page_path>",
    "payment_due_at": "<payment_due_at>",
    "collection_mode": "<collection_mode>",
    "requested_collection_at": "<requested_collection_at>",
    "accepted_at": "<accepted_at>",
    "preparing_at": "<preparing_at>",
    "ready_at": "<ready_at>",
    "collected_at": "<collected_at>",
    "customer_name": "Alex Example",
    "customer_email": "alex@example.com",
    "customer_phone": "+44 7700 900123"
  },
  "outcome": "recorded",
  "amount_pence": 1500,
  "full_refund": true,
  "recorded_by_name": "<recorded_by_name>"
}

Refund an order (full or partial).

Staff-initiated refund. Validates the refund window + amount, then creates a Stripe refund, idempotent via a Stripe idempotency key derived from order + refund_attempt_id (a retry of the same tap never double-refunds, while two distinct taps with distinct ids each go through). The amount is exact: more than is still refundable (the order total less what has gone back, including what a lost dispute took) is refused with 409 REFUND_OVER_REMAINING and details.remaining_pence. A refund_attempt_id that already went through is answered with that refund; one still going through, or a refund that moved on the same order while this one was being placed, is 409 REFUND_IN_PROGRESS (retry with the same id); the same id re-sent with another amount is 409 REFUND_ATTEMPT_REUSED. Reverses loyalty + promo on a full refund.

Parameters

orderIdstringpathrequired

Request body

store_idstring · uuidrequired
reasonstringrequired

Why the order is being refunded (audited).

amount_penceinteger, nullableoptional

Refund amount in whole pence; omit/null to refund everything still left. Refunded exactly: more than is left is refused (409 REFUND_OVER_REMAINING, details.remaining_pence), never reduced.

refund_attempt_idstring · uuid, nullableoptional

Optional UUID for ONE merchant refund tap. A fresh id per tap makes two legitimate equal-amount/equal-reason refunds distinct; a retry of the same tap (same id) safely dedups via the Stripe idempotency key.

Response, 200

refundobjectrequired
3 child fields
idstringrequired
statusstring, nullablerequired
amountnumberrequired
curl -X POST "https://www.membber.com/api/v1/orders/b80cf509-0000-4000-8000-d0c5000000b8/refund" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
  -H "Content-Type: application/json" \
  -d '{
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "reason": "Added at the front desk"
  }'
Response, 200
{
  "refund": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "status": "<status>",
    "amount": 1500
  }
}

Let an unpaid order go, and put its stock back on sale.

The transfer never arrived. Ends the order (`cancelled`, `released_unpaid`), voids its stock holds and puts the quantities they held back on sale. The buyer is told separately, on the sweep, inside the shop’s sending hours, so a release at half past five in the morning does not wake anybody. Refused on a PAID order: releasing takes the goods back without returning the money, so there the instrument is a refund. Idempotent.

Parameters

orderIdstringpathrequired

Request body

store_idstring · uuidrequired

Store that owns the order.

reasonenumoptional

`merchant` when she decides, `stale` when the deadline passed. Defaults to the merchant.

merchantstale

Response, 200

orderobjectrequired

A guest order row (Order & Collect).

17 child fields
idstringrequired
store_idstringrequired
order_typestringrequired
fulfilment_statusstring, nullableoptional
collection_codestring, nullableoptional
payment_methodenumoptional
pay_nowbank_transfercash
order_page_pathstring, nullableoptional
payment_due_atstring, nullableoptional
collection_modestring, nullableoptional
requested_collection_atstring, nullableoptional
accepted_atstring, nullableoptional
preparing_atstring, nullableoptional
ready_atstring, nullableoptional
collected_atstring, nullableoptional
customer_namestring, nullableoptional
customer_emailstring, nullableoptional
customer_phonestring, nullableoptional
outcomeenumrequired
releasedalready_released
items_restockednumberrequired

How many item lines went back on sale.

holds_voidednumberrequired

How many stock holds were released.

curl -X POST "https://www.membber.com/api/v1/orders/b80cf509-0000-4000-8000-d0c5000000b8/release" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
  -H "Content-Type: application/json" \
  -d '{
    "store_id": "6659c139-0000-4000-8000-d0c500000066"
  }'
Response, 200
{
  "order": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "order_type": "<order_type>",
    "fulfilment_status": "<fulfilment_status>",
    "collection_code": "EXAMPLE10",
    "payment_method": "pay_now",
    "order_page_path": "<order_page_path>",
    "payment_due_at": "<payment_due_at>",
    "collection_mode": "<collection_mode>",
    "requested_collection_at": "<requested_collection_at>",
    "accepted_at": "<accepted_at>",
    "preparing_at": "<preparing_at>",
    "ready_at": "<ready_at>",
    "collected_at": "<collected_at>",
    "customer_name": "Alex Example",
    "customer_email": "alex@example.com",
    "customer_phone": "+44 7700 900123"
  },
  "outcome": "released",
  "items_restocked": 1,
  "holds_voided": 1
}

Set an Order & Collect order's business status (ready / fulfilled / cancelled).

Staff transition of the merchant status axis: ready, fulfilled, or cancelled. Backed by the idempotent updateGuestOrderStatus service (noop on a same-status repeat; store-scoped transition guard). Writes a store_payment_audit_logs row, bridges buy_now status changes onto the order_status_events outbox so the customer is notified, and releases slot + stock holds on cancel. Not money-moving (a refund is refundOrder).

Parameters

orderIdstringpathrequired

Request body

store_idstring · uuidrequired

Store that owns the order (also authorises the merchant).

statusenumrequired

Target business status: ready, fulfilled, or cancelled.

readyfulfilledcancelled
notestring, nullableoptional

Optional staff note, stored on the status change + audit row.

Response, 200

orderobjectrequired
6 child fields
idstringrequired
store_idstringrequired
statusstring, nullableoptional
order_typestring, nullableoptional
fulfilled_atstring, nullableoptional
cancelled_atstring, nullableoptional
curl -X PATCH "https://www.membber.com/api/v1/orders/b80cf509-0000-4000-8000-d0c5000000b8/status" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
  -H "Content-Type: application/json" \
  -d '{
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "status": "ready"
  }'
Response, 200
{
  "order": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "status": "<status>",
    "order_type": "<order_type>",
    "fulfilled_at": "<fulfilled_at>",
    "cancelled_at": "<cancelled_at>"
  }
}

Take back a drop order handover, within 10 minutes of it.

For the box handed to the wrong person. Puts back what the handover changed, in one transaction: the collect stage the order was in, any loyalty stamp the handover earned, and the cash when that same handover took it (money recorded earlier by Mark as paid stays recorded). Refused with UNDO_WINDOW_PASSED once the handover is more than 10 minutes old (server clock), and on a refunded, disputed or cancelled order. Idempotent: a replay returns `already_undone`. Drop orders only. People only: an AI agent key is refused.

Parameters

orderIdstringpathrequired

Request body

store_idstring · uuidrequired

Store that owns the order.

Response, 200

orderobjectrequired

A guest order row (Order & Collect).

17 child fields
idstringrequired
store_idstringrequired
order_typestringrequired
fulfilment_statusstring, nullableoptional
collection_codestring, nullableoptional
payment_methodenumoptional
pay_nowbank_transfercash
order_page_pathstring, nullableoptional
payment_due_atstring, nullableoptional
collection_modestring, nullableoptional
requested_collection_atstring, nullableoptional
accepted_atstring, nullableoptional
preparing_atstring, nullableoptional
ready_atstring, nullableoptional
collected_atstring, nullableoptional
customer_namestring, nullableoptional
customer_emailstring, nullableoptional
customer_phonestring, nullableoptional
outcomeenumrequired

`already_undone` when this is a replay of an undo that already landed: nothing changed twice.

undonealready_undone
back_tostring, nullablerequired

The stage the order went back to (`preparing` for a drop order).

cash_undonebooleanrequired

True when the handover had taken the cash: that money is owed on collection again.

amount_pencenumberrequired

The cash put back to owed, in pence. 0 when the handover took none.

curl -X POST "https://www.membber.com/api/v1/orders/b80cf509-0000-4000-8000-d0c5000000b8/undo-handover" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
  -H "Content-Type: application/json" \
  -d '{
    "store_id": "6659c139-0000-4000-8000-d0c500000066"
  }'
Response, 200
{
  "order": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "order_type": "<order_type>",
    "fulfilment_status": "<fulfilment_status>",
    "collection_code": "EXAMPLE10",
    "payment_method": "pay_now",
    "order_page_path": "<order_page_path>",
    "payment_due_at": "<payment_due_at>",
    "collection_mode": "<collection_mode>",
    "requested_collection_at": "<requested_collection_at>",
    "accepted_at": "<accepted_at>",
    "preparing_at": "<preparing_at>",
    "ready_at": "<ready_at>",
    "collected_at": "<collected_at>",
    "customer_name": "Alex Example",
    "customer_email": "alex@example.com",
    "customer_phone": "+44 7700 900123"
  },
  "outcome": "undone",
  "back_to": "<back_to>",
  "cash_undone": true,
  "amount_pence": 1500
}

Move an order to an earlier collection time (customer accepts early collection).

For an order that is ready before its booked slot, moves it onto an earlier open slot. Atomic and first-come-first-served: a full slot returns SLOT_JUST_FILLED (409) and the order keeps its original time; a slot that is not actually earlier returns NOT_EARLIER (400). Idempotent on the same slot.

Request body

store_idstring · uuidrequired

Store that owns the order (also part of the ownership check).

order_idstring · uuidrequired

The customer’s own order to move earlier.

slot_idstring · uuidrequired

The earlier, open collection slot to move onto.

Response, 200

to_slot_idstringrequired

The slot the order now holds.

requested_collection_atstringrequired

The new collection instant (ISO 8601, UTC).

orders_remaininginteger, nullablerequired

Places still free in the new slot, or null when it is uncapped.

curl -X POST "https://www.membber.com/api/v1/orders/collect-earlier" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
  -H "Content-Type: application/json" \
  -d '{
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "order_id": "4991ffac-0000-4000-8000-d0c500000049",
    "slot_id": "820a5efc-0000-4000-8000-d0c500000082"
  }'
Response, 200
{
  "to_slot_id": "098d6938-0000-4000-8000-d0c500000009",
  "requested_collection_at": "<requested_collection_at>",
  "orders_remaining": -9007199254740991
}

Confirm a native order after the payment sheet succeeds.

Resolves the order by PaymentIntent id, verifies ownership + the PI on the platform account, then runs the idempotent reconcile (mark paid + ledger + loyalty award). Safe alongside the Stripe webhook.

Request body

store_idstring · uuidrequired
payment_intent_idstringrequired

The PaymentIntent the sheet reported as succeeded.

Response, 200

order_idstringrequired
order_numberstringrequired
statusstringrequired
total_pencenumber, nullablerequired
currencystring, nullablerequired
subtotal_pencenumber, nullableoptional
discount_pencenumber, nullableoptional
promo_discount_pencenumber, nullableoptional
voucher_discount_pencenumber, nullableoptional
applied_voucher_idstring, nullableoptional
applied_promo_codestring, nullableoptional
applied_promo_labelstring, nullableoptional
payment_intent_idstringrequired
order_typestringrequired
collection_codestring, nullablerequired
fulfilment_statusstringrequired
prep_minutesnumber, nullablerequired
collection_modestring, nullableoptional
requested_collection_atstring, nullableoptional
loyalty_awardedbooleanoptional
stamps_addednumberoptional
stamp_countnumberoptional
goalnumberoptional
voucher_mintedbooleanoptional
ask_marketing_opt_inboolean, nullableoptional
reward_titlestring, nullableoptional
is_first_orderbooleanoptional
reward_unlock_messagestring, nullableoptional
welcome_messagestring, nullableoptional
childrenarray of objectoptional

Collect children of a mixed order (empty/absent for a normal order).

8 child fields
order_idstringrequired
order_numberstringrequired
order_typestringrequired
collection_codestring, nullablerequired
fulfilment_statusstringrequired
prep_minutesnumber, nullablerequired
requested_collection_atstring, nullablerequired
total_pencenumber, nullablerequired
curl -X POST "https://www.membber.com/api/v1/orders/confirm" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
  -H "Content-Type: application/json" \
  -d '{
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "payment_intent_id": "0b6642a5-0000-4000-8000-d0c50000000b"
  }'
Response, 200
{
  "order_id": "4991ffac-0000-4000-8000-d0c500000049",
  "order_number": "<order_number>",
  "status": "<status>",
  "total_pence": 1500,
  "currency": "GBP",
  "subtotal_pence": 1500,
  "discount_pence": 1500,
  "promo_discount_pence": 1500,
  "voucher_discount_pence": 1500,
  "applied_voucher_id": "e79b214e-0000-4000-8000-d0c5000000e7",
  "applied_promo_code": "EXAMPLE10",
  "applied_promo_label": "<applied_promo_label>",
  "payment_intent_id": "0b6642a5-0000-4000-8000-d0c50000000b",
  "order_type": "<order_type>",
  "collection_code": "EXAMPLE10",
  "fulfilment_status": "<fulfilment_status>",
  "prep_minutes": 1,
  "collection_mode": "<collection_mode>",
  "requested_collection_at": "<requested_collection_at>",
  "loyalty_awarded": true,
  "stamps_added": 1,
  "stamp_count": 1,
  "goal": 1,
  "voucher_minted": true,
  "ask_marketing_opt_in": true,
  "reward_title": "<reward_title>",
  "is_first_order": true,
  "reward_unlock_message": "Added at the front desk",
  "welcome_message": "Added at the front desk",
  "children": [
    {
      "order_id": "4991ffac-0000-4000-8000-d0c500000049",
      "order_number": "<order_number>",
      "order_type": "<order_type>",
      "collection_code": "EXAMPLE10",
      "fulfilment_status": "<fulfilment_status>",
      "prep_minutes": 1,
      "requested_collection_at": "<requested_collection_at>",
      "total_pence": 1500
    }
  ]
}
WhatsApp
Book a Call
Start Free