Get all member memberships with pagination
GET /api/members/memberships
Success: 200 OK
- Products: Operator (
FOH), Consumer (CONSUMER) (any one of these products, not all) - Features: Online Joining (
ONLINEJOIN), Online Bookings (ONLINEBOOK), Front of House Generic Access (FOHGENERIC) (any one of these features, not all)
Overview
Bulk-exports the memberships held across the whole member base — what each member has bought, when it started and ends, who is paying for it and how. Use it to seed or refresh a reporting warehouse or a CRM; for one member on demand, use Get member memberships and payment information instead, which is the same shape but resolves live pricing.
This endpoint does not tell you what a member owes next. paymentDetails.nextPaymentDue, paymentDetails.nextPaymentAmount and the whole paymentDetails.nextPayment object are never populated here — they are always null. Next-payment figures require a live pricing calculation, which only the single-member endpoint performs. If you need them, call that per member.
Two mutually exclusive modes, as with the other bulk exports:
- Delta mode (the default) — returns members with a membership created or modified between
modifiedDateFromandmodifiedDateTo. Omit both and the window is not "everything"; supply them explicitly. - Full export mode — set
returnAllRecords=trueand omit both dates. Sending either date alongside it fails with400.
A member appears if they hold a membership themselves or if they are the primary member paying for a linked member's membership, so the same membership can reach you through more than one member in the export. De-duplicate on membershipRef, which identifies the individual membership record.
Paging runs on member id ascending using a continuation token; there is no offset. The page size here is capped at 25, lower than the other bulk endpoints. Stop when continuation-token comes back as an empty string.
Endpoint
GET {base_url}/api/members/memberships
{base_url} is the environment URL issued to your integration. See Authenticating with Gladstone APIs.
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
modifiedDateFrom | string (date-time) | No | The start of the window, matched against each membership's created and modified dates — either one falling in range includes the member. ISO 8601. Cannot be combined with returnAllRecords=true. |
modifiedDateTo | string (date-time) | No | The end of the window, in the same format and matched against the same two dates. Cannot be combined with returnAllRecords=true. |
continuation-token | string | No | The cursor for the next page, copied verbatim from the previous response. It carries the last member id returned, and paging resumes at the next member id above it. Do not build one by hand — a malformed token is rejected with 400. A token minted with returnAllRecords=true carries no usable date and is rejected if replayed with returnAllRecords=false. The token does not carry your date window, so re-send modifiedDateFrom and modifiedDateTo on every page. Omit it for the first page. |
limit | integer (int32) | No | How many members — not memberships — to return per page. Valid range is 1 to 25; anything above 25 is rejected with 400. 0 or a negative value is not an error, it falls back to the default of 25. Because each member can carry many memberships, a page of 25 can still be a large response. |
returnAllRecords | boolean | No | Switches from delta mode to a full export of every member holding a membership. Defaults to false. Mutually exclusive with the two date parameters, and must stay the same for every call in a paging sequence because it changes what a continuation token means. |
Sample request
curl -X GET '{base_url}/api/members/memberships' \
-H 'Authorization: Bearer {accessToken}' \
-H 'X-Use-SSO: true'Response fields
| Field | Type | Description |
|---|---|---|
members | array of object | One page of members, ordered by member id ascending, at most limit long. Only members with at least one membership appear — the export is not a member list. Empty when nothing matched or you have paged past the end. |
members[].memberId | integer (int32) | The member this block is about, and the cursor paging advances through. Only ids greater than 0 are returned. Note this member is not necessarily the person the membership is for: they may appear because they pay for a linked member's membership. |
members[].memberships | array of object | The memberships reaching this member — those allocated to them, and those they pay for on behalf of linked members. The same membership can therefore appear under more than one member across the export; membershipRef is what identifies it uniquely. |
members[].memberships[].id | string | The membership type code, such as ADULT — what was bought, not which purchase. Operator-defined, shared by every member on that type, and the id used by the membership-type configuration endpoints. For the individual purchase, use membershipRef. |
members[].memberships[].name | string | The operator's name for the membership type. Display text and changeable; key on id. |
members[].memberships[].description | string | The longer, member-facing blurb configured for the type — the wording written for websites and apps rather than for staff. null when the operator has not written one. |
members[].memberships[].membershipRef | integer (int32) | The reference for this specific membership record — the individual purchase, unique across the tenant. This is the value to de-duplicate on, to store as your key, and to match against invoices. |
members[].memberships[].startDate | string (date-time) | When this membership term began. On a renewing membership this moves forward each term, so it is the start of the current term rather than of the relationship — see originalStartDate for that. |
members[].memberships[].expiryDate | string (date-time) | When this membership term ends. On a continuous membership it still holds a date, which is simply rolled forward on renewal, so a past expiryDate does not by itself mean the membership has lapsed — read membershipStatus. |
members[].memberships[].originalStartDate | string (date-time) | When the member first took this membership, unchanged by renewals. Use it for tenure and loyalty calculations. |
members[].memberships[].renewalStopDate | string (date-time) | The date from which the membership will stop renewing — set when a member gives notice. null on a membership that is still set to renew indefinitely. For a continuous membership this, not expiryDate, is what determines whether it is still active. |
members[].memberships[].earliestEndDate | string (date-time) | The earliest date the membership may be ended, reflecting any minimum term the member committed to. null when no minimum term applies. Check it before offering a member a cancellation date. |
members[].memberships[].membershipStatus | string | Either ACTIVE or EXPIRED, calculated at request time rather than stored. For a continuous membership it is ACTIVE while renewalStopDate is null or in the future; for a fixed-term one it is ACTIVE while expiryDate is in the future. There is no separate frozen or cancelled value here. |
members[].memberships[].applyToLinks | boolean | true when this membership type covers the buyer's linked members as well as the buyer. When it is true, assignedToMembers lists everyone covered and the membership is reported once rather than once per person. |
members[].memberships[].backColor | string | The colour the operator has assigned to this membership type for display, converted to a hex string. Cosmetic only. |
members[].memberships[].paidByMember | object | Who actually pays for this membership. It is the member themselves when they pay their own way, and their linked primary member when the primary pays on their behalf. Always present. |
members[].memberships[].paidByMember.id | integer (int32) | The paying member's id. Compare it with members[].memberId to tell a self-funded membership from one a primary member is paying for. |
members[].memberships[].paidByMember.name | string | The paying member's first names and last name joined with a space. Display text; do not parse it back into parts. |
members[].memberships[].assignedToMembers | array of object | Everyone this membership entitles. Normally a single entry — the member it was allocated to. When applyToLinks is true it also lists the linked members covered by the same purchase. |
members[].memberships[].assignedToMembers[].id | integer (int32) | The covered member's id. |
members[].memberships[].assignedToMembers[].name | string | The covered member's first names and last name joined with a space. |
members[].memberships[].duration | object | How long a term of this membership type runs, and whether it renews. Describes the type, not the remaining time on this particular membership. |
members[].memberships[].duration.isContinuous | boolean | true when the membership auto-renews rather than simply expiring. This is the flag that decides how membershipStatus is worked out, so read it before interpreting expiryDate. |
members[].memberships[].duration.durationType | string | The unit that value is counted in: Monthly, Daily or Weekly. Returned as a name, not a number. |
members[].memberships[].duration.value | integer (int32) | How many of durationType make up one term — value: 12 with durationType: Monthly being a twelve-month term. |
members[].memberships[].paymentDetails | object | How this membership was invoiced, resolved from the sales invoice raised for it. null when no matching invoice was found — for example a membership granted without a sale — so check for null before reading into it. |
members[].memberships[].paymentDetails.paymentMethodId | string | The payment method code on the invoice, as configured by the operator. Usually the same as the membership's own paymentMethodId, but this one reflects what the invoice was actually raised against. |
members[].memberships[].paymentDetails.paymentMethodDescription | string | The operator's label for that payment method, such as Direct Debit. Display text; see translations for other languages. |
members[].memberships[].paymentDetails.nextPaymentDue | string (date-time) | Always null on this endpoint. Next-payment dates require a live pricing calculation that the bulk export does not perform. Use Get member memberships and payment information for a member you need this for. |
members[].memberships[].paymentDetails.nextPaymentAmount | number (double) | Always null on this endpoint, for the same reason as nextPaymentDue. Do not treat the absence as "nothing to pay". |
members[].memberships[].paymentDetails.paymentStatus | string | Where the invoice for this membership stands, as a name: Unpaid, PartPaid, Paid, Void, PartCredited, PartCreditedPaid, Credited or CreditNote. This is the invoice's status, not the membership's — an EXPIRED membership can still be Paid. |
members[].memberships[].paymentDetails.collectionInterface | string | How the money is collected, as a name: Manual, DirectDebit, CreditCard, External, SmartCard, CashlessAccount, LoyaltyPoints, OnLineAuthorisation, InvoicingAccount or EFT. Note DirectDebit and EFT are distinct values here, whereas membershipIsDirectDebit treats any EFT system as direct debit. |
members[].memberships[].paymentDetails.translations | array of object | Translations of the payment method description. Empty when the operator has configured none — in which case fall back to paymentMethodDescription. |
members[].memberships[].paymentDetails.translations[].type | string | Which piece of text this translation is for, since a record can carry translations of more than one attribute. |
members[].memberships[].paymentDetails.translations[].culture | string | The culture the text is written for, such as cy-GB. Match it against your user's locale; there is no automatic fallback. |
members[].memberships[].paymentDetails.translations[].text | string | The translated text itself. |
members[].memberships[].paymentDetails.nextPayment | object | Always null on this endpoint. The whole next-payment breakdown, including discounts, comes from live pricing and is only populated by the single-member endpoint. |
members[].memberships[].paymentDetails.nextPayment.amount | string | Not populated here — see nextPayment. On the single-member endpoint this is the amount due, as a string rather than a number. |
members[].memberships[].paymentDetails.nextPayment.currency | string | Not populated here — see nextPayment. |
members[].memberships[].paymentDetails.nextPayment.discount | object | Not populated here — see nextPayment. |
members[].memberships[].paymentDetails.nextPayment.discount.priceBeforeDiscount | string | Not populated here — see nextPayment. |
members[].memberships[].paymentDetails.nextPayment.discount.discountValue | string | Not populated here — see nextPayment. |
members[].memberships[].paymentDetails.nextPayment.discount.discountEndDate | string (date-time) | Not populated here — see nextPayment. |
members[].memberships[].isUsageSubscription | boolean | true when the membership type is sold as a bundle of visits rather than a period of time — a ten-session pass, for example. Derived from the type having a maximum usage above zero. When it is true, usagesRemaining is the number that matters, not expiryDate. |
members[].memberships[].usagesRemaining | integer (int32) | How many uses are left on a usage-based membership. Returned as 0, never null, when the membership has none left and when it is not usage-based at all — so always check isUsageSubscription before showing this to anyone. |
members[].memberships[].imageUrl | string | The full URL of the image configured for this membership type, for display in apps and portals. null when the type has no image. |
members[].memberships[].paymentMethodId | string | The payment method recorded on the membership itself, as opposed to on its invoice. Where the two differ, this is the method the membership is set to use going forward. |
members[].memberships[].documentationRequired | array of object | The documents the operator requires for this membership type, each flagged with whether the member has supplied it. Empty when the type requires none. This is a checklist, not a set of files — the documents themselves are not in this response. |
members[].memberships[].documentationRequired[].documentTypeInd | integer (int32) | One of ProofOfEligibility (ProofOfEligibility), ProofOfCancellation (ProofOfCancellation), MedicalInformation (MedicalInformation), ContractualInformation (ContractualInformation), DirectDebitMandate (DirectDebitMandate), PARQAndHealthCommitmentStatement (PARQAndHealthCommitmentStatement), SunbedDeclaration (SunbedDeclaration), EmailAttachment (EmailAttachment), OtherSupportingDocument (OtherSupportingDocument), MemberPicture (MemberPicture). |
members[].memberships[].documentationRequired[].documentName | string | The operator's name for the required document, as shown to staff and members. |
members[].memberships[].documentationRequired[].documentComments | string | The operator's note explaining what is wanted or why. null when none was written. |
members[].memberships[].documentationRequired[].uploaded | boolean | Whether the member has supplied this document. false means outstanding — the platform does not block the membership on it, so treat it as a prompt rather than a gate. |
members[].memberships[].documentationRequired[].translations | array of object | Translations of the document name and comments. Empty when none are configured. |
members[].memberships[].documentationRequired[].translations[].type | string | Which piece of text this translation is for. |
members[].memberships[].documentationRequired[].translations[].culture | string | The culture the text is written for, such as cy-GB. |
members[].memberships[].documentationRequired[].translations[].text | string | The translated text itself. |
members[].memberships[].translations | array of object | Translations of the membership type's own text — its name and description. Empty when the operator has configured none, in which case use name and description directly. |
members[].memberships[].translations[].type | string | Which piece of text this translation is for. |
members[].memberships[].translations[].culture | string | The culture the text is written for, such as cy-GB. |
members[].memberships[].translations[].text | string | The translated text itself. |
members[].memberships[].membershipIsDirectDebit | boolean | true when the membership's payment method is wired to any electronic funds transfer system. Broader than paymentDetails.collectionInterface == "DirectDebit", which names one specific collection route — a membership can be true here and show EFT there. |
members[].memberships[].modifiedOn | string (date-time) | When this membership record was last changed. One of the two fields the date window filters on, and the value the continuation token is built from, so it is what you keep as a high-water mark. null on a record never modified since creation. |
members[].memberships[].createdOn | string (date-time) | When this membership record was created. The other field the date window filters on, so newly sold memberships appear in a delta run even though nothing has been modified. |
continuation-token | string | The cursor to send back for the next page. An empty string when there is no more data — that, not a short page, is the end-of-data signal. It encodes the last member id in the page and is only valid for the same returnAllRecords mode that produced it. |
Sample response
{
"members": [
{
"memberId": 12345,
"memberships": [
{
"id": "string",
"name": "string",
"description": "string",
"membershipRef": 1,
"startDate": "2026-08-14T19:00:00Z",
"expiryDate": "2026-08-14T19:00:00Z",
"originalStartDate": "2026-08-14T19:00:00Z",
"renewalStopDate": "2026-08-14T19:00:00Z",
"earliestEndDate": "2026-08-14T19:00:00Z",
"membershipStatus": "string",
"applyToLinks": true,
"backColor": "string",
"paidByMember": {
"id": 12345,
"name": "string"
},
"assignedToMembers": [
{
"id": 12345,
"name": "string"
}
],
"duration": {
"isContinuous": true,
"durationType": "string",
"value": 1
},
"paymentDetails": {
"paymentMethodId": "string",
"paymentMethodDescription": "string",
"nextPaymentDue": "2026-08-14T19:00:00Z",
"nextPaymentAmount": 10.5,
"paymentStatus": "string",
"collectionInterface": "string",
"translations": [
{
"type": "string",
"culture": "string",
"text": "string"
}
],
"nextPayment": {
"amount": "string",
"currency": "GBP",
"discount": {
"priceBeforeDiscount": "string",
"discountValue": "string",
"discountEndDate": "2026-08-14T19:00:00Z"
}
}
},
"isUsageSubscription": true,
"usagesRemaining": 1,
"imageUrl": "string",
"paymentMethodId": "string",
"documentationRequired": [
{
"documentTypeInd": 1,
"documentName": "string",
"documentComments": "string",
"uploaded": true,
"translations": [
{
"type": "string",
"culture": "string",
"text": "string"
}
]
}
],
"translations": [
{
"type": "string",
"culture": "string",
"text": "string"
}
],
"membershipIsDirectDebit": true,
"modifiedOn": "2026-08-14T19:00:00Z",
"createdOn": "2026-08-14T19:00:00Z"
}
]
}
],
"continuation-token": "string"
}Errors
| Status | Meaning | When |
|---|---|---|
400 | Bad request | returnAllRecords=true was sent together with modifiedDateFrom and/or modifiedDateTo. The body is You cannot specify a dateFrom and/or dateTo if returnAllRecords is set to true. |
400 | Bad request | limit is greater than 25. The body is Invalid value supplied for number of profiles per page. Limit must be an integer from 1 to 25. A limit of 0 or below is not an error — it falls back to 25. |
400 | Bad request | A continuation token from full-export mode was replayed with returnAllRecords=false. The body is The continuation-token {token} is not valid while returnAllRecords is false. |
400 | Bad request | The continuation token is malformed — a part that is not a key and value pair, or a value that will not parse. The body names the offending element or value. |
400 | Bad request | modifiedDateFrom or modifiedDateTo is not a recognisable ISO 8601 date. The body is a validation error. |
500 | Internal server error | An unexpected server-side failure while reading the memberships. |