3 operations. Every schema and example on this page is generated from the platform contract.
The Business-app customer-detail timeline: a single chronological (newest-first) feed interleaving every recorded touchpoint for one member at one store, paginated by a before cursor. Also returns whether the customer has any store-scoped agreements on record. Store-scoped and relationship-gated: a customer with no relationship at this store returns 404.
Store whose journey with the customer to read (also authorises the merchant).
Page size (default 25, max 50).
ISO 8601 cursor, return events strictly older than this timestamp.
joinedstampvoucher_earnedvoucher_redeemedordermessageemailjourneymomentclass_bookingmembershipin_storein_appemailjourneymomentgymcurl -G "https://www.membber.com/api/v1/customers/a1c10999-0000-4000-8000-d0c5000000a1/journey" \
-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.raw.GET("/api/v1/customers/{customerId}/journey", {
params: { path: { customerId: "a1c10999-0000-4000-8000-d0c5000000a1" }, 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.getCustomerJourney(
path: .init(customerId: "a1c10999-0000-4000-8000-d0c5000000a1"),
query: .init(storeId: "6659c139-0000-4000-8000-d0c500000066")
).ok.body.json
print(response){
"events": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"type": "joined",
"channel": "in_store",
"timestamp": "<timestamp>",
"title": "Morning class",
"subtitle": "<subtitle>",
"status": "<status>",
"detail": "<detail>",
"campaignName": "<campaignName>",
"opened": true,
"clicked": true,
"returningVisitAt": "<returningVisitAt>",
"returnDays": 1,
"amountPence": 1500,
"refundedPence": 1,
"promoDiscountPence": 1,
"appliedPromoCode": "EXAMPLE10",
"currency": "GBP",
"autoSent": true,
"resultKind": "<resultKind>",
"resultAt": "<resultAt>",
"resultValuePence": 1
}
],
"pagination": {
"limit": 25,
"before": "<before>",
"nextCursor": "<nextCursor>",
"hasMore": true
},
"has_store_agreements": true
}Merchant browses their full customer roster, everyone who has interacted with the store, enriched with lifecycle stage, visits, stamp count, order count + net spend, and marketing consent. Supports stage/facet/text filters, sort by recent/spend/visits/name, and pagination with a true filtered total_count.
Store whose roster to list (also authorises the merchant).
Sort order (default recent).
recentspendvisitsnameLifecycle-stage filter.
newactivestalelapsedreturningComma-separated AND filters: has_orders, has_stamps, marketing_opted_in.
Filter the roster by name/email/phone.
Page size (default 30, max 100).
Page offset.
curl -G "https://www.membber.com/api/v1/customers/list" \
-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.raw.GET("/api/v1/customers/list", {
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.listCustomers(
query: .init(storeId: "6659c139-0000-4000-8000-d0c500000066")
).ok.body.json
print(response){
"customers": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"name": "Example name",
"phone": "+44 7700 900123",
"email": "alex@example.com",
"last_visit_at": "<last_visit_at>",
"lifecycle_stage": "<lifecycle_stage>",
"total_visits": 1,
"stamp_count": 1,
"order_count": 1,
"total_spent_pence": 1500,
"marketing_opted_in": true
}
],
"pagination": {
"limit": 25,
"offset": 0,
"has_more": true,
"total_count": 1
}
}Merchant searches the customers who have interacted with their store (class bookings, stamps, or paid orders). A 2+ character term filters by name/phone/email; a short/empty term returns the most-recent customers as a list.
Store whose customers to search (also authorises the merchant).
Search term; 2+ chars filters by name/phone/email, else returns the most-recent 20.
curl -G "https://www.membber.com/api/v1/customers/search" \
-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.raw.GET("/api/v1/customers/search", {
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.searchCustomers(
query: .init(storeId: "6659c139-0000-4000-8000-d0c500000066")
).ok.body.json
print(response){
"customers": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"name": "Example name",
"phone": "+44 7700 900123",
"email": "alex@example.com",
"last_seen": "<last_seen>"
}
]
}