API referenceBookings

Bookings

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

Quick-add a booking as the merchant.

Books a walk-up / phone appointment as the merchant, into a unit the authenticated store owns. Wraps the one booking authority, so a normal add still cannot double-book. With `override: true` the merchant FORCE-BOOKS a squeeze-in the authority would refuse, the resulting block is exempt from the double-booking guard and blocks nobody. Idempotent per `client_token`. No money moves.

Request body

store_idstring · uuidrequired
unit_idstring · uuidrequired

The staff member / room / table to book. Must belong to the authenticated store.

service_idstring · uuid, nullableoptional
starts_atstringrequired

ISO instant the appointment starts.

ends_atstringrequired

ISO instant the appointment ends.

customer_idstring · uuid, nullableoptional

An existing customer to book for.

guest_namestring, nullableoptional

Who the appointment is for, for a walk-up with no account.

guest_emailstring · email, nullableoptional

Required if there is no customer_id, someone must be reachable.

guest_phonestring, nullableoptional
party_sizeintegeroptional
price_penceintegeroptional

Agreed price, snapshotted onto the appointment.

block_starts_atstring, nullableoptional

Widen what the UNIT is occupied for (buffers), without changing what the customer is told.

block_ends_atstring, nullableoptional
overridebooleanoptional

FORCE-BOOK: squeeze this in even where the availability authority would refuse. The merchant-only power, a squeeze-in blocks nobody else. Defaults to false.

client_tokenstringoptional

Caller-generated idempotency key, a retry with the same token returns the SAME appointment, never a duplicate.

Response, 200

appointmentobjectrequired
21 child fields
idstringrequired
store_idstringrequired
unit_idstringrequired
service_idstring, nullablerequired
customer_idstring, nullablerequired
guest_namestring, nullablerequired
guest_emailstring, nullablerequired
guest_phonestring, nullablerequired
starts_atstringrequired
ends_atstringrequired
statusstringrequired
payment_statusstringrequired
price_pencenumberrequired
deposit_pencenumberrequired
balance_pencenumberrequired
currencystringrequired
party_sizenumberrequired
childrennumberrequired

How many of the party are children (age 12 and under). 0 for a normal appointment.

high_chairsnumberrequired

High chairs the diner asked for, so the host can fetch them.

sourcestringrequired
is_overridebooleanrequired
reusedbooleanrequired

true when an idempotent retry returned the appointment the first call created.

curl -X POST "https://www.membber.com/api/v1/bookings/appointments" \
  -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",
    "unit_id": "eeebf9b6-0000-4000-8000-d0c5000000ee",
    "starts_at": "<starts_at>",
    "ends_at": "<ends_at>"
  }'
Response, 200
{
  "appointment": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "unit_id": "eeebf9b6-0000-4000-8000-d0c5000000ee",
    "service_id": "993232e5-0000-4000-8000-d0c500000099",
    "customer_id": "96607d1c-0000-4000-8000-d0c500000096",
    "guest_name": "<guest_name>",
    "guest_email": "alex@example.com",
    "guest_phone": "+44 7700 900123",
    "starts_at": "<starts_at>",
    "ends_at": "<ends_at>",
    "status": "<status>",
    "payment_status": "<payment_status>",
    "price_pence": 1500,
    "deposit_pence": 1500,
    "balance_pence": 1500,
    "currency": "GBP",
    "party_size": 1,
    "children": 1,
    "high_chairs": 1,
    "source": "<source>",
    "is_override": true
  },
  "reused": true
}

Cancel an appointment as the merchant.

Cancels a booking the authenticated store owns and frees its slot (the block is RELEASED, never deleted, so the audit trail survives). Idempotent, cancelling twice is a no-op, never a second state change. No fee is charged here (cancel/no-show fees are Stage 7).

Request body

store_idstring · uuidrequired
appointment_idstring · uuidrequired

The appointment to cancel. Must belong to the authenticated store.

reasonstring, nullableoptional

Why, for the record.

Response, 200

appointment_idstringrequired
cancelledbooleanrequired
noopbooleanrequired

true when it was already cancelled/completed, an idempotent no-op.

curl -X POST "https://www.membber.com/api/v1/bookings/appointments/cancel" \
  -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",
    "appointment_id": "0d727dbb-0000-4000-8000-d0c50000000d"
  }'
Response, 200
{
  "appointment_id": "0d727dbb-0000-4000-8000-d0c50000000d",
  "cancelled": true,
  "noop": true
}

Check a customer in.

Marks a confirmed appointment as checked-in (they have arrived). Single-winner: only a confirmed booking can be checked in, and a second check-in is a no-op. Store-scoped. Audited. No money moves.

Request body

store_idstring · uuidrequired
appointment_idstring · uuidrequired

The appointment. Must belong to the authenticated store.

Response, 200

appointment_idstringrequired
statusstringrequired

The status the appointment now holds.

noopbooleanrequired

true when it was already in that status, an idempotent no-op.

curl -X POST "https://www.membber.com/api/v1/bookings/appointments/check-in" \
  -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",
    "appointment_id": "0d727dbb-0000-4000-8000-d0c50000000d"
  }'
Response, 200
{
  "appointment_id": "0d727dbb-0000-4000-8000-d0c50000000d",
  "status": "<status>",
  "noop": true
}

Complete an appointment.

Marks an appointment done, from confirmed or checked-in. Single-winner: a second complete is a no-op, and a cancelled / no-show booking cannot be completed. Store-scoped. Audited. No money moves (settle is Stage 6).

Request body

store_idstring · uuidrequired
appointment_idstring · uuidrequired

The appointment. Must belong to the authenticated store.

Response, 200

appointment_idstringrequired
statusstringrequired

The status the appointment now holds.

noopbooleanrequired

true when it was already in that status, an idempotent no-op.

curl -X POST "https://www.membber.com/api/v1/bookings/appointments/complete" \
  -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",
    "appointment_id": "0d727dbb-0000-4000-8000-d0c50000000d"
  }'
Response, 200
{
  "appointment_id": "0d727dbb-0000-4000-8000-d0c50000000d",
  "status": "<status>",
  "noop": true
}

Record a no-show.

Marks a DUE confirmed appointment as a no-show (the time has passed and nobody came). A checked-in guest showed up, so a no-show cannot fire from checked-in; a future booking is not yet due and is refused. Single-winner and idempotent. Store-scoped. Audited. NO fee is charged here (no-show fees are Stage 7).

Request body

store_idstring · uuidrequired
appointment_idstring · uuidrequired

The appointment. Must belong to the authenticated store.

Response, 200

appointment_idstringrequired
statusstringrequired

The status the appointment now holds.

noopbooleanrequired

true when it was already in that status, an idempotent no-op.

curl -X POST "https://www.membber.com/api/v1/bookings/appointments/no-show" \
  -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",
    "appointment_id": "0d727dbb-0000-4000-8000-d0c50000000d"
  }'
Response, 200
{
  "appointment_id": "0d727dbb-0000-4000-8000-d0c50000000d",
  "status": "<status>",
  "noop": true
}

Move an appointment as the merchant.

Secures the NEW slot before releasing the OLD, so a half-failed move leaves the original untouched. Both the appointment and the destination unit must belong to the authenticated store. With `override: true` the merchant moves past the cancellation window and past the free-slot check (their diary, their call), a power the customer reschedule never has.

Request body

store_idstring · uuidrequired
appointment_idstring · uuidrequired

The appointment to move. Must belong to the authenticated store.

unit_idstring · uuidrequired

Where it is moving to, may be the same unit. Must belong to the authenticated store.

starts_atstringrequired

ISO instant of the new start.

ends_atstringrequired

ISO instant of the new end.

block_starts_atstring, nullableoptional
block_ends_atstring, nullableoptional
overridebooleanoptional

Move even inside the cancellation policy window and even onto an occupied slot (a merchant squeeze-move). The merchant-only power. Defaults to false (respects the window and the free-slot check).

Response, 200

appointment_idstringrequired
unit_idstringrequired
starts_atstringrequired
ends_atstringrequired
moved_in_placebooleanrequired

true when the booking was nudged within the same unit.

curl -X POST "https://www.membber.com/api/v1/bookings/appointments/reschedule" \
  -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",
    "appointment_id": "0d727dbb-0000-4000-8000-d0c50000000d",
    "unit_id": "eeebf9b6-0000-4000-8000-d0c5000000ee",
    "starts_at": "<starts_at>",
    "ends_at": "<ends_at>"
  }'
