API referenceCustomer

Customer

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

List the signed-in customer's active collect legs across all stores.

Cross-store ACTIVE collect legs for the wallet Collections hub. One row per in-flight pickup (paid, not collected/cancelled) across every store the customer holds. Caller-only, index-backed, light by design so it is cheap to poll while a pickup is in flight.

Response, 200

legsarray of objectrequired
26 child fields
leg_idstringrequired

The collect leg's own guest_orders id (child_collect for a mixed leg, else the standalone order id).

order_idstringrequired

The order the customer owns (parent_order_id for a mixed leg, else leg_id).

order_numberstring, nullablerequired

Display order number (the parent's for a mixed leg).

store_idstringrequired
store_namestring, nullablerequired
store_logo_urlstring, nullablerequired
store_logo_blurhashstring, nullablerequired
store_primary_colorstring, nullablerequired
store_secondary_colorstring, nullablerequired
messaging_enabledbooleanrequired

Store has live chat → the tile can offer "Message <store>".

fulfilment_statusstringrequired

none | accepted | preparing | ready (active legs are never collected/cancelled).

collection_codestring, nullablerequired
collect_tokenstring, nullablerequired

What this leg's QR encodes: the leg identity, HMAC-signed. The short collection_code is a human label and is NOT sufficient to collect.

prep_minutesnumber, nullablerequired
collection_modestring, nullablerequired

'now' (ASAP) | 'scheduled' (booked slot).

requested_collection_atstring, nullablerequired

ISO instant of the booked slot (scheduled legs); null for ASAP.

accepted_atstring, nullablerequired
preparing_atstring, nullablerequired
ready_atstring, nullablerequired
created_atstringrequired
paid_atstring, nullablerequired
currencystringrequired
total_pencenumberrequired
refunded_pencenumberrequired
item_countnumberrequired
itemsarray of objectrequired
2 child fields
namestringrequired
quantitynumberrequired
curl -G "https://www.membber.com/api/v1/customer/active-collections" \
  -H "Authorization: Bearer $MEMBBER_TOKEN"
Response, 200
{
  "legs": [
    {
      "leg_id": "be0aecec-0000-4000-8000-d0c5000000be",
      "order_id": "4991ffac-0000-4000-8000-d0c500000049",
      "order_number": "<order_number>",
      "store_id": "6659c139-0000-4000-8000-d0c500000066",
      "store_name": "<store_name>",
      "store_logo_url": "https://example.com/image.jpg",
      "store_logo_blurhash": "<store_logo_blurhash>",
      "store_primary_color": "<store_primary_color>",
      "store_secondary_color": "<store_secondary_color>",
      "messaging_enabled": true,
      "fulfilment_status": "<fulfilment_status>",
      "collection_code": "EXAMPLE10",
      "collect_token": "<collect_token>",
      "prep_minutes": 1,
      "collection_mode": "<collection_mode>",
      "requested_collection_at": "<requested_collection_at>",
      "accepted_at": "<accepted_at>",
      "preparing_at": "<preparing_at>",
      "ready_at": "<ready_at>",
      "created_at": "<created_at>",
      "paid_at": "<paid_at>",
      "currency": "GBP",
      "total_pence": 1500,
      "refunded_pence": 1500,
      "item_count": 1,
      "items": [
        {
          "name": "Example name",
          "quantity": 1
        }
      ]
    }
  ]
}

Get the customer's booking for a class occurrence.

The signed-in customer's own booking for a specific class occurrence, with the occurrence and class context the iOS ClassBooking decoder needs (schedule, instructor, capacity, class details, promotion / reconfirmation state). Read-only. Only the caller own booking is ever returned; cancelled rows are excluded.

auth customer:readop getCustomerBookingByOccurrencerate limitederrors

Parameters

occurrenceIdstringpathrequired

Response, 200

bookingobjectrequired
24 child fields
idstringrequired

Booking id.

statusstringrequired

Booking status (waitlisted / promotion_pending / confirmed).

waitlistPositionnumber, nullablerequired

Rank in the waitlist queue, if waitlisted.

waitlistLockedboolean, nullablerequired

Whether the waitlist position is locked.

bookingDatestring, nullablerequired

Date the booking was made.

createdAtstring, nullablerequired

Row creation timestamp.

occurrenceIdstringrequired

The class occurrence this booking is for.

scheduledDatestring, nullablerequired

Occurrence scheduled date.

startTimestring, nullablerequired

Occurrence start time.

endTimestring, nullablerequired

Occurrence end time.

instructorNamestring, nullablerequired

Instructor for the occurrence.

maxCapacitynumber, nullablerequired

Occurrence maximum capacity.

confirmedCountnumber, nullablerequired

Number of confirmed bookings on the occurrence.

occurrenceStatusstring, nullablerequired

Occurrence status.

classNamestring, nullablerequired

Class name.

categorystring, nullablerequired

Class category.

descriptionstring, nullablerequired

Class description.

imageUrlstring, nullablerequired

Class image URL.

difficultystring, nullablerequired

Class difficulty.

durationMinutesnumber, nullablerequired

Class duration in minutes.

promotionExpiresAtstring, nullablerequired

When a pending promotion offer expires.

reconfirmationRequiredboolean, nullablerequired

Whether reconfirmation is required.

reconfirmationDeadlinestring, nullablerequired

Reconfirmation deadline.

reconfirmedAtstring, nullablerequired

When the booking was reconfirmed.

curl -G "https://www.membber.com/api/v1/customer/bookings/by-occurrence/a987c2cc-0000-4000-8000-d0c5000000a9" \
  -H "Authorization: Bearer $MEMBBER_TOKEN"
Response, 200
{
  "booking": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "status": "<status>",
    "waitlistPosition": 1,
    "waitlistLocked": true,
    "bookingDate": "<bookingDate>",
    "createdAt": "<createdAt>",
    "occurrenceId": "a987c2cc-0000-4000-8000-d0c5000000a9",
    "scheduledDate": "<scheduledDate>",
    "startTime": "<startTime>",
    "endTime": "<endTime>",
    "instructorName": "<instructorName>",
    "maxCapacity": 1,
    "confirmedCount": 1,
    "occurrenceStatus": "<occurrenceStatus>",
    "className": "<className>",
    "category": "<category>",
    "description": "Added at the front desk",
    "imageUrl": "https://example.com/image.jpg",
    "difficulty": "<difficulty>",
    "durationMinutes": 1,
    "promotionExpiresAt": "<promotionExpiresAt>",
    "reconfirmationRequired": true,
    "reconfirmationDeadline": "<reconfirmationDeadline>",
    "reconfirmedAt": "<reconfirmedAt>"
  }
}

