# 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)

HTML version: [Get all member memberships with pagination](https://support.gladstonesoftware.cloud/reference/members/get-all-member-memberships-with-pagination)

## 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](get-member-memberships-and-payment-information.md) 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 `modifiedDateFrom` and `modifiedDateTo`. Omit both and the window is not "everything"; supply them explicitly.
- **Full export mode** — set `returnAllRecords=true` and omit both dates. Sending either date alongside it fails with `400`.

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](../../guides/authenticating-with-gladstone-apis.md).

## 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

```bash title="cURL"
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](get-member-memberships-and-payment-information.md) 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

```json title="200 OK"
{
  "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. |