Response, 200
{
  "appointment_id": "0d727dbb-0000-4000-8000-d0c50000000d",
  "unit_id": "eeebf9b6-0000-4000-8000-d0c5000000ee",
  "starts_at": "<starts_at>",
  "ends_at": "<ends_at>",
  "moved_in_place": true
}

Search the appointment history by person.

Answers "when was this person last in?" across the store's WHOLE history, grouped by person rather than by row. Store-wide and business-authenticated; the store is the authenticated store, never a client-supplied id. A customer who has been deleted under the data-integrity law is unfindable here: their financial rows stay in the books, but their identity cannot be searched back out of them. Counts are real statuses only, visits means completed or checked-in, and no-shows, cancellations and unresolved past bookings are each reported as themselves.

auth merchant:readop searchAppointmentPeoplerate limitederrors

Parameters

store_idstring · uuidqueryrequired
qstringqueryrequired

Part of a name or an email address. Two characters minimum: one letter matches most of a roster.

limitintegerqueryoptional

How many people to return. Default 20.

visit_limitintegerqueryoptional

How many recent appointments per person. Default 12.

Response, 200

store_idstringrequired
timezonestringrequired

The store's IANA timezone, every instant above is anchored to it for display.

querystringrequired

The normalised needle actually searched for.

totalnumberrequired

How many people matched in total, counted BEFORE `limit`, so a client can say "20 of 34" honestly.

peoplearray of objectrequired

Most recently seen first.

14 child fields
keystringrequired

Stable grouping key for this person within this store. `c:<customer_id>` for an account booking, `g:<name>|<email>` for a guest, a guest has no id, so name plus email is the most honest identity the data supports. Two different people sharing both would merge; nothing in the data can separate them.

customer_idstring, nullablerequired

Set only where the booking was made from an account.

namestringrequired

The most recent name this person booked under.

emailstring, nullablerequired
currencystringrequired
visitsnumberrequired

Times they were actually in the chair: completed + checked-in. A no-show is not a visit and is counted separately.

no_showsnumberrequired
cancellednumberrequired
unresolvednumberrequired

Past appointments still sitting in `confirmed`, nobody ever said whether they came. Reported on its own rather than guessed either way; this is the state B497 found two of yesterday's rows in.

first_visitstring, nullablerequired

ISO instant of their first actual visit.

last_visitstring, nullablerequired

ISO instant of their most recent actual visit, the answer to the question.

next_visitstring, nullablerequired

ISO instant of their soonest future booking, if any.

spend_pencenumberrequired

Sum of the price on visits that happened. Not a forecast, not a lifetime value.

recentarray of objectrequired

Their most recent appointments, newest first, capped by `visit_limit`.

8 child fields
idstringrequired
starts_atstringrequired

ISO instant the appointment started.

ends_atstringrequired
statusstringrequired

'completed' | 'checked_in' | 'confirmed' | 'cancelled' | 'no_show' | 'pending_payment'.

payment_statusstringrequired
price_pencenumberrequired
currencystringrequired
unit_namestring, nullablerequired

Who or what they were booked with.

curl -G "https://www.membber.com/api/v1/bookings/appointments/search" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  --data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066" \
  --data-urlencode "q=<q>"
Response, 200
{
  "store_id": "6659c139-0000-4000-8000-d0c500000066",
  "timezone": "Europe/London",
  "query": "<query>",
  "total": 1,
  "people": [
    {
      "key": "<key>",
      "customer_id": "96607d1c-0000-4000-8000-d0c500000096",
      "name": "Example name",
      "email": "alex@example.com",
      "currency": "GBP",
      "visits": 1,
      "no_shows": 1,
      "cancelled": 1,
      "unresolved": 1,
      "first_visit": "<first_visit>",
      "last_visit": "<last_visit>",
      "next_visit": "<next_visit>",
      "spend_pence": 1500,
      "recent": [
        {
          "id": "00000d1b-0000-4000-8000-d0c500000000",
          "starts_at": "<starts_at>",
          "ends_at": "<ends_at>",
          "status": "<status>",
          "payment_status": "<payment_status>",
          "price_pence": 1500,
          "currency": "GBP",
          "unit_name": "<unit_name>"
        }
      ]
    }
  ]
}

Record what is still owed on an appointment as taken.

The merchant takes the outstanding balance at the end of an appointment, in cash or on their own card machine, and records it here. NO Stripe money moves and no platform fee is taken, the money changed hands outside Membber, so this row is the only evidence it was collected. The amount is DERIVED server-side (price − deposit actually paid − everything already settled) and is never accepted from the client. Settling completes the appointment. A short settle leaves the residual collectable: the no-op gate is "nothing outstanding", never "already stamped", and the recorded total accumulates. Nothing outstanding is an idempotent no-op rather than an error, and a retry can never record twice. Losing a race to a colleague comes back as outcome=already_settled with who/how/how much, never as your own success. A no-show is never settled here (that is the no-show fee path). Store-scoped and business-authed; gated by the can_use_bookings entitlement + the can_process_payments staff permission.

Request body

store_idstring · uuidrequired

Store the appointment belongs to (authorisation only, the store acted on always comes from auth).

appointment_idstring · uuidrequired

The appointment to settle. Must belong to the authenticated store.

methodenumrequired

How the money was taken. Both are RECORDED ONLY (the money moved outside Membber, at the counter or on the shop's own terminal, so this is the only record it was collected). No Stripe charge is made and no platform fee is taken.

cashcard_machine

Response, 200

outcomeenumrequired

'settled' = this call recorded the money. 'already_settled' = somebody else's settle got there first and this call recorded nothing (never draw it as your own success, the person who lost may be holding the cash). 'nothing_owed' = there was nothing left to take.

settledalready_settlednothing_owed
appointment_idstringrequired
statusstringrequired

The appointment status after the call, settling completes the appointment.

payment_statusstringrequired

'none' | 'deposit_paid' | 'paid' | 'refunded' | 'partially_refunded' | 'failed'.

outstanding_pencenumberrequired

What is STILL owed AFTER this call, derived server-side as price − deposit actually paid − everything settled. Unambiguous on every outcome, so a client can write it straight onto the row it is showing.

collected_pencenumberrequired

What THIS call recorded. 0 on any outcome other than 'settled'.

settled_total_pencenumberrequired

Everything ever recorded as settled on this booking, this call included.

currencystringrequired
methodenumoptional

How the settle being reported was taken (null when nothing was ever owed).

cashcard_machine
settled_atstring, nullableoptional

ISO instant of the settle being reported.

settled_by_youbooleanrequired

true when the settle being reported is the caller's own.

settled_by_namestring, nullableoptional

Who recorded it, when that was somebody else and we can name them. null = we cannot say who.

curl -X POST "https://www.membber.com/api/v1/bookings/appointments/settle" \
  -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",
    "appointment_id": "0d727dbb-0000-4000-8000-d0c50000000d",
    "method": "cash"
  }'
Response, 200
{
  "outcome": "settled",
  "appointment_id": "0d727dbb-0000-4000-8000-d0c50000000d",
  "status": "<status>",
  "payment_status": "<payment_status>",
  "outstanding_pence": 1500,
  "collected_pence": 1500,
  "settled_total_pence": 1500,
  "currency": "GBP",
  "method": "cash",
  "settled_at": "<settled_at>",
  "settled_by_you": true,
  "settled_by_name": "<settled_by_name>"
}

The store's day, grouped by unit.

The merchant view of the diary: every active bookable unit for a date RANGE (store-local dates), each carrying its appointments, live holds and time-off. Store-wide and business-authenticated, the customer appointments read is caller-scoped and cannot see another booking. Timezone-correct: day boundaries read the store timezone.

Parameters

store_idstring · uuidqueryrequired
from_datestringqueryrequired

First day to show, in the STORE's timezone.

to_datestringqueryrequired

Last day to show (inclusive), in the STORE's timezone.

unit_idstring · uuid, nullablequeryoptional

Restrict to one unit. Omit for every unit (the full diary).

include_cancelledbooleanqueryoptional

Include cancelled appointments. Defaults to excluding them.

Response, 200

store_idstringrequired
timezonestringrequired

The store's IANA timezone, every instant below is anchored to it for display.

fromstringrequired

ISO instant the window starts (00:00 store-local on from_date).

tostringrequired

ISO instant the window ends, EXCLUSIVE (00:00 store-local the day after to_date).

unitsarray of objectrequired