Cancel a class booking or leave a waitlist (money-adjacent, may refund a drop-in).

The signed-in customer cancels one of their own class bookings or leaves a waitlist. Flips status + releases the seat + re-numbers the waitlist + cascades any pending promotion (cancel_class_booking), then classifies the drop-in refund early-vs-late (store-timezone aware) and issues it on the connected account. Idempotent at the service layer: the refund is deduped per (booking, trigger) and an already-cancelled booking is rejected, so a retry never double-refunds or double-releases a seat.

Request body

booking_idstring · uuidrequired

The caller own booking to cancel / leave. Ownership is enforced server-side against the session.

Response, 200

leftbooleanrequired

The booking was cancelled / the waitlist was left.

refundobjectrequired

The drop-in refund outcome for this cancellation (membership-paid bookings report a no-payment skip).

6 child fields
statusstringrequired

Refund outcome (succeeded / already_succeeded / skipped_no_payment / failed / ...).

triggerReasonstringrequired

How the refund was classified: voluntary_leave_early (full) or voluntary_leave_late (minus fee).

amountRefundedPencenumberrequired

Amount refunded to the member, in pence.

amountWithheldPencenumberrequired

Amount withheld (late-leave fee), in pence.

stripeRefundIdstring, nullablerequired

Stripe refund id, when a refund was actually issued.

errorMessagestring, nullablerequired

Non-fatal refund error message, if the refund engine failed.

curl -X POST "https://www.membber.com/api/v1/customer/bookings/cancel" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
  -H "Content-Type: application/json" \
  -d '{
    "booking_id": "ae11dec1-0000-4000-8000-d0c5000000ae"
  }'
Response, 200
{
  "left": true,
  "refund": {
    "status": "<status>",
    "triggerReason": "Added at the front desk",
    "amountRefundedPence": 1500,
    "amountWithheldPence": 1500,
    "stripeRefundId": "41b31220-0000-4000-8000-d0c500000041",
    "errorMessage": "Added at the front desk"
  }
}

Set or release a basket's soft stock hold.

