5 operations. Every schema and example on this page is generated from the platform contract.
Read-only cart promo preview using the SAME validator checkout uses. Enumeration-safe: invalid / expired / used-up codes all collapse to one generic "can't be used" message; only min_spend and email_required stay specific. With basket lines it returns a server-computed discount + per-line strike (display == charge).
The promo code entered in the cart (absent/null/empty/oversized collapses to the generic message).
Current basket subtotal in pence.
Optional basket lines → a server-computed estimate + per-line strike for item-scope codes.
min_spend | email_required (the only non-collapsed reasons).
Shopper-facing message (generic "can't be used" collapses all enumeration-sensitive failures).
curl -X POST "https://www.membber.com/api/v1/checkout/promo/preview" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
-H "Content-Type: application/json" \
-d '{
"subtotal_pence": 1500
}'import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.POST("/api/v1/checkout/promo/preview", {
body: {
subtotal_pence: 1500
},
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.previewPromoCode(
body: .json(.init(
subtotalPence: 1500
))
).ok.body.json
print(response){
"valid": true,
"reason": "Added at the front desk",
"message": "Added at the front desk",
"discount_type": "<discount_type>",
"discount_value": 1,
"description": "Added at the front desk",
"stackable_with_voucher": true,
"min_spend_pence": 1500,
"estimated_discount_pence": 1500,
"applies_to": "<applies_to>",
"affected_item_id": "257c9efc-0000-4000-8000-d0c500000025",
"discounted_unit_pence": 1500
}Public guest checkout for the Android stopgap / web /pay. Re-prices + re-validates the basket server-side and creates a hosted Stripe Checkout session. Idempotent via the body idempotency_key (order-level replay reuses the same session). When a member is signed in (verified Bearer session) the order is anchored to their customer id so loyalty lands on their card; a client-supplied customer_id is always ignored.
Public store code.
Basket lines (re-priced + re-validated server-side).
Order idempotency key (body, or the Idempotency-Key header). Order-level replay reuses the same session.
Anonymous contact details (loyalty resolves by email at webhook time when no member is signed in).
buy_nowcollectnowscheduledMixed-cart groups (take-now + collect).
nowcollectnowscheduledThe created hosted-checkout session (Stripe Checkout URL + order handle).
curl -X POST "https://www.membber.com/api/v1/checkout/sessions" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
-H "Content-Type: application/json" \
-d '{
"store_code": "EXAMPLE10",
"items": [
{
"menu_item_id": "ca65a6e7-0000-4000-8000-d0c5000000ca",
"quantity": 1
}
]
}'import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.POST("/api/v1/checkout/sessions", {
body: {
store_code: "EXAMPLE10",
items: [
{
menu_item_id: "ca65a6e7-0000-4000-8000-d0c5000000ca",
quantity: 1
}
]
},
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.createCheckoutSession(
body: .json(.init(
storeCode: "EXAMPLE10",
items: [.init(
menuItemId: "ca65a6e7-0000-4000-8000-d0c5000000ca",
quantity: 1
)]
))
).ok.body.json
print(response){
"session": {
"order_id": "4991ffac-0000-4000-8000-d0c500000049",
"order_number": "<order_number>",
"status": "<status>",
"checkout_url": "https://example.com/image.jpg",
"stripe_checkout_session_id": "3c37c50b-0000-4000-8000-d0c50000003c",
"expires_at": "<expires_at>",
"total_pence": 1500,
"currency": "GBP"
}
}Public status poll after a hosted Stripe Checkout redirect: resolves the order by stripe_checkout_session_id and returns its status (paid/expired/etc.), totals, and collection code. 404 when no order matches the session.
The order behind the checkout session (post-redirect status polling).
curl -G "https://www.membber.com/api/v1/checkout/sessions/243a3e51-0000-4000-8000-d0c500000024"import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.GET("/api/v1/checkout/sessions/{sessionId}", {
params: { path: { sessionId: "243a3e51-0000-4000-8000-d0c500000024" } },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.getCheckoutSession(
path: .init(sessionId: "243a3e51-0000-4000-8000-d0c500000024")
).ok.body.json
print(response){
"order": {
"id": "00000d1b-0000-4000-8000-d0c500000000",
"order_number": "<order_number>",
"status": "<status>",
"total_pence": 1500,
"currency": "GBP",
"customer_email": "alex@example.com",
"created_at": "<created_at>",
"paid_at": "<paid_at>",
"expires_at": "<expires_at>",
"order_type": "<order_type>",
"collection_code": "EXAMPLE10"
}
}Merchant read of the full checkout configuration for one store.
Store whose checkout settings to fetch.
curl -G "https://www.membber.com/api/v1/checkout/settings" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
--data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066"import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.getCheckoutSettings({
params: { query: { store_id: "6659c139-0000-4000-8000-d0c500000066" } },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.getCheckoutSettings(
query: .init(storeId: "6659c139-0000-4000-8000-d0c500000066")
).ok.body.json
print(response){
"checkout_enabled": true,
"menu_checkout_enabled": true,
"allow_guest_checkout": true,
"test_mode_enabled": true,
"currency": "GBP",
"min_amount_pence": 1500,
"max_amount_pence": 1500,
"prices_include_vat": true,
"vat_receipts_enabled": true,
"vat_number": "<vat_number>",
"tip_enabled": true,
"tip_presets_pence": [
1500
],
"service_charge_enabled": true,
"service_charge_percent": 1,
"service_charge_label": "<service_charge_label>",
"customer_receipts_enabled": true,
"receipt_email_collection": "alex@example.com",
"refund_window_days": 1,
"purchase_to_loyalty_enabled": true,
"loyalty_rule": "<loyalty_rule>",
"loyalty_spend_threshold_pence": 1500,
"order_fulfilment_mode": "<order_fulfilment_mode>",
"public_note": "Added at the front desk",
"offline_message": "Added at the front desk",
"buy_now_enabled": true,
"collect_enabled": true,
"collect_mode": "<collect_mode>",
"default_prep_minutes": 1,
"max_concurrent_orders": 1,
"orders_per_slot": 1,
"collection_window_days": 1,
"slot_minutes": 1,
"collect_window_start": "<collect_window_start>",
"collect_window_end": "<collect_window_end>",
"collect_daily_release_time": "<collect_daily_release_time>",
"collect_timezone": "Europe/London",
"collect_lead_time_minutes": 1,
"collect_cutoff_minutes": 1,
"collect_paused": true,
"collect_instructions": "<collect_instructions>",
"auto_accept": true,
"show_slot_spots": true
}Public (Android stopgap / web /pay) store payload: branding, checkout + Order & Collect settings, and the purchasable menu with media, allergens, stock and prices. checkout_available reflects the resolved entitlement + Stripe readiness.
Public guest-checkout store payload (branding + settings + menu).
Full public checkout settings (currency, tips, VAT, Order & Collect, loyalty).
Purchasable menu items with media, allergens, stock, prices.
curl -G "https://www.membber.com/api/v1/checkout/shop/EXAMPLE10"import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.GET("/api/v1/checkout/shop/{storeCode}", {
params: { path: { storeCode: "EXAMPLE10" } },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.getCheckoutShop(
path: .init(storeCode: "EXAMPLE10")
).ok.body.json
print(response){
"store": {
"id": "00000d1b-0000-4000-8000-d0c500000000",
"code": "EXAMPLE10",
"name": "Example name",
"description": "Added at the front desk",
"logo_url": "https://example.com/image.jpg",
"primary_color": "<primary_color>",
"brand_color": "<brand_color>",
"secondary_color": "<secondary_color>",
"loyalty_goal": 1,
"reward_title": "<reward_title>",
"stamp_icon_filled_url": "https://example.com/image.jpg",
"stamp_icon_empty_url": "https://example.com/image.jpg",
"is_active": true,
"checkout_available": true,
"unavailable_reason": "Added at the front desk",
"menu_version": "<menu_version>",
"menu_updated_at": "<menu_updated_at>",
"settings": {},
"menu_items": [
{}
]
}
}