Every active bookable unit, each with its appointments, holds and time-off.

4 child fields
unitobjectrequired
11 child fields
idstringrequired
display_namestringrequired
kindstringrequired
unit_typestring, nullablerequired
user_idstring, nullablerequired
colourstring, nullablerequired

Diary column colour.

photo_urlstring, nullablerequired
sortnumberrequired
bookablebooleanrequired
online_bookablebooleanrequired
is_activebooleanrequired
appointmentsarray of objectrequired
24 child fields
idstringrequired
customer_idstring, nullablerequired
guest_namestring, nullablerequired
guest_emailstring, nullablerequired
guest_phonestring, nullablerequired
service_idstring, nullablerequired
starts_atstringrequired

ISO instant the appointment starts.

ends_atstringrequired

ISO instant the appointment ends (what the customer was told).

statusstringrequired

'pending_payment' | 'confirmed' | 'checked_in' | 'completed' | 'cancelled' | 'no_show'.

payment_statusstringrequired
price_pencenumberrequired
deposit_pencenumberrequired
balance_pencenumberrequired
currencystringrequired
party_sizenumberrequired
childrennumberrequired

How many of the party are children (age 12 and under). 0 for a normal appointment.

high_chairsnumberrequired

High chairs the diner asked for, so the host can fetch them.

preferred_area_idstring · uuid, nullablerequired

The dining AREA the guest asked for at booking (Level-1 seating). Null for no-preference and every non-restaurant booking.

preferred_area_namestring, nullablerequired

Resolved name of preferred_area_id (e.g. "Window"), joined from restaurant_areas. Null when there is no preference.

sourcestringrequired
is_overridebooleanrequired

true when this was FORCE-BOOKED (a squeeze-in exempt from the double-booking guard).

checked_in_atstring, nullablerequired
completed_atstring, nullablerequired
cancelled_atstring, nullablerequired
holdsarray of objectrequired

Live pending reservations mid-checkout.

4 child fields
idstringrequired
starts_atstringrequired
ends_atstringrequired
expires_atstring, nullablerequired

When this pending reservation lapses.

time_offarray of objectrequired

Time-off / lunch, from both the time-off entity and manual blocks.

5 child fields
idstringrequired
kindstringrequired

'time_off' (an explicit time-off entry) or 'block' (a manual lunch/errand block).

starts_atstringrequired
ends_atstringrequired
reasonstring, nullablerequired
curl -G "https://www.membber.com/api/v1/bookings/diary" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  --data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066" \
  --data-urlencode "from_date=<from_date>" \
  --data-urlencode "to_date=<to_date>"
Response, 200
{
  "store_id": "6659c139-0000-4000-8000-d0c500000066",
  "timezone": "Europe/London",
  "from": "<from>",
  "to": "<to>",
  "units": [
    {
      "unit": {
        "id": "00000d1b-0000-4000-8000-d0c500000000",
        "display_name": "<display_name>",
        "kind": "<kind>",
        "unit_type": "<unit_type>",
        "user_id": "f73aee0f-0000-4000-8000-d0c5000000f7",
        "colour": "<colour>",
        "photo_url": "https://example.com/image.jpg",
        "sort": 1,
        "bookable": true,
        "online_bookable": true,
        "is_active": true
      },
      "appointments": [
        {
          "id": "00000d1b-0000-4000-8000-d0c500000000",
          "customer_id": "96607d1c-0000-4000-8000-d0c500000096",
          "guest_name": "<guest_name>",
          "guest_email": "alex@example.com",
          "guest_phone": "+44 7700 900123",
          "service_id": "993232e5-0000-4000-8000-d0c500000099",
          "starts_at": "<starts_at>",
          "ends_at": "<ends_at>",
          "status": "<status>",
          "payment_status": "<payment_status>",
          "price_pence": 1500,
          "deposit_pence": 1500,
          "balance_pence": 1500,
          "currency": "GBP",
          "party_size": 1,
          "children": 1,
          "high_chairs": 1,
          "preferred_area_id": "afa05c4f-0000-4000-8000-d0c5000000af",
          "preferred_area_name": "<preferred_area_name>",
          "source": "<source>",
          "is_override": true,
          "checked_in_at": "<checked_in_at>",
          "completed_at": "<completed_at>",
          "cancelled_at": "<cancelled_at>"
        }
      ],
      "holds": [
        {
          "id": "00000d1b-0000-4000-8000-d0c500000000",
          "starts_at": "<starts_at>",
          "ends_at": "<ends_at>",
          "expires_at": "<expires_at>"
        }
      ],
      "time_off": [
        {
          "id": "00000d1b-0000-4000-8000-d0c500000000",
          "kind": "<kind>",
          "starts_at": "<starts_at>",
          "ends_at": "<ends_at>",
          "reason": "Added at the front desk"
        }
      ]
    }
  ]
}

The store's live walk-in queue.

The merchant rail: every waiting + called walk-in for the AUTHENTICATED store, in join order, each waiting entry carrying its DERIVED position, honest wait, and the earliest-free chair the estimate would assign it (the default assign target). Store-wide and business-authenticated, the customer status read can only ever see one own entry. Business-auth + the paid can_use_bookings entitlement.

Parameters

store_idstring · uuidqueryrequired

The store whose queue to read. Must be the authenticated store.

Response, 200

store_idstringrequired
walkin_modestring, nullablerequired

'appointments_only' | 'walk_ins_only' | 'mixed', whether the store even takes walk-ins.

called_hold_minutesnumber, nullablerequired

The hold-after-call window, for the rail's countdown on called entries.

entriesarray of objectrequired

Every waiting + called entry in join order. Waiting entries carry a derived position + wait + suggested chair; called entries carry called_at.

17 child fields
entry_idstringrequired
store_idstringrequired
customer_idstring, nullablerequired
guest_namestring, nullablerequired
guest_phonestring, nullablerequired

Present on the merchant surface; omitted from the customer surface.

service_idstring, nullablerequired

The service the walk-in asked for, shapes the wait estimate and the assigned duration.

preferred_unit_idstring, nullablerequired

A chair/stylist the walk-in asked for, if any.

party_sizenumberrequired
statusstringrequired

'waiting' | 'called' | 'assigned' | 'completed' | 'left' | 'no_show' | 'converted_to_appointment'.

joined_atstringrequired

ISO instant they joined the queue (the join order that derives position).

called_atstring, nullablerequired

ISO instant they were called, if they have been.

quoted_wait_minnumber, nullablerequired

The wait we quoted AT JOIN, snapshotted, so a later dispute is answerable.

appointment_idstring, nullablerequired

Set once assigned, the booking the entry converted into.

queue_positionnumber, nullablerequired

DERIVED 1-based place in line. Null once called/assigned/left, a stored position is a second source of truth that drifts.

expected_wait_minnumber, nullablerequired

DERIVED minutes until a chair is expected free for this person, from the live blocks. Null when not waiting.

expected_startstring, nullablerequired

DERIVED ISO instant a chair is expected free for this person. Null when not waiting.

suggested_unit_idstring, nullablerequired

The earliest-free chair the estimate would hand this person, the rail's default assign target. Null when not waiting.

curl -G "https://www.membber.com/api/v1/bookings/queue" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  --data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066"
Response, 200
{
  "store_id": "6659c139-0000-4000-8000-d0c500000066",
  "walkin_mode": "<walkin_mode>",
  "called_hold_minutes": 1,
  "entries": [
    {
      "entry_id": "83353c08-0000-4000-8000-d0c500000083",
      "store_id": "6659c139-0000-4000-8000-d0c500000066",
      "customer_id": "96607d1c-0000-4000-8000-d0c500000096",
      "guest_name": "<guest_name>",
      "guest_phone": "+44 7700 900123",
      "service_id": "993232e5-0000-4000-8000-d0c500000099",
      "preferred_unit_id": "cb0a9bf8-0000-4000-8000-d0c5000000cb",
      "party_size": 1,
      "status": "<status>",
      "joined_at": "<joined_at>",
      "called_at": "<called_at>",
      "quoted_wait_min": 1,
      "appointment_id": "0d727dbb-0000-4000-8000-d0c50000000d",
      "queue_position": 1,
      "expected_wait_min": 1,
      "expected_start": "<expected_start>",
      "suggested_unit_id": "28cd789a-0000-4000-8000-d0c500000028"
    }
  ]
}

Seat a walk-in at a unit (books it).