Soft 5-minute stock hold for a customer basket. On add/quantity change the client sets the hold to the new quantity and reads back `granted` (so two shoppers can't both hold the last unit); on basket clear it releases every hold. Holds lapse on their own after 5 minutes. Idempotent, a set replaces (never stacks) the cart's hold.

Request body

cart_tokenstringrequired

Opaque per-basket token the client generates.

clearbooleanoptional

true → release every hold for this cart (item_id/quantity ignored).

item_idstringoptional

Stock-tracked menu item to hold (UUID). Required unless clear=true.

quantitynumberoptional

Desired hold quantity (clamped 0..99). Required unless clear=true.

Response, 200

trackedbooleanoptional

false when the item isn't stock-tracked (nothing held).

grantednumberoptional

How much of the requested quantity was actually held (the client caps the basket to this).

availablenumber, nullableoptional

Units still available to this cart after the grant (null when untracked).

clearednumberoptional

How many holds were released (clear mode only).

curl -X POST "https://www.membber.com/api/v1/customer/cart-hold" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
  -H "Content-Type: application/json" \
  -d '{
    "cart_token": "<cart_token>"
  }'
Response, 200
{
  "tracked": true,
  "granted": 1,
  "available": 1,
  "cleared": 1
}

Get a store's open collection slots + per-item availability for a date.

Customer mini-store collection slot picker: the open slots for the date (with tz-correct start instants) and, per collectable menu item, the earliest instant it can be collected (now + its lead time). The app greys an item for a chosen slot when earliest_collectable_at > slot.start_at.

Parameters

store_idstringqueryrequired

Store whose collection day-view to fetch.

datestringqueryrequired

Collection date (YYYY-MM-DD, interpreted in the store timezone).

Response, 200

datestringrequired

The requested date (echoed).

slotsarray of objectrequired
7 child fields
idstringrequired
start_timestringrequired

HH:MM

end_timestringrequired

HH:MM

orders_remainingnumberrequired
max_ordersnumberrequired
fullbooleanrequired
start_atstringrequired

ISO instant (store-tz aware).

itemsarray of objectrequired
3 child fields
idstringrequired
collect_eligiblebooleanrequired
earliest_collectable_atstringrequired

ISO instant = now + max(item prep, store default). Grey the item for a slot when this > slot.start_at.

curl -G "https://www.membber.com/api/v1/customer/collection-slots" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  --data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066" \
  --data-urlencode "date=<date>"
Response, 200
{
  "date": "<date>",
  "slots": [
    {
      "id": "00000d1b-0000-4000-8000-d0c500000000",
      "start_time": "<start_time>",
      "end_time": "<end_time>",
      "orders_remaining": 1,
      "max_orders": 1,
      "full": true,
      "start_at": "<start_at>"
    }
  ],
  "items": [
    {
      "id": "00000d1b-0000-4000-8000-d0c500000000",
      "collect_eligible": true,
      "earliest_collectable_at": "<earliest_collectable_at>"
    }
  ]
}

Get the signed-in customer's agreements across all their stores.

The customer app's "Your agreements" screen: every consent decision the member has recorded, across all of their stores plus the platform-scope Terms/Privacy, grouped by (agreement type, store) with each store's name, the full history newest first, and an up-to-date flag versus the active definition. The customer is always resolved from the session, never a client-supplied id.

Response, 200

groupsarray of objectrequired
9 child fields
agreement_typestringrequired
store_idstring, nullablerequired
store_namestring, nullablerequired
latest_decisionenumrequired
acceptedrejectedwithdrawn
latest_versionnumberrequired
latest_accepted_atstringrequired
active_versionnumber, nullablerequired
up_to_datebooleanrequired
eventsarray of objectrequired
11 child fields
idstringrequired
decisionenumrequired
acceptedrejectedwithdrawn
agreement_versionnumberrequired
accepted_atstringrequired
sourcestringrequired
terms_snapshotstring, nullablerequired
terms_urlstring, nullablerequired
ip_addressstring, nullablerequired
user_agentstring, nullablerequired
signature_image_urlstring, nullablerequired
metadataobjectrequired
curl -G "https://www.membber.com/api/v1/customer/consent/mine" \
  -H "Authorization: Bearer $MEMBBER_TOKEN"
Response, 200
{
  "groups": [
    {
      "agreement_type": "<agreement_type>",
      "store_id": "6659c139-0000-4000-8000-d0c500000066",
      "store_name": "<store_name>",
      "latest_decision": "accepted",
      "latest_version": 1,
      "latest_accepted_at": "<latest_accepted_at>",
      "active_version": 1,
      "up_to_date": true,
      "events": [
        {
          "id": "00000d1b-0000-4000-8000-d0c500000000",
          "decision": "accepted",
          "agreement_version": 1,
          "accepted_at": "<accepted_at>",
          "source": "<source>",
          "terms_snapshot": "<terms_snapshot>",
          "terms_url": "https://example.com/image.jpg",
          "ip_address": "<ip_address>",
          "user_agent": "<user_agent>",
          "signature_image_url": "https://example.com/image.jpg",
          "metadata": {}
        }
      ]
    }
  ]
}

