4 operations. Every schema and example on this page is generated from the platform contract.
/api/v1/store-closureClears today's closed override and un-pauses collect. Deliberately does NOT un-refund anything: the money has gone back and the customers have been told.
curl -X DELETE "https://www.membber.com/api/v1/store-closure" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678"import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.DELETE("/api/v1/store-closure", {
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.reopenStore().ok.body.json
print(response){
"reopened": true
}Real computed numbers for the 'we can't trade' confirm sheet, how many orders, how much money, how many PEOPLE to tell and on what channel, plus the progress of a closure already in flight.
Real computed numbers for the close-now confirm sheet. Never an estimate.
The store-LOCAL day the closure covers. Tomorrow is never affected.
Paid orders still holding money that are due on that day.
Total still owed back across those orders.
Distinct PEOPLE to tell, one apology each, however many orders they hold.
Guests with neither an account nor an email. Recorded honestly, never silently dropped.
First names of the first few affected people, so the merchant sees real people before committing.
The live closure, or null when the store is trading normally. Survives the app being closed.
'customers' or 'internal', whether the note above ever reached a customer.
stopping | refunding | notifying | complete | reopened
False when the person who stopped trading lacks can_process_payments, trade halts immediately, refunds wait for someone who may move money.
curl -G "https://www.membber.com/api/v1/store-closure" \
-H "Authorization: Bearer $MEMBBER_TOKEN"import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.GET("/api/v1/store-closure");
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.getStoreClosure().ok.body.json
print(response){
"preview": {
"scope_date": "<scope_date>",
"orders": 1,
"amount_pence": 1500,
"recipients_total": 1,
"recipients_push": 1,
"recipients_email": 1,
"recipients_unreachable": 1,
"sample": [
"<sample>"
]
},
"closure": {
"id": "00000d1b-0000-4000-8000-d0c500000000",
"reason_code": "Added at the front desk",
"merchant_message": "Added at the front desk",
"message_visibility": "Added at the front desk",
"scope_date": "<scope_date>",
"status": "<status>",
"refunds_authorised": true,
"orders_total": 1,
"orders_refunded": 1,
"orders_failed": 1,
"amount_total_pence": 1500,
"amount_refunded_pence": 1500,
"recipients_total": 1,
"recipients_notified": 1,
"opened_at": "<opened_at>"
}
}One durable job: pauses the store for the rest of the store-local day (both take-now and collect), snapshots every paid order still holding money, refunds each one, and sends ONE apology per person. Stopping is a safety action any staff member may take; refunding requires can_process_payments, and when the actor lacks it the refunds stay queued rather than blocking the stop.
equipment_failurestaff_unavailablepower_or_watersold_outweatheremergencyotherThe merchant's own words. Whether a customer ever reads them is decided by message_visibility.
Who the merchant's note is for. 'customers' shows it verbatim to affected customers AND on the storefront closed line. 'internal' keeps it on the closure for staff and audit only, both customer surfaces fall back to the neutral per-reason phrase.
customersinternalTrue when a closure was already running, a second tap resumes it, never forks the work.
Real computed numbers for the close-now confirm sheet. Never an estimate.
The store-LOCAL day the closure covers. Tomorrow is never affected.
Paid orders still holding money that are due on that day.
Total still owed back across those orders.
Distinct PEOPLE to tell, one apology each, however many orders they hold.
Guests with neither an account nor an email. Recorded honestly, never silently dropped.
First names of the first few affected people, so the merchant sees real people before committing.
The live closure, or null when the store is trading normally. Survives the app being closed.
'customers' or 'internal', whether the note above ever reached a customer.
stopping | refunding | notifying | complete | reopened
False when the person who stopped trading lacks can_process_payments, trade halts immediately, refunds wait for someone who may move money.
curl -X POST "https://www.membber.com/api/v1/store-closure" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
-H "Content-Type: application/json" \
-d '{
"reason_code": "equipment_failure"
}'import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.POST("/api/v1/store-closure", {
body: {
reason_code: "equipment_failure"
},
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.openStoreClosure(
body: .json(.init(
reasonCode: .equipmentFailure
))
).ok.body.json
print(response){
"closure_id": "a171799f-0000-4000-8000-d0c5000000a1",
"resumed": true,
"refunds_authorised": true,
"preview": {
"scope_date": "<scope_date>",
"orders": 1,
"amount_pence": 1500,
"recipients_total": 1,
"recipients_push": 1,
"recipients_email": 1,
"recipients_unreachable": 1,
"sample": [
"<sample>"
]
},
"closure": {
"id": "00000d1b-0000-4000-8000-d0c500000000",
"reason_code": "Added at the front desk",
"merchant_message": "Added at the front desk",
"message_visibility": "Added at the front desk",
"scope_date": "<scope_date>",
"status": "<status>",
"refunds_authorised": true,
"orders_total": 1,
"orders_refunded": 1,
"orders_failed": 1,
"amount_total_pence": 1500,
"amount_refunded_pence": 1500,
"recipients_total": 1,
"recipients_notified": 1,
"opened_at": "<opened_at>"
}
}The staff-side read of past closures: the reason, the merchant's own note (private ones included, this surface is the reason a private note is worth writing), who opened it, what it refunded and how many people were told. Newest first, this store only.
Newest first. Defaults to 20.
'closure' (refunded today's orders and told those customers) or 'hold' (stopped new orders only; nobody refunded, nobody messaged).
The reason in words, never the machine code.
What the merchant typed, public or private alike, this is the staff-side read.
'customers' or 'internal', so the merchant can see at a glance which notes went out.
Who stopped trading. Null when the staff member has since been removed.
curl -G "https://www.membber.com/api/v1/store-closure/history" \
-H "Authorization: Bearer $MEMBBER_TOKEN"import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.GET("/api/v1/store-closure/history");
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.listStoreClosures().ok.body.json
print(response){
"closures": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"kind": "<kind>",
"reason_code": "Added at the front desk",
"reason_label": "Added at the front desk",
"merchant_message": "Added at the front desk",
"message_visibility": "Added at the front desk",
"scope_date": "<scope_date>",
"status": "<status>",
"opened_at": "<opened_at>",
"reopened_at": "<reopened_at>",
"opened_by_name": "<opened_by_name>",
"orders_refunded": 1,
"orders_failed": 1,
"amount_refunded_pence": 1500,
"recipients_notified": 1
}
]
}