Seats a walk-in at a chair/stylist/table starting now(), which BOOKS A REAL APPOINTMENT through the single booking authority, the queue never writes its own booking, so a walk-in and an online customer can never both take one chair. A lost race returns STALE_SLOT and the walk-in KEEPS THEIR PLACE (they are not dropped). Idempotent: a second assign returns the same appointment, never a double-book. With override: true the merchant force-seats a squeeze-in the authority would refuse. Both entry and unit must belong to the authenticated store. Business-auth + can_use_bookings. No money moves (deposits are Stage 6).

Request body

store_idstring · uuidrequired

The authenticated store the entry + unit belong to.

entry_idstring · uuidrequired

The walk-in to seat. Must belong to the store.

unit_idstring · uuidrequired

The chair/stylist/table to seat them at, starting now(). Must belong to the store.

duration_mininteger, nullableoptional

Override the assigned length. Defaults to the service duration (or 30 min).

overridebooleanoptional

FORCE-SEAT even where the availability authority would refuse (a squeeze-in). The merchant-only power, the block is exempt from the double-booking guard. Defaults to false.

Response, 200

entry_idstringrequired
appointment_idstringrequired

The booking the walk-in became, created through the ONE booking authority, source "walk_in".

assignedbooleanrequired

false when the entry was already assigned, an idempotent no-op returning the same appointment.

curl -X POST "https://www.membber.com/api/v1/bookings/queue/assign" \
  -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",
    "entry_id": "83353c08-0000-4000-8000-d0c500000083",
    "unit_id": "eeebf9b6-0000-4000-8000-d0c5000000ee"
  }'
Response, 200
{
  "entry_id": "83353c08-0000-4000-8000-d0c500000083",
  "appointment_id": "0d727dbb-0000-4000-8000-d0c50000000d",
  "assigned": true
}

Call the next (or a specific) walk-in.

Marks a WAITING walk-in as called and starts the hold-after-call countdown (they get "you're up", the shop holds their place for the policy window). "Call the next" is simply calling the first waiting entry the list returned. Single-winner and idempotent, a second call is a no-op returning the original called_at; an entry that is not waiting is refused. The entry must belong to the authenticated store. Business-auth + can_use_bookings.

Request body

store_idstring · uuidrequired

The authenticated store the entry belongs to.

entry_idstring · uuidrequired

The entry to call. "Call the next" is the first waiting entry from the list. Must belong to the store.

Response, 200

entry_idstringrequired
calledbooleanrequired

false when it was already called, an idempotent no-op.

hold_minutesnumberrequired

How long they are held before they lose their place.

called_atstring, nullablerequired

ISO instant they were called (the existing time on a no-op re-call).

curl -X POST "https://www.membber.com/api/v1/bookings/queue/call" \
  -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",
    "entry_id": "83353c08-0000-4000-8000-d0c500000083"
  }'
Response, 200
{
  "entry_id": "83353c08-0000-4000-8000-d0c500000083",
  "called": true,
  "hold_minutes": 1,
  "called_at": "<called_at>"
}

Remove a walk-in (left / no-show).

Marks a queue entry left or no_show, the merchant side of clearing the rail when a called walk-in does not appear or gives up. "left" and "no_show" are kept distinct for the record. Idempotent, removing an already-ended entry is a no-op. The entry must belong to the authenticated store. Business-auth + can_use_bookings. No fee (queue-side fees never exist in v1, no consent is captured at join).

Request body

store_idstring · uuidrequired

The authenticated store the entry belongs to.

entry_idstring · uuidrequired

The entry to remove. Must belong to the store.

statusenumrequired

Why it is leaving the queue: 'left' (they gave up / no-answer) or 'no_show' (called and did not appear). Distinct outcomes for the record.

leftno_show

Response, 200

entry_idstringrequired
statusstringrequired

The terminal status the entry now holds.

noopbooleanrequired

true when the entry had already ended, an idempotent no-op.

curl -X POST "https://www.membber.com/api/v1/bookings/queue/remove" \
  -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",
    "entry_id": "83353c08-0000-4000-8000-d0c500000083",
    "status": "left"
  }'
Response, 200
{
  "entry_id": "83353c08-0000-4000-8000-d0c500000083",
  "status": "<status>",
  "noop": true
}

A store's service periods.

Every service period (Lunch/Dinner/…) for the authenticated store. Disabled periods are excluded unless asked for.

Parameters

store_idstring · uuidqueryrequired
include_archivedbooleanqueryoptional

Include disabled periods. Defaults to active only.

Response, 200

periodsarray of objectrequired
7 child fields
idstringrequired
store_idstringrequired
namestringrequired
sortnumberrequired
weekobjectrequired

The week this period is served. Omit a day to close it. e.g. {"friday":{"open":"18:00","close":"22:00"}}.

7 child fields
sundayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

mondayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

tuesdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

wednesdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

thursdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

fridayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

saturdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

last_seating_offset_minnumberrequired
is_activebooleanrequired
curl -G "https://www.membber.com/api/v1/bookings/service-periods" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  --data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066"
Response, 200
{
  "periods": [
    {
      "id": "00000d1b-0000-4000-8000-d0c500000000",
      "store_id": "6659c139-0000-4000-8000-d0c500000066",
      "name": "Example name",
      "sort": 1,
      "week": {
        "sunday": {
          "open": "<open>",
          "close": "<close>"
        },
        "monday": {
          "open": "<open>",
          "close": "<close>"
        },
        "tuesday": {
          "open": "<open>",
          "close": "<close>"
        },
        "wednesday": {
          "open": "<open>",
          "close": "<close>"
        },
        "thursday": {
          "open": "<open>",
          "close": "<close>"
        },
        "friday": {
          "open": "<open>",
          "close": "<close>"
        },
        "saturday": {
          "open": "<open>",
          "close": "<close>"
        }
      },
      "last_seating_offset_min": 1,
      "is_active": true
    }
  ]
}

Create a service period.

Adds a named service period to the authenticated store. Send a `client_token` to make the create idempotent.

Request body

store_idstring · uuidrequired
client_tokenstringoptional

Caller-generated idempotency key, a retry with the same token returns the SAME period, never a duplicate.

namestringrequired

What the period is called, e.g. "Lunch" or "Dinner".

sortintegeroptional

Display order among the store's periods.

weekobjectoptional

The week this period is served. Omit a day to close it. e.g. {"friday":{"open":"18:00","close":"22:00"}}.

7 child fields
sundayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

mondayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

tuesdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

wednesdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

thursdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

fridayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

saturdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

last_seating_offset_minintegeroptional

Minutes before this period closes that the last table is seated. Overrides the store policy value for this period.

Response, 200

periodobjectrequired
7 child fields
idstringrequired
store_idstringrequired
namestringrequired
sortnumberrequired
weekobjectrequired

The week this period is served. Omit a day to close it. e.g. {"friday":{"open":"18:00","close":"22:00"}}.

7 child fields
sundayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

mondayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

tuesdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

wednesdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

thursdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

fridayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

saturdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

last_seating_offset_minnumberrequired
is_activebooleanrequired
curl -X POST "https://www.membber.com/api/v1/bookings/service-periods" \
  -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",
    "name": "Example name"
  }'
Response, 200
{
  "period": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "name": "Example name",
    "sort": 1,
    "week": {
      "sunday": {
        "open": "<open>",
        "close": "<close>"
      },
      "monday": {
        "open": "<open>",
        "close": "<close>"
      },
      "tuesday": {
        "open": "<open>",
        "close": "<close>"
      },
      "wednesday": {
        "open": "<open>",
        "close": "<close>"
      },
      "thursday": {
        "open": "<open>",
        "close": "<close>"
      },
      "friday": {
        "open": "<open>",
        "close": "<close>"
      },
      "saturday": {
        "open": "<open>",
        "close": "<close>"
      }
    },
    "last_seating_offset_min": 1,
    "is_active": true
  }
}

Delete a service period.

Hard-deletes a service period (config only, no appointment references it). Idempotent: deleting one already gone is a no-op. To keep it but stop serving it, PATCH is_active=false instead.

Parameters

periodIdstringpathrequired
store_idstring · uuidqueryrequired

Response, 200

period_idstringrequired
removedbooleanrequired

false when there was nothing to remove (idempotent).

curl -X DELETE "https://www.membber.com/api/v1/bookings/service-periods/19dd12bc-0000-4000-8000-d0c500000019?store_id=6659c139-0000-4000-8000-d0c500000066" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678"
Response, 200
{
  "period_id": "21c59859-0000-4000-8000-d0c500000021",
  "removed": true
}