Record the signed-in customer's consent decision for an agreement.

Records a customer accept / reject / withdraw decision against the active definition for a platform agreement type (Terms, Privacy, marketing), freezing the wording at the version validated. Powers the onboarding "Before you start" gate and the "Your agreements" withdraw affordance. The customer is always resolved from the session, never a client-supplied id. Appends to the immutable consent_events ledger.

Request body

agreement_typestringrequired

Agreement type to record against. One of: platform_terms, platform_privacy, marketing_email.

decisionstringrequired

The member's decision. One of: accepted, rejected, withdrawn.

store_idstring, nullableoptional

Consent scope: the store the agreement belongs to (null / omitted = platform scope). NOT an identity field.

client_terms_hashstringoptional

If supplied, must match the active definition hash (else CONSENT_STALE 409), guards a TOCTOU where the wording changed after the client fetched it.

Response, 200

event_idstringrequired
versionnumberrequired
curl -X POST "https://www.membber.com/api/v1/customer/consent/record" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
  -H "Content-Type: application/json" \
  -d '{
    "agreement_type": "<agreement_type>",
    "decision": "<decision>"
  }'
Response, 200
{
  "event_id": "1093c0e0-0000-4000-8000-d0c500000010",
  "version": 1
}

Get the platform agreements the onboarding gate must present.

Drives the onboarding "Before you start" gate: the platform Terms and Privacy (required, blocking) and the marketing opt-in (optional), each with whether the signed-in customer already satisfies it at the current version. needsGate is true when any required agreement is unsatisfied. The customer is always resolved from the session, never a client-supplied id.

Response, 200

needsGatebooleanrequired
consentsarray of objectrequired
9 child fields
agreement_typestringrequired
definition_idstringrequired
versionnumberrequired
terms_textstring, nullablerequired
terms_urlstring, nullablerequired
terms_hashstringrequired
requiredbooleanrequired
satisfiedbooleanrequired

member has a valid current-version ACCEPTANCE

answeredbooleanrequired

member made ANY current-version decision (accepted OR rejected), so a declined optional (marketing) is not re-asked as if never seen

curl -G "https://www.membber.com/api/v1/customer/consent/required" \
  -H "Authorization: Bearer $MEMBBER_TOKEN"
Response, 200
{
  "needsGate": true,
  "consents": [
    {
      "agreement_type": "<agreement_type>",
      "definition_id": "bc15d787-0000-4000-8000-d0c5000000bc",
      "version": 1,
      "terms_text": "<terms_text>",
      "terms_url": "https://example.com/image.jpg",
      "terms_hash": "<terms_hash>",
      "required": true,
      "satisfied": true,
      "answered": true
    }
  ]
}

Create or update the signed-in customer's emergency contact at a store.

The customer app's emergency-contact save: upserts the store-scoped member_emergency_contacts row (insert when no id is supplied, update the customer-scoped row when an id is), then recomputes onboarding progress (non-fatal, a failure is logged, never surfaced). Returns the saved contact. Idempotency is rpc-mode: the update path is idempotent (scoped by id + customer_id, converges to the same row on retry); the create path has no HTTP dedup, exactly matching the legacy route which sent no Idempotency-Key. The customer is always resolved from the session, never a client-supplied id.

Request body

store_idstring · uuidrequired

Store the emergency contact belongs to (the contact is store-scoped).

idstring · uuidoptional

Existing contact id to update; omit to create a new contact.

contact_namestringrequired

Emergency contact's full name (required).

contact_phonestringrequired

Emergency contact's phone number (required).

relationshipstring, nullableoptional

Relationship to the member (e.g. Partner, Parent).

is_primarybooleanoptional

Whether this is the primary emergency contact (defaults to false).

Response, 200

contactobjectrequired
9 child fields
idstringrequired

member_emergency_contacts row id.

customer_idstringrequired

The signed-in customer id (owner of the contact).

store_idstringrequired

Store the contact belongs to.

contact_namestringrequired
contact_phonestringrequired
relationshipstring, nullablerequired
is_primarybooleanrequired
created_atstringrequired
updated_atstringrequired
curl -X POST "https://www.membber.com/api/v1/customer/emergency-contacts" \
  -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",
    "contact_name": "<contact_name>",
    "contact_phone": "+44 7700 900123"
  }'
Response, 200
{
  "contact": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "customer_id": "96607d1c-0000-4000-8000-d0c500000096",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "contact_name": "<contact_name>",
    "contact_phone": "+44 7700 900123",
    "relationship": "<relationship>",
    "is_primary": true,
    "created_at": "<created_at>",
    "updated_at": "<updated_at>"
  }
}

