6 operations. Every schema and example on this page is generated from the platform contract.
Merchant reads the gym attendance report for their store over a rolling window (default 30 days): a per-day breakdown of classes, bookings, attended, no-shows, cancellations and capacity utilisation, plus a rollup summary. Requires the can_view_reports staff permission.
Store whose attendance report to read (also authorises the merchant).
DEPRECATED alias for a rolling window; prefer preset or start_date/end_date. Days back (default 30).
Preset range (defaults per endpoint). Use "custom" with start_date and end_date for an arbitrary range.
todaylast_7dlast_14dlast_30dlast_90dlast_6mlast_12mcustomCustom range start, store-local YYYY-MM-DD (inclusive). Required when preset is "custom".
Custom range end, store-local YYYY-MM-DD (inclusive). Required when preset is "custom".
curl -G "https://www.membber.com/api/v1/reports/attendance" \
-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/reports/attendance", {
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.getAttendanceReport(
query: .init(storeId: "6659c139-0000-4000-8000-d0c500000066")
).ok.body.json
print(response){
"report": [
{
"day": "<day>",
"total_classes": 1,
"total_bookings": 1,
"total_attended": 1,
"total_no_shows": 1,
"total_cancellations": 1,
"capacity_utilization_pct": 1
}
],
"summary": {
"total_classes": 1,
"total_bookings": 1,
"total_attended": 1,
"total_no_shows": 1,
"avg_capacity_pct": 1
}
}Merchant reads the gym capacity utilisation heatmap for their store over a rolling window (default 30 days): one weekday bucket per day with the class-count-weighted average capacity utilisation and total classes. Requires the can_view_reports staff permission.
Store whose capacity heatmap to read (also authorises the merchant).
DEPRECATED alias for a rolling window; prefer preset or start_date/end_date. Days back (default 30).
Preset range (defaults per endpoint). Use "custom" with start_date and end_date for an arbitrary range.
todaylast_7dlast_14dlast_30dlast_90dlast_6mlast_12mcustomCustom range start, store-local YYYY-MM-DD (inclusive). Required when preset is "custom".
Custom range end, store-local YYYY-MM-DD (inclusive). Required when preset is "custom".
Day of week, 0 = Sunday through 6 = Saturday.
Hour of day, 0 to 23 (currently always 0, weekday-level granularity).
Class-count-weighted average capacity utilisation for the bucket.
Total classes counted in the bucket.
curl -G "https://www.membber.com/api/v1/reports/capacity" \
-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/reports/capacity", {
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.getCapacityReport(
query: .init(storeId: "6659c139-0000-4000-8000-d0c500000066")
).ok.body.json
print(response){
"heatmap": [
{
"day_of_week": 1,
"hour": 1,
"avg_utilization_pct": 1,
"total_classes": 1
}
]
}Merchant reads the churn card for their gym/membership store: the churn rate percentage, the number of memberships cancelled in the last 30 days, the active count, and the at-risk breakdown (paused, frozen, past_due) whose sum is total_at_risk. Read-only rollup gated by can_view_reports.
Store whose churn report to read (also authorises the merchant).
paused + frozen + past_due.
curl -G "https://www.membber.com/api/v1/reports/churn" \
-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/reports/churn", {
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.getChurnReport(
query: .init(storeId: "6659c139-0000-4000-8000-d0c500000066")
).ok.body.json
print(response){
"report": {
"churn_rate_pct": 1,
"cancelled_30d": 1,
"active_count": 1,
"paused_count": 1,
"frozen_count": 1,
"past_due_count": 1,
"total_at_risk": 1
}
}Merchant reads the gym class-popularity ranking for their store over a rolling 30-day window: per class the occurrences, bookings, attendance, no-shows and no-show rate, average capacity utilisation and revenue, ordered by bookings (most booked first). Requires the can_view_reports staff permission.
Store whose class-popularity rankings to read (also authorises the merchant).
Gym class identifier.
Class name.
Class category, or null if uncategorised.
Number of class occurrences in the last 30 days.
Total bookings in the last 30 days.
Bookings marked attended in the last 30 days.
Bookings marked no-show in the last 30 days.
No-show rate as a percentage.
Average capacity utilisation as a percentage.
Revenue attributed to the class in the last 30 days, in pence.
curl -G "https://www.membber.com/api/v1/reports/class-popularity" \
-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/reports/class-popularity", {
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.getClassPopularityReport(
query: .init(storeId: "6659c139-0000-4000-8000-d0c500000066")
).ok.body.json
print(response){
"classes": [
{
"class_id": "2945b542-0000-4000-8000-d0c500000029",
"class_name": "<class_name>",
"category": "<category>",
"occurrences_30d": 1,
"bookings_30d": 1,
"attended_30d": 1,
"no_shows_30d": 1,
"no_show_rate_pct": 1,
"avg_capacity_pct": 1,
"revenue_30d_pence": 1500
}
]
}Merchant views membership retention grouped by join month. For each cohort (month a member joined) it reports how many joined, how many are still active, and the resulting retention percentage. Covers the trailing window of months (default 6), sorted oldest cohort first.
Store whose retention to report (also authorises the merchant).
How many months back to include join cohorts (default 6).
curl -G "https://www.membber.com/api/v1/reports/retention" \
-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/reports/retention", {
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.getReportRetention(
query: .init(storeId: "6659c139-0000-4000-8000-d0c500000066")
).ok.body.json
print(response){
"cohorts": [
{
"cohort_month": "<cohort_month>",
"total_joined": 1,
"still_active": 1,
"retention_pct": 1
}
]
}Merchant reads their monthly recurring revenue snapshot: MRR (pence and pounds), active members, average revenue per member, new signups and cancellations over the last 30 days, past-due count, and projected annual revenue. Derived from the daily-refreshed membership metrics view. Requires the can_view_reports staff permission.
Store whose revenue report to read (also authorises the merchant).
curl -G "https://www.membber.com/api/v1/reports/revenue" \
-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/reports/revenue", {
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.getReportRevenue(
query: .init(storeId: "6659c139-0000-4000-8000-d0c500000066")
).ok.body.json
print(response){
"report": {
"mrr_pence": 1500,
"mrr_pounds": "<mrr_pounds>",
"active_members": 1,
"avg_revenue_per_member_pence": 1500,
"new_signups_30d": 1,
"cancelled_30d": 1,
"past_due_count": 1,
"projected_annual_pence": 1500
}
}