Update a service period.

Partial update of a service period the authenticated store owns. A window change shapes FUTURE availability only.

Parameters

periodIdstringpathrequired

Request body

store_idstring · uuidrequired
namestringoptional

What the period is called, e.g. "Lunch" or "Dinner".

sortintegeroptional

Display order among the store's periods.

weekobjectoptional

The week this period is served. Omit a day to close it. e.g. {"friday":{"open":"18:00","close":"22:00"}}.

7 child fields
sundayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

mondayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

tuesdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

wednesdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

thursdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

fridayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

saturdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

last_seating_offset_minintegeroptional

Minutes before this period closes that the last table is seated. Overrides the store policy value for this period.

is_activebooleanoptional

Set false to disable this period without deleting it; true to re-enable.

Response, 200

periodobjectrequired
7 child fields
idstringrequired
store_idstringrequired
namestringrequired
sortnumberrequired
weekobjectrequired

The week this period is served. Omit a day to close it. e.g. {"friday":{"open":"18:00","close":"22:00"}}.

7 child fields
sundayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

mondayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

tuesdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

wednesdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

thursdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

fridayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

saturdayobjectoptional

One serving window for one day.

2 child fields
openstringrequired

When this period opens on this day (24h HH:MM).

closestringrequired

When this period closes on this day (must be after open).

last_seating_offset_minnumberrequired
is_activebooleanrequired
curl -X PATCH "https://www.membber.com/api/v1/bookings/service-periods/19dd12bc-0000-4000-8000-d0c500000019" \
  -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
{
  "period": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "name": "Example name",
    "sort": 1,
    "week": {
      "sunday": {
        "open": "<open>",
        "close": "<close>"
      },
      "monday": {
        "open": "<open>",
        "close": "<close>"
      },
      "tuesday": {
        "open": "<open>",
        "close": "<close>"
      },
      "wednesday": {
        "open": "<open>",
        "close": "<close>"
      },
      "thursday": {
        "open": "<open>",
        "close": "<close>"
      },
      "friday": {
        "open": "<open>",
        "close": "<close>"
      },
      "saturday": {
        "open": "<open>",
        "close": "<close>"
      }
    },
    "last_seating_offset_min": 1,
    "is_active": true
  }
}

A store's bookable services.

Every service the store offers, each with its variants and add-ons. Scoped to the authenticated store; archived services are excluded unless asked for.

Parameters

store_idstring · uuidqueryrequired

The store whose catalogue to read (must be the authenticated store).

include_archivedbooleanqueryoptional

Include archived services. Defaults to active only.

Response, 200

servicesarray of objectrequired
22 child fields
idstringrequired
store_idstringrequired
categorystring, nullablerequired
namestringrequired
descriptionstring, nullablerequired
imagesarray of stringrequired

Image URLs the merchant uploaded for this service.

duration_minnumberrequired
price_pencenumberrequired
currencystringrequired
price_typeenumrequired
fixedfromper_person
party_minnumberrequired
party_maxnumberrequired
buffer_before_minnumberrequired
buffer_after_minnumberrequired
processing_minnumberrequired
location_typeenumrequired
on_premisesonlinecustomer_site
rebook_interval_daysnumber, nullablerequired
online_visiblebooleanrequired
sortnumberrequired
is_activebooleanrequired
variantsarray of objectrequired

Pricing/duration variants for this service.

6 child fields
idstringrequired
namestringrequired
duration_minnumber, nullablerequired
price_pencenumber, nullablerequired
sortnumberrequired
is_activebooleanrequired
addonsarray of objectrequired

Optional paid add-ons that extend this service.

6 child fields
idstringrequired
namestringrequired
extra_minnumberrequired
extra_pencenumberrequired
sortnumberrequired
is_activebooleanrequired
curl -G "https://www.membber.com/api/v1/bookings/services" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  --data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066"
Response, 200
{
  "services": [
    {
      "id": "00000d1b-0000-4000-8000-d0c500000000",
      "store_id": "6659c139-0000-4000-8000-d0c500000066",
      "category": "<category>",
      "name": "Example name",
      "description": "Added at the front desk",
      "images": [
        "<image>"
      ],
      "duration_min": 1,
      "price_pence": 1500,
      "currency": "GBP",
      "price_type": "fixed",
      "party_min": 1,
      "party_max": 1,
      "buffer_before_min": 1,
      "buffer_after_min": 1,
      "processing_min": 1,
      "location_type": "on_premises",
      "rebook_interval_days": 1,
      "online_visible": true,
      "sort": 1,
      "is_active": true,
      "variants": [
        {
          "id": "00000d1b-0000-4000-8000-d0c500000000",
          "name": "Example name",
          "duration_min": 1,
          "price_pence": 1500,
          "sort": 1,
          "is_active": true
        }
      ],
      "addons": [
        {
          "id": "00000d1b-0000-4000-8000-d0c500000000",
          "name": "Example name",
          "extra_min": 1,
          "extra_pence": 1500,
          "sort": 1,
          "is_active": true
        }
      ]
    }
  ]
}

Create a bookable service.

Adds a service to the authenticated store. Send a `client_token` to make the create idempotent, a retry with the same token returns the same service rather than a duplicate.

Request body

store_idstring · uuidrequired
client_tokenstringoptional

Caller-generated idempotency key. Send the same token on a retry to get the SAME service back instead of a duplicate.

categorystring, nullableoptional
namestringrequired

What the customer books.

descriptionstring, nullableoptional
imagesarray of string · urioptional

Uploaded image URLs.

duration_minintegerrequired

Appointment length in minutes.

price_penceintegeroptional

Price in the smallest currency unit.

currencystringoptional
price_typeenumoptional

'fixed' | 'from' | 'per_person'.

fixedfromper_person
party_minintegeroptional
party_maxintegeroptional
deposit_policyobjectoptional

Deposit policy JSON. WRITABLE but INERT until the money stage, no charge is wired from it here.

buffer_before_minintegeroptional

Prep time the unit is occupied before.

buffer_after_minintegeroptional

Clean-up time the unit is occupied after.

processing_minintegeroptional
location_typeenumoptional
on_premisesonlinecustomer_site
rebook_interval_daysinteger, nullableoptional
online_visiblebooleanoptional

Whether customers can see and book this online.

sortintegeroptional

Response, 200

serviceobjectrequired
22 child fields
idstringrequired
store_idstringrequired
categorystring, nullablerequired
namestringrequired
descriptionstring, nullablerequired
imagesarray of stringrequired

Image URLs the merchant uploaded for this service.

duration_minnumberrequired
price_pencenumberrequired
currencystringrequired
price_typeenumrequired
fixedfromper_person
party_minnumberrequired
party_maxnumberrequired
buffer_before_minnumberrequired
buffer_after_minnumberrequired
processing_minnumberrequired
location_typeenumrequired
on_premisesonlinecustomer_site
rebook_interval_daysnumber, nullablerequired
online_visiblebooleanrequired
sortnumberrequired
is_activebooleanrequired
variantsarray of objectrequired

Pricing/duration variants for this service.

6 child fields
idstringrequired
namestringrequired
duration_minnumber, nullablerequired
price_pencenumber, nullablerequired
sortnumberrequired
is_activebooleanrequired
addonsarray of objectrequired

Optional paid add-ons that extend this service.

6 child fields
idstringrequired
namestringrequired
extra_minnumberrequired
extra_pencenumberrequired
sortnumberrequired
is_activebooleanrequired
curl -X POST "https://www.membber.com/api/v1/bookings/services" \
  -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",
    "name": "Example name",
    "duration_min": 1
  }'
Response, 200
{
  "service": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "category": "<category>",
    "name": "Example name",
    "description": "Added at the front desk",
    "images": [
      "<image>"
    ],
    "duration_min": 1,
    "price_pence": 1500,
    "currency": "GBP",
    "price_type": "fixed",
    "party_min": 1,
    "party_max": 1,
    "buffer_before_min": 1,
    "buffer_after_min": 1,
    "processing_min": 1,
    "location_type": "on_premises",
    "rebook_interval_days": 1,
    "online_visible": true,
    "sort": 1,
    "is_active": true,
    "variants": [
      {
        "id": "00000d1b-0000-4000-8000-d0c500000000",
        "name": "Example name",
        "duration_min": 1,
        "price_pence": 1500,
        "sort": 1,
        "is_active": true
      }
    ],
    "addons": [
      {
        "id": "00000d1b-0000-4000-8000-d0c500000000",
        "name": "Example name",
        "extra_min": 1,
        "extra_pence": 1500,
        "sort": 1,
        "is_active": true
      }
    ]
  }
}