List a store's upcoming events for the signed-in customer.

A store's active, upcoming special events sorted by date, each enriched with an is_booked flag set from the signed-in customer's own confirmed bookings. Read-only. The customer is resolved from the session; a client-supplied id is never trusted for identity.

auth customer:readop getCustomerUpcomingEventsrate limitederrors

Parameters

store_idstring · uuidqueryrequired

Store whose upcoming events to list.

Response, 200

eventsarray of objectrequired
18 child fields
idstringrequired

Event id.

store_idstringrequired

Store the event belongs to.

namestringrequired

Event name.

descriptionstring, nullablerequired

Event description.

event_datestringrequired

Event date (YYYY-MM-DD).

start_timestringrequired

Event start time.

end_timestring, nullablerequired

Event end time, if set.

locationstring, nullablerequired

Event location, if set.

price_pencenumberrequired

Ticket price in pence (0 = free).

currencystringrequired

ISO currency code for the price.

max_capacitynumber, nullablerequired

Capacity cap, if any.

is_members_onlybooleanrequired

Whether the event is restricted to members.

is_activebooleanrequired

Whether the event is active.

image_urlstring, nullablerequired

Event image URL, if set.

created_bystring, nullablerequired

Merchant user who created the event, if recorded.

created_atstringrequired

Row creation timestamp.

updated_atstringrequired

Row last-update timestamp.

is_bookedbooleanrequired

True when the signed-in customer holds a confirmed booking for this event.

curl -G "https://www.membber.com/api/v1/customer/events" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  --data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066"
Response, 200
{
  "events": [
    {
      "id": "00000d1b-0000-4000-8000-d0c500000000",
      "store_id": "6659c139-0000-4000-8000-d0c500000066",
      "name": "Example name",
      "description": "Added at the front desk",
      "event_date": "<event_date>",
      "start_time": "<start_time>",
      "end_time": "<end_time>",
      "location": "<location>",
      "price_pence": 1500,
      "currency": "GBP",
      "max_capacity": 1,
      "is_members_only": true,
      "is_active": true,
      "image_url": "https://example.com/image.jpg",
      "created_by": "<created_by>",
      "created_at": "<created_at>",
      "updated_at": "<updated_at>",
      "is_booked": true
    }
  ]
}

List the signed-in customer's order history at a store.

The Membber Customer iOS Orders list/detail feed: real persisted guest_orders scoped to the signed-in customer for one store. Caller-only, paid-only, keyset-paginated. details=false returns the LIGHT response for fast first render (summary rows, no thumbnails/collect children/loyalty aggregation).

auth customer:readop listCustomerStoreOrdersrate limitederrors

Parameters

store_idstringqueryrequired

Store whose order history to list.

limitintegerqueryoptional

Page size (default 20, max 50).

beforestringqueryoptional

Keyset cursor ("<created_at>|<id>") from a prior next_cursor.

detailsstringqueryoptional

Anything other than a case-insensitive "false" → FULL response; "false" → LIGHT response (summary rows only, no thumbnails/children/loyalty). Default true.

Response, 200

storeobjectrequired

Store branding + legal/receipt fields; null for an unknown store.

12 child fields
idstringrequired
codestring, nullablerequired
namestring, nullablerequired
logo_urlstring, nullablerequired
primary_colorstring, nullablerequired
reward_titlestring, nullablerequired
addressstring, nullablerequired
phonestring, nullablerequired
emailstring, nullablerequired
vat_registeredboolean, nullablerequired
vat_rate_percentnumber, nullablerequired
vat_numberstring, nullablerequired
ordersarray of objectrequired
39 child fields
order_idstringrequired
order_numberstring, nullablerequired
statusstringrequired

paid | ready | fulfilled | partially_refunded | refunded | disputed | cancelled

order_typestringrequired

'buy_now' | 'collect'

fulfilment_statusstring, nullablerequired
collection_codestring, nullablerequired
collect_tokenstring, nullablerequired

Signed QR payload for a STANDALONE collect order; null for buy-now and mixed parents (each leg carries its own).

prep_minutesnumber, nullablerequired
collection_modestring, nullablerequired
requested_collection_atstring, nullablerequired
currencystringrequired
subtotal_pencenumberrequired
discount_pencenumberrequired
promo_discount_pencenumberrequired
voucher_discount_pencenumberrequired
applied_promo_codestring, nullablerequired
applied_promo_labelstring, nullablerequired
tip_pencenumberrequired
service_charge_pencenumberrequired
vat_pencenumberrequired
vat_rate_percentnumberrequired