Update a service.

Partial update of a service the authenticated store owns. A price or duration change shapes FUTURE availability only, a booked appointment keeps the price and policy it was snapshotted with.

Parameters

serviceIdstringpathrequired

Request body

store_idstring · uuidrequired
categorystring, nullableoptional
namestringoptional

What the customer books.

descriptionstring, nullableoptional
imagesarray of string · urioptional

Uploaded image URLs.

duration_minintegeroptional

Appointment length in minutes.

price_penceintegeroptional

Price in the smallest currency unit.

currencystringoptional
price_typeenumoptional

'fixed' | 'from' | 'per_person'.

fixedfromper_person
party_minintegeroptional
party_maxintegeroptional
deposit_policyobjectoptional

Deposit policy JSON. WRITABLE but INERT until the money stage, no charge is wired from it here.

buffer_before_minintegeroptional

Prep time the unit is occupied before.

buffer_after_minintegeroptional

Clean-up time the unit is occupied after.

processing_minintegeroptional
location_typeenumoptional
on_premisesonlinecustomer_site
rebook_interval_daysinteger, nullableoptional
online_visiblebooleanoptional

Whether customers can see and book this online.

sortintegeroptional
is_activebooleanoptional

Set true to RESTORE an archived service (the inverse of /archive); false archives it. Archiving never deletes, existing appointments keep their snapshot either way.

Response, 200

serviceobjectrequired
22 child fields
idstringrequired
store_idstringrequired
categorystring, nullablerequired
namestringrequired
descriptionstring, nullablerequired
imagesarray of stringrequired

Image URLs the merchant uploaded for this service.

duration_minnumberrequired
price_pencenumberrequired
currencystringrequired
price_typeenumrequired
fixedfromper_person
party_minnumberrequired
party_maxnumberrequired
buffer_before_minnumberrequired
buffer_after_minnumberrequired
processing_minnumberrequired
location_typeenumrequired
on_premisesonlinecustomer_site
rebook_interval_daysnumber, nullablerequired
online_visiblebooleanrequired
sortnumberrequired
is_activebooleanrequired
variantsarray of objectrequired

Pricing/duration variants for this service.

6 child fields
idstringrequired
namestringrequired
duration_minnumber, nullablerequired
price_pencenumber, nullablerequired
sortnumberrequired
is_activebooleanrequired
addonsarray of objectrequired

Optional paid add-ons that extend this service.

6 child fields
idstringrequired
namestringrequired
extra_minnumberrequired
extra_pencenumberrequired
sortnumberrequired
is_activebooleanrequired
curl -X PATCH "https://www.membber.com/api/v1/bookings/services/f46cf6b0-0000-4000-8000-d0c5000000f4" \
  -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
{
  "service": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "category": "<category>",
    "name": "Example name",
    "description": "Added at the front desk",
    "images": [
      "<image>"
    ],
    "duration_min": 1,
    "price_pence": 1500,
    "currency": "GBP",
    "price_type": "fixed",
    "party_min": 1,
    "party_max": 1,
    "buffer_before_min": 1,
    "buffer_after_min": 1,
    "processing_min": 1,
    "location_type": "on_premises",
    "rebook_interval_days": 1,
    "online_visible": true,
    "sort": 1,
    "is_active": true,
    "variants": [
      {
        "id": "00000d1b-0000-4000-8000-d0c500000000",
        "name": "Example name",
        "duration_min": 1,
        "price_pence": 1500,
        "sort": 1,
        "is_active": true
      }
    ],
    "addons": [
      {
        "id": "00000d1b-0000-4000-8000-d0c500000000",
        "name": "Example name",
        "extra_min": 1,
        "extra_pence": 1500,
        "sort": 1,
        "is_active": true
      }
    ]
  }
}

Add a service add-on.

Adds an add-on to a service the authenticated store owns. Idempotent per `client_token`.

Parameters

serviceIdstringpathrequired

Request body

store_idstring · uuidrequired
client_tokenstringoptional

Caller-generated idempotency key. Send the same token on a retry to get the SAME service back instead of a duplicate.

namestringrequired
extra_minintegeroptional

Extra minutes this add-on adds to the appointment.

extra_penceintegeroptional

Extra charge in the smallest currency unit (INERT until the money stage).

sortintegeroptional

Response, 200

addonobjectrequired
6 child fields
idstringrequired
namestringrequired
extra_minnumberrequired
extra_pencenumberrequired
sortnumberrequired
is_activebooleanrequired
curl -X POST "https://www.membber.com/api/v1/bookings/services/f46cf6b0-0000-4000-8000-d0c5000000f4/addons" \
  -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",
    "name": "Example name"
  }'
Response, 200
{
  "addon": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "name": "Example name",
    "extra_min": 1,
    "extra_pence": 1500,
    "sort": 1,
    "is_active": true
  }
}

Update or archive a service add-on.

Partial update of an add-on belonging to a service the authenticated store owns.

Parameters

serviceIdstringpathrequired
addonIdstringpathrequired

Request body

store_idstring · uuidrequired
namestringoptional
extra_minintegeroptional
extra_penceintegeroptional
sortintegeroptional
is_activebooleanoptional

Set false to archive this add-on.

Response, 200

addonobjectrequired
6 child fields
idstringrequired
namestringrequired
extra_minnumberrequired
extra_pencenumberrequired
sortnumberrequired
is_activebooleanrequired
curl -X PATCH "https://www.membber.com/api/v1/bookings/services/f46cf6b0-0000-4000-8000-d0c5000000f4/addons/bb965b7b-0000-4000-8000-d0c5000000bb" \
  -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
{
  "addon": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "name": "Example name",
    "extra_min": 1,
    "extra_pence": 1500,
    "sort": 1,
    "is_active": true
  }
}

Archive a service (honouring existing bookings).

Sets the service inactive so it stops appearing in availability, but NEVER deletes it, every existing appointment keeps its snapshotted price/duration and its link to the service. Idempotent.

Parameters

serviceIdstringpathrequired

Request body

store_idstring · uuidrequired

Response, 200

service_idstringrequired
archivedbooleanrequired

true once inactive (idempotent, archiving twice is a no-op).

curl -X POST "https://www.membber.com/api/v1/bookings/services/f46cf6b0-0000-4000-8000-d0c5000000f4/archive" \
  -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
{
  "service_id": "993232e5-0000-4000-8000-d0c500000099",
  "archived": true
}

Add a service variant.

Adds a variant to a service the authenticated store owns. Idempotent per `client_token`.

Parameters

serviceIdstringpathrequired

Request body

store_idstring · uuidrequired
client_tokenstringoptional

Caller-generated idempotency key. Send the same token on a retry to get the SAME service back instead of a duplicate.

namestringrequired
duration_mininteger, nullableoptional

Overrides the service duration for this variant.

price_penceinteger, nullableoptional
sortintegeroptional

Response, 200

variantobjectrequired
6 child fields
idstringrequired
namestringrequired
duration_minnumber, nullablerequired
price_pencenumber, nullablerequired
sortnumberrequired
is_activebooleanrequired
curl -X POST "https://www.membber.com/api/v1/bookings/services/f46cf6b0-0000-4000-8000-d0c5000000f4/variants" \
  -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",
    "name": "Example name"
  }'
Response, 200
{
  "variant": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "name": "Example name",
    "duration_min": 1,
    "price_pence": 1500,
    "sort": 1,
    "is_active": true
  }
}

Update or archive a service variant.

Partial update of a variant belonging to a service the authenticated store owns.

Parameters

serviceIdstringpathrequired
variantIdstringpathrequired

Request body

store_idstring · uuidrequired
namestringoptional
duration_mininteger, nullableoptional
price_penceinteger, nullableoptional
sortintegeroptional
is_activebooleanoptional

Set false to archive this variant.

Response, 200

variantobjectrequired
6 child fields
idstringrequired
namestringrequired
duration_minnumber, nullablerequired
price_pencenumber, nullablerequired
sortnumberrequired
is_activebooleanrequired
curl -X PATCH "https://www.membber.com/api/v1/bookings/services/f46cf6b0-0000-4000-8000-d0c5000000f4/variants/fb1b0c80-0000-4000-8000-d0c5000000fb" \
  -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
{
  "variant": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "name": "Example name",
    "duration_min": 1,
    "price_pence": 1500,
    "sort": 1,
    "is_active": true
  }
}

Set the store timezone.

Writes `stores.timezone` after validating it is a real IANA timezone. This is the anchor every day boundary, hour label and rollup in the bookings vertical reads, so an invalid value is refused rather than silently skewing a diary. Idempotent.

Request body

store_idstring · uuidrequired
timezonestringrequired

An IANA timezone name, e.g. "Europe/London". Validated against the runtime before it is written.

Response, 200

store_idstringrequired
timezonestringrequired
curl -X PUT "https://www.membber.com/api/v1/bookings/store-timezone" \
  -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",
    "timezone": "Europe/London"
  }'
Response, 200
{
  "store_id": "6659c139-0000-4000-8000-d0c500000066",
  "timezone": "Europe/London"
}

What a store offers for online booking.

The customer-facing view of a store's bookable services and people, the read the Book flow starts from, and the only way to obtain the `service_id` that availability requires. Public, because showing what a shop offers must not require an account. Returns only what is genuinely offered online: archived and staff-only services are absent, and so is anyone who is not taking online bookings.

auth none, publicop getBookingStorefrontrate limitederrors

Parameters

store_idstring · uuidqueryrequired

The store whose bookable offering to read.

Response, 200

servicesarray of objectrequired

Bookable online, in the merchant's own order.

14 child fields
idstringrequired
namestringrequired
descriptionstring, nullablerequired
imagesarray of stringrequired

The merchant's own photos. Empty is a real state, the client draws its designed blank, never a stock photo.

duration_minnumberrequired

What the customer is told the appointment lasts. Buffers are NEVER exposed, they are the shop's business, not the customer's.

price_pencenumberrequired
currencystringrequired
price_typeenumrequired

'from' when performers price it differently, the exact figure locks at the person step.

fixedfromper_person
categorystring, nullablerequired
unit_idsarray of stringrequired
sortnumberrequired
party_minnumberrequired

Smallest party this service takes. 1 for a normal appointment.

party_maxnumberrequired

Largest party bookable online. Above it, the client offers "message the restaurant".

seat_choice_levelnumberrequired

Who picks the table for a tables store: 0 the house assigns, 1 the guest picks, 2 reserved. From booking_policies.table_choice_level (store-level).

peoplearray of objectrequired

Who can be booked, in the merchant's own order, the same order the diary columns use.

5 child fields
idstringrequired

The bookable unit id, what `availability` and the booking call take as `unit_id`.

display_namestringrequired
photo_urlstring, nullablerequired
sortnumberrequired
overridesarray of objectrequired

Per-person price/duration for a service, where it differs from the service default. Resolved so the confirm card can show the TRUE figure for this person.

3 child fields
service_idstringrequired
duration_minnumber, nullablerequired
price_pencenumber, nullablerequired
areasarray of objectrequired

The venue's dining areas, in the merchant's order. Empty unless it is a tables store with areas.

4 child fields
idstringrequired
namestringrequired

The area name the diner picks, e.g. "Window", "Main room", "Bar".

sortnumberrequired
descriptionstring, nullablerequired

Optional one line, e.g. "Heated and covered".

acceptingbooleanrequired

False when the store is set up but PAUSED. The client shows one calm line rather than an empty slot grid pretending to be availability.

curl -G "https://www.membber.com/api/v1/bookings/storefront" \
  --data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066"
Response, 200
{
  "services": [
    {
      "id": "00000d1b-0000-4000-8000-d0c500000000",
      "name": "Example name",
      "description": "Added at the front desk",
      "images": [
        "<image>"
      ],
      "duration_min": 1,
      "price_pence": 1500,
      "currency": "GBP",
      "price_type": "fixed",
      "category": "<category>",
      "unit_ids": [
        "eeebf9b6-0000-4000-8000-d0c5000000ee"
      ],
      "sort": 1,
      "party_min": 1,
      "party_max": 1,
      "seat_choice_level": 1
    }
  ],
  "people": [
    {
      "id": "00000d1b-0000-4000-8000-d0c500000000",
      "display_name": "<display_name>",
      "photo_url": "https://example.com/image.jpg",
      "sort": 1,
      "overrides": [
        {
          "service_id": "993232e5-0000-4000-8000-d0c500000099",
          "duration_min": 1,
          "price_pence": 1500
        }
      ]
    }
  ],
  "areas": [
    {
      "id": "00000d1b-0000-4000-8000-d0c500000000",
      "name": "Example name",
      "sort": 1,
      "description": "Added at the front desk"
    }
  ],
  "accepting": true
}

A store's bookable units.

Every bookable unit for the authenticated store, each carrying which services it offers. Archived units excluded unless asked for.

Parameters

store_idstring · uuidqueryrequired
include_archivedbooleanqueryoptional

Response, 200

unitsarray of objectrequired
14 child fields
idstringrequired
store_idstringrequired
kindenumrequired
personspaceasset
unit_typestring, nullablerequired

Free-text sub-type (e.g. "chair", "room").

user_idstring, nullablerequired

The staff member this unit represents, when kind = person.

display_namestringrequired
biostring, nullablerequired
photo_urlstring, nullablerequired
colourstring, nullablerequired

Diary column colour.

bookablebooleanrequired

Whether the unit can hold appointments at all.

online_bookablebooleanrequired

Whether customers can book it online (vs staff-only).

sortnumberrequired
is_activebooleanrequired
servicesarray of objectrequired

Which services this unit offers, with any per-unit overrides.

3 child fields
service_idstringrequired
duration_override_minnumber, nullablerequired
price_override_pencenumber, nullablerequired
curl -G "https://www.membber.com/api/v1/bookings/units" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  --data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066"
Response, 200
{
  "units": [
    {
      "id": "00000d1b-0000-4000-8000-d0c500000000",
      "store_id": "6659c139-0000-4000-8000-d0c500000066",
      "kind": "person",
      "unit_type": "<unit_type>",
      "user_id": "f73aee0f-0000-4000-8000-d0c5000000f7",
      "display_name": "<display_name>",
      "bio": "<bio>",
      "photo_url": "https://example.com/image.jpg",
      "colour": "<colour>",
      "bookable": true,
      "online_bookable": true,
      "sort": 1,
      "is_active": true,
      "services": [
        {
          "service_id": "993232e5-0000-4000-8000-d0c500000099",
          "duration_override_min": 1,
          "price_override_pence": 1500
        }
      ]
    }
  ]
}

Create a bookable unit.

Adds a person / space / asset to the authenticated store. Idempotent per `client_token`.

Request body

store_idstring · uuidrequired
client_tokenstringoptional

Caller-generated idempotency key, a retry with the same token returns the SAME unit, never a duplicate.

kindenumoptional

'person' | 'space' | 'asset'. Defaults to 'person'.

personspaceasset
unit_typestring, nullableoptional
user_idstring · uuid, nullableoptional

Only permitted when kind = person (the DB enforces this).

display_namestringrequired

What the diary column is labelled.

biostring, nullableoptional
photo_urlstring · uri, nullableoptional
colourstring, nullableoptional
bookablebooleanoptional
online_bookablebooleanoptional
sortintegeroptional

Response, 200

unitobjectrequired
14 child fields
idstringrequired
store_idstringrequired
kindenumrequired
personspaceasset
unit_typestring, nullablerequired

Free-text sub-type (e.g. "chair", "room").

user_idstring, nullablerequired

The staff member this unit represents, when kind = person.

display_namestringrequired
biostring, nullablerequired
photo_urlstring, nullablerequired
colourstring, nullablerequired

Diary column colour.

bookablebooleanrequired

Whether the unit can hold appointments at all.

online_bookablebooleanrequired

Whether customers can book it online (vs staff-only).

sortnumberrequired
is_activebooleanrequired
servicesarray of objectrequired

Which services this unit offers, with any per-unit overrides.

3 child fields
service_idstringrequired
duration_override_minnumber, nullablerequired
price_override_pencenumber, nullablerequired
curl -X POST "https://www.membber.com/api/v1/bookings/units" \
  -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",
    "display_name": "<display_name>"
  }'