The store rate only when it verifiably matches this order's snapshot, else 0.

total_pencenumberrequired
refunded_pencenumberrequired
created_atstringrequired
paid_atstring, nullablerequired
accepted_atstring, nullablerequired
preparing_atstring, nullablerequired
ready_atstring, nullablerequired
collected_atstring, nullablerequired
item_countnumberrequired
itemsarray of objectrequired
6 child fields
menu_item_idstring, nullablerequired
namestringrequired
quantitynumberrequired
unit_amount_pencenumberrequired
line_total_pencenumberrequired
image_urlstring, nullablerequired

Joined from menu_items; null when the item was deleted.

allowed_actionsarray of enumrequired
reorderreceipttrackmessagereport
loyalty_awardedbooleanrequired
stamps_earnednumberrequired
voucher_earnedbooleanrequired
fulfilment_rolestringrequired

'standalone' | 'parent'

handed_over_atstring, nullablerequired
groupsarray of objectrequired
15 child fields
child_order_idstringrequired
collection_codestring, nullablerequired
collect_tokenstring, nullablerequired

What this leg's QR encodes: the leg identity, HMAC-signed. The short collection_code is a human label and is NOT sufficient to collect.

fulfilment_statusstring, nullablerequired

none | accepted | preparing | ready | collected | cancelled

prep_minutesnumber, nullablerequired
collection_modestring, nullablerequired
requested_collection_atstring, nullablerequired
accepted_atstring, nullablerequired
preparing_atstring, nullablerequired
ready_atstring, nullablerequired
collected_atstring, nullablerequired
total_pencenumberrequired
refunded_pencenumberrequired
item_countnumberrequired
itemsarray of objectrequired
6 child fields
menu_item_idstring, nullablerequired
namestringrequired
quantitynumberrequired
unit_amount_pencenumberrequired
line_total_pencenumberrequired
image_urlstring, nullablerequired

Joined from menu_items; null when the item was deleted.

overall_statusstringrequired

in_progress | ready | complete | cancelled | refunded

next_cursorstring, nullablerequired

Pass as ?before= for the next page.

has_morebooleanrequired
curl -G "https://www.membber.com/api/v1/customer/orders" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  --data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066"
Response, 200
{
  "store": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "code": "EXAMPLE10",
    "name": "Example name",
    "logo_url": "https://example.com/image.jpg",
    "primary_color": "<primary_color>",
    "reward_title": "<reward_title>",
    "address": "<address>",
    "phone": "+44 7700 900123",
    "email": "alex@example.com",
    "vat_registered": true,
    "vat_rate_percent": 1,
    "vat_number": "<vat_number>"
  },
  "orders": [
    {
      "order_id": "4991ffac-0000-4000-8000-d0c500000049",
      "order_number": "<order_number>",
      "status": "<status>",
      "order_type": "<order_type>",
      "fulfilment_status": "<fulfilment_status>",
      "collection_code": "EXAMPLE10",
      "collect_token": "<collect_token>",
      "prep_minutes": 1,
      "collection_mode": "<collection_mode>",
      "requested_collection_at": "<requested_collection_at>",
      "currency": "GBP",
      "subtotal_pence": 1500,
      "discount_pence": 1500,
      "promo_discount_pence": 1500,
      "voucher_discount_pence": 1500,
      "applied_promo_code": "EXAMPLE10",
      "applied_promo_label": "<applied_promo_label>",
      "tip_pence": 1500,
      "service_charge_pence": 1500,
      "vat_pence": 1500,
      "vat_rate_percent": 1,
      "total_pence": 1500,
      "refunded_pence": 1500,
      "created_at": "<created_at>",
      "paid_at": "<paid_at>",
      "accepted_at": "<accepted_at>",
      "preparing_at": "<preparing_at>",
      "ready_at": "<ready_at>",
      "collected_at": "<collected_at>",
      "item_count": 1,
      "items": [
        {
          "menu_item_id": "ca65a6e7-0000-4000-8000-d0c5000000ca",
          "name": "Example name",
          "quantity": 1,
          "unit_amount_pence": 1500,
          "line_total_pence": 1500,
          "image_url": "https://example.com/image.jpg"
        }
      ],
      "allowed_actions": [
        "reorder"
      ],
      "loyalty_awarded": true,
      "stamps_earned": 1,
      "voucher_earned": true,
      "fulfilment_role": "<fulfilment_role>",
      "handed_over_at": "<handed_over_at>",
      "groups": [
        {
          "child_order_id": "f1ff3b6f-0000-4000-8000-d0c5000000f1",
          "collection_code": "EXAMPLE10",
          "collect_token": "<collect_token>",
          "fulfilment_status": "<fulfilment_status>",
          "prep_minutes": 1,
          "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>",
          "total_pence": 1500,
          "refunded_pence": 1500,
          "item_count": 1,
          "items": [
            {
              "menu_item_id": null,
              "name": null,
              "quantity": null,
              "unit_amount_pence": null,
              "line_total_pence": null,
              "image_url": null
            }
          ]
        }
      ],
      "overall_status": "<overall_status>"
    }
  ],
  "next_cursor": "<next_cursor>",
  "has_more": true
}

Request a refund on a mini-store order.

Creates a refund_requests row (status=requested) for the merchant to approve or reject. NO money moves here, approval is always a human merchant decision. Validates order ownership, refundability, the refund window, and a remaining balance; a duplicate open request 409s (idempotent via the unique index).

Parameters

orderIdstringpathrequired

Request body

store_idstringrequired

Store the order belongs to.

reason_codestringrequired

One of item_missing | wrong_item | quality | not_received | other.

messagestring, nullableoptional

Optional free-text detail from the customer.

amount_penceinteger, nullableoptional

Optional partial amount in pence; omit/null to request the full remaining balance.

Response, 200

requestobjectrequired
4 child fields
idstringrequired
statusstringrequired
reason_codestringrequired
created_atstringrequired
curl -X POST "https://www.membber.com/api/v1/customer/orders/b80cf509-0000-4000-8000-d0c5000000b8/refund-request" \
  -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_code": "Added at the front desk"
  }'
Response, 200
{
  "request": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "status": "<status>",
    "reason_code": "Added at the front desk",
    "created_at": "<created_at>"
  }
}

Get the customer's most-recent paid order at a store (reorder seed).

Powers the one-tap "Order again" card. Returns the single newest paid order for the signed-in customer at one store, trimmed to order_number + order_type + collection_mode + bare item lines. The client re-prices and re-validates each line against the CURRENT menu, so no stale prices are ever returned.

Parameters

store_idstringqueryrequired

Store whose most-recent paid order to seed a reorder from.

Response, 200

orderobjectrequired

The newest paid order trimmed to what a reorder needs; null when there is none.

4 child fields
order_numberstring, nullablerequired
order_typestringrequired

'buy_now' | 'collect'

collection_modestring, nullablerequired

'now' | 'scheduled' | null

itemsarray of objectrequired
3 child fields
menu_item_idstring, nullablerequired
namestringrequired
quantitynumberrequired
curl -G "https://www.membber.com/api/v1/customer/orders/recent" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  --data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066"
Response, 200
{
  "order": {
    "order_number": "<order_number>",
    "order_type": "<order_type>",
    "collection_mode": "<collection_mode>",
    "items": [
      {
        "menu_item_id": "ca65a6e7-0000-4000-8000-d0c5000000ca",
        "name": "Example name",
        "quantity": 1
      }
    ]
  }
}

Get the signed-in customer's profile at a store.

The customer profile for one store: the store-scoped member_profiles row (health, address, ID verification fields) merged with the name and email from the customers table, so the settings screen can render one unified form. If no profile row exists yet, an empty shell is returned carrying the customer id, store id, name and email. The customer is always resolved from the session, never a client-supplied id.

Parameters

store_idstring · uuidqueryrequired

Store whose profile to read (the profile is store-scoped).

Response, 200

profileobjectrequired
20 child fields
idstringrequired

member_profiles row id, or an empty string when no profile exists yet.

customer_idstringrequired

The signed-in customer id.

store_idstringrequired

Store the profile belongs to.

namestring, nullablerequired

Customer display name from the customers table.

emailstring, nullablerequired

Customer email from the customers table.

profile_image_urlstring, nullableoptional
genderstring, nullableoptional
date_of_birthstring, nullableoptional
address_line_1string, nullableoptional
address_line_2string, nullableoptional
citystring, nullableoptional
postcodestring, nullableoptional
medical_notesstring, nullableoptional
id_document_urlstring, nullableoptional
id_verification_statusstringoptional
id_verified_atstring, nullableoptional
id_verified_bystring, nullableoptional
id_rejection_reasonstring, nullableoptional
created_atstringoptional
updated_atstringoptional
curl -G "https://www.membber.com/api/v1/customer/profile" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  --data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066"
Response, 200
{
  "profile": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "customer_id": "96607d1c-0000-4000-8000-d0c500000096",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "name": "Example name",
    "email": "alex@example.com",
    "profile_image_url": "https://example.com/image.jpg",
    "gender": "<gender>",
    "date_of_birth": "<date_of_birth>",
    "address_line_1": "<address_line_1>",
    "address_line_2": "<address_line_2>",
    "city": "<city>",
    "postcode": "EXAMPLE10",
    "medical_notes": "Added at the front desk",
    "id_document_url": "https://example.com/image.jpg",
    "id_verification_status": "<id_verification_status>",
    "id_verified_at": "<id_verified_at>",
    "id_verified_by": "<id_verified_by>",
    "id_rejection_reason": "Added at the front desk",
    "created_at": "<created_at>",
    "updated_at": "<updated_at>"
  }
}