Response, 200
{
  "unit": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "kind": "person",
    "unit_type": "<unit_type>",
    "user_id": "f73aee0f-0000-4000-8000-d0c5000000f7",
    "display_name": "<display_name>",
    "bio": "<bio>",
    "photo_url": "https://example.com/image.jpg",
    "colour": "<colour>",
    "bookable": true,
    "online_bookable": true,
    "sort": 1,
    "is_active": true,
    "services": [
      {
        "service_id": "993232e5-0000-4000-8000-d0c500000099",
        "duration_override_min": 1,
        "price_override_pence": 1500
      }
    ]
  }
}

Update or archive a bookable unit.

Partial update of a unit the authenticated store owns. Archiving (is_active=false) keeps existing appointments intact.

Parameters

unitIdstringpathrequired

Request body

store_idstring · uuidrequired
kindenumoptional

'person' | 'space' | 'asset'. Defaults to 'person'.

personspaceasset
unit_typestring, nullableoptional
user_idstring · uuid, nullableoptional

Only permitted when kind = person (the DB enforces this).

display_namestringoptional

What the diary column is labelled.

biostring, nullableoptional
photo_urlstring · uri, nullableoptional
colourstring, nullableoptional
bookablebooleanoptional
online_bookablebooleanoptional
sortintegeroptional
is_activebooleanoptional

Set false to archive the unit (existing appointments are honoured).

Response, 200

unitobjectrequired
14 child fields
idstringrequired
store_idstringrequired
kindenumrequired
personspaceasset
unit_typestring, nullablerequired

Free-text sub-type (e.g. "chair", "room").

user_idstring, nullablerequired

The staff member this unit represents, when kind = person.

display_namestringrequired
biostring, nullablerequired
photo_urlstring, nullablerequired
colourstring, nullablerequired

Diary column colour.

bookablebooleanrequired

Whether the unit can hold appointments at all.

online_bookablebooleanrequired

Whether customers can book it online (vs staff-only).

sortnumberrequired
is_activebooleanrequired
servicesarray of objectrequired

Which services this unit offers, with any per-unit overrides.

3 child fields
service_idstringrequired
duration_override_minnumber, nullablerequired
price_override_pencenumber, nullablerequired
curl -X PATCH "https://www.membber.com/api/v1/bookings/units/cde691bf-0000-4000-8000-d0c5000000cd" \
  -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
{
  "unit": {
    "id": "00000d1b-0000-4000-8000-d0c500000000",
    "store_id": "6659c139-0000-4000-8000-d0c500000066",
    "kind": "person",
    "unit_type": "<unit_type>",
    "user_id": "f73aee0f-0000-4000-8000-d0c5000000f7",
    "display_name": "<display_name>",
    "bio": "<bio>",
    "photo_url": "https://example.com/image.jpg",
    "colour": "<colour>",
    "bookable": true,
    "online_bookable": true,
    "sort": 1,
    "is_active": true,
    "services": [
      {
        "service_id": "993232e5-0000-4000-8000-d0c500000099",
        "duration_override_min": 1,
        "price_override_pence": 1500
      }
    ]
  }
}

Map a service onto a unit.

Records that a unit offers a service (with optional per-unit duration/price overrides). Upsert on the (unit, service) pair, so it is idempotent, re-sending it converges rather than duplicating. Both the unit and the service must belong to the authenticated store.

Parameters

unitIdstringpathrequired

Request body

store_idstring · uuidrequired
service_idstring · uuidrequired

The service this unit should offer (must belong to the same store).

duration_override_mininteger, nullableoptional

Per-unit duration override.

price_override_penceinteger, nullableoptional

Per-unit price override.

Response, 200

unit_idstringrequired
service_idstringrequired
curl -X POST "https://www.membber.com/api/v1/bookings/units/cde691bf-0000-4000-8000-d0c5000000cd/services" \
  -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",
    "service_id": "993232e5-0000-4000-8000-d0c500000099"
  }'
Response, 200
{
  "unit_id": "eeebf9b6-0000-4000-8000-d0c5000000ee",
  "service_id": "993232e5-0000-4000-8000-d0c500000099"
}

Unmap a service from a unit.

Removes the (unit, service) mapping. Idempotent, removing one that is already gone is a no-op.

Parameters

unitIdstringpathrequired
serviceIdstringpathrequired
store_idstring · uuidqueryrequired

Response, 200

unit_idstringrequired
service_idstringrequired
removedbooleanrequired

false when there was nothing to remove (idempotent).

curl -X DELETE "https://www.membber.com/api/v1/bookings/units/cde691bf-0000-4000-8000-d0c5000000cd/services/f46cf6b0-0000-4000-8000-d0c5000000f4?store_id=6659c139-0000-4000-8000-d0c500000066" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  -H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678"
Response, 200
{
  "unit_id": "eeebf9b6-0000-4000-8000-d0c5000000ee",
  "service_id": "993232e5-0000-4000-8000-d0c500000099",
  "removed": true
}

A unit's working pattern.

The working intervals for a unit the authenticated store owns. Multiple rows for one weekday ARE the intervals; the gaps ARE the breaks.

auth merchant:readop listUnitWorkingPatternsrate limitederrors

Parameters

unitIdstringpathrequired
store_idstring · uuidqueryrequired

Response, 200

unit_idstringrequired
patternsarray of objectrequired
7 child fields
weekdayintegerrequired

0 = Sunday … 6 = Saturday.

start_minuteintegerrequired

Minutes past midnight the interval starts.

end_minuteintegerrequired

Minutes past midnight the interval ends (must be after start).

spans_midnightbooleanoptional

True for an interval that runs past midnight.

effective_fromstring, nullableoptional

YYYY-MM-DD the interval starts applying (null = always).

effective_tostring, nullableoptional

YYYY-MM-DD the interval stops applying (null = open-ended).

idstringrequired
curl -G "https://www.membber.com/api/v1/bookings/units/cde691bf-0000-4000-8000-d0c5000000cd/working-patterns" \
  -H "Authorization: Bearer $MEMBBER_TOKEN" \
  --data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066"
Response, 200
{
  "unit_id": "eeebf9b6-0000-4000-8000-d0c5000000ee",
  "patterns": [
    {
      "weekday": 0,
      "start_minute": 0,
      "end_minute": 1,
      "spans_midnight": true,
      "effective_from": "<effective_from>",
      "effective_to": "<effective_to>",
      "id": "00000d1b-0000-4000-8000-d0c500000000"
    }
  ]
}

Replace a unit's working pattern.

Swaps the unit's ENTIRE working pattern for the set you send, atomically (the old rows and the new ones never coexist, and a half-applied pattern is impossible). Idempotent, replacing with the same set converges. The unit must belong to the authenticated store.

Parameters

unitIdstringpathrequired

Request body

store_idstring · uuidrequired
patternsarray of objectrequired

The COMPLETE new set of intervals for this unit. Send an empty array to clear the pattern.

6 child fields
weekdayintegerrequired

0 = Sunday … 6 = Saturday.

start_minuteintegerrequired

Minutes past midnight the interval starts.

end_minuteintegerrequired

Minutes past midnight the interval ends (must be after start).

spans_midnightbooleanoptional

True for an interval that runs past midnight.

effective_fromstring, nullableoptional

YYYY-MM-DD the interval starts applying (null = always).

effective_tostring, nullableoptional

YYYY-MM-DD the interval stops applying (null = open-ended).

Response, 200

unit_idstringrequired
patternsarray of objectrequired
7 child fields
weekdayintegerrequired

0 = Sunday … 6 = Saturday.

start_minuteintegerrequired

Minutes past midnight the interval starts.

end_minuteintegerrequired

Minutes past midnight the interval ends (must be after start).

spans_midnightbooleanoptional

True for an interval that runs past midnight.

effective_fromstring, nullableoptional

YYYY-MM-DD the interval starts applying (null = always).

effective_tostring, nullableoptional

YYYY-MM-DD the interval stops applying (null = open-ended).

idstringrequired
curl -X PUT "https://www.membber.com/api/v1/bookings/units/cde691bf-0000-4000-8000-d0c5000000cd/working-patterns" \
  -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",
    "patterns": [
      {
        "weekday": 0,
        "start_minute": 0,
        "end_minute": 1
      }
    ]
  }'
Response, 200
{
  "unit_id": "eeebf9b6-0000-4000-8000-d0c5000000ee",
  "patterns": [
    {
      "weekday": 0,
      "start_minute": 0,
      "end_minute": 1,
      "spans_midnight": true,
      "effective_from": "<effective_from>",
      "effective_to": "<effective_to>",
      "id": "00000d1b-0000-4000-8000-d0c500000000"
    }
  ]
}
WhatsApp
Book a Call
Start Free