Create or update the signed-in customer's profile at a store.

The customer app auto-save for the settings form: upserts the store-scoped member_profiles row (health, address, gender) and updates name/email on the customers table, then recomputes onboarding progress (non-fatal). Returns the merged profile view (identical shape to getCustomerProfile). Idempotent: the member_profiles upsert is keyed on (customer_id, store_id) and the customers update is a plain set, so a retried identical request converges to the same state. The customer is always resolved from the session, never a client-supplied id.

Request body

store_idstring · uuidrequired

Store whose profile to write (the profile is store-scoped).

namestring, nullableoptional

Customer display name (persisted on the customers table).

emailstring, nullableoptional

Customer email (lower-cased + trimmed server-side; customers table).

genderstring, nullableoptional

Gender display string; normalized to the DB value server-side.

date_of_birthstring, nullableoptional

ISO date; empty string is coerced to null.

address_line_1string, nullableoptional
address_line_2string, nullableoptional
citystring, nullableoptional
postcodestring, nullableoptional
medical_notesstring, nullableoptional

Response, 200

profileobjectrequired
20 child fields
idstringrequired

member_profiles row id.

customer_idstringrequired

The signed-in customer id.

store_idstringrequired

Store the profile belongs to.

namestring, nullablerequired

Customer display name from the customers table.

emailstring, nullablerequired

Customer email from the customers table.

profile_image_urlstring, nullableoptional
genderstring, nullableoptional
date_of_birthstring, nullableoptional
address_line_1string, nullableoptional
address_line_2string, nullableoptional
citystring, nullableoptional
postcodestring, nullableoptional
medical_notesstring, nullableoptional
id_document_urlstring, nullableoptional
id_verification_statusstringoptional
id_verified_atstring, nullableoptional
id_verified_bystring, nullableoptional
id_rejection_reasonstring, nullableoptional
created_atstringoptional
updated_atstringoptional
curl -X POST "https://www.membber.com/api/v1/customer/profile" \
  -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
{
  "profile": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "customer_id": "96607d1c-0000-4000-8000-d0c500000096",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "name": "Example name",
    "email": "alex@example.com",
    "profile_image_url": "https://example.com/image.jpg",
    "gender": "<gender>",
    "date_of_birth": "<date_of_birth>",
    "address_line_1": "<address_line_1>",
    "address_line_2": "<address_line_2>",
    "city": "<city>",
    "postcode": "EXAMPLE10",
    "medical_notes": "Added at the front desk",
    "id_document_url": "https://example.com/image.jpg",
    "id_verification_status": "<id_verification_status>",
    "id_verified_at": "<id_verified_at>",
    "id_verified_by": "<id_verified_by>",
    "id_rejection_reason": "Added at the front desk",
    "created_at": "<created_at>",
    "updated_at": "<updated_at>"
  }
}

Get the member's booking readiness for a store.

Booking pre-flight check for the signed-in customer at a given store: whether they satisfy the store-configured requirements (health questionnaire, waivers, emergency contact), the list of any outstanding requirement keys, and the per-requirement status. Each requirement is only enforced when the store enables it. The member is resolved from the session; the store is context, never identity.

Parameters

store_idstring · uuidqueryrequired

Store whose booking requirements to check readiness against (context, not identity).

Response, 200

readybooleanrequired

True when every store-required item is satisfied (missing is empty).

missingarray of stringrequired

The requirement keys still outstanding (e.g. 'health_questionnaire', 'waiver', 'emergency_contact').

healthQuestionnaireValidbooleanrequired

Whether a valid, unexpired health questionnaire is on file (true when not required by the store).

waiversCompletebooleanrequired

Whether all active waivers are signed (true when not required by the store).

emergencyContactSetbooleanrequired

Whether at least one emergency contact is on file (true when not required by the store).

curl -G "https://www.membber.com/api/v1/customer/readiness" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  --data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066"
Response, 200
{
  "ready": true,
  "missing": [
    "<missing>"
  ],
  "healthQuestionnaireValid": true,
  "waiversComplete": true,
  "emergencyContactSet": true
}
WhatsApp
Book a Call
Start Free