List all member profiles with filtering and pagination

GET /api/members/profiles

Success: 200 OK

Overview

Returns member profiles in pages, for integrations that need to mirror or export an operator's member base rather than look up one member. Unlike the per-member endpoints, this one does not check a member ID against your access token — it is a bulk operation, authorised by your integration's scope alone.

Pick one of two modes before you start, and stay in it. By default the endpoint returns a window of recently changed profiles, bounded by dateFrom and dateTo on the member record's last-modified date. Send returnAllRecords=true instead to walk the entire member base. The two are mutually exclusive: sending a date alongside returnAllRecords=true is rejected with 400.

A call with no parameters at all is not "everything". With no dateFrom the window defaults to the start of yesterday, UTC; with no dateTo it defaults to the moment the request is handled. A bare call therefore returns only members changed in roughly the last day, and returns nothing at all on a quiet system. If you meant to fetch every member, you have to say so with returnAllRecords=true.

Paging. Pages hold at most 25 profiles and the size cannot be changed — there is no limit parameter. Read continuation-token from the response and send it back as the continuation-token query parameter to get the next page; omit it on the first call. Keep going until a response comes back with an empty profiles array and an empty token. The token records only your position — the member ID and modified date of the last profile on the page — so it does not remember your query: resend dateFrom, dateTo, returnAllRecords, the filters and the include* flags identically on every page, or later pages will not mean what you think. Tokens are also tied to the mode that produced them, and mixing them is the most common way to break a bulk export.

What comes back. Each profile carries the member's core details and their current status; there is no includeStatus flag here, unlike the single-profile endpoint, and status is always populated. Addresses, contact details and subscriptions are omitted unless you ask for them. And as on the single-profile endpoint, a caller whose token carries the DataHub feature and none of the privileged full-profile features (TRP, online booking or online join) receives a deliberately reduced profile — member ID, home site, gender, join date, date of birth, postcode and subscriptions, and nothing else.

One difference from Retrieve a member's basic profile details worth planning around: this endpoint returns the address stored on the member record in email and does not resolve inherited addresses. For a member whose inheritPrimaryMembersEmail is true — typically a junior member using a parent's address — the usable address belongs to the primary member, and this endpoint will not give it to you.

Endpoint

GET {base_url}/api/members/profiles

{base_url} is the environment URL issued to your integration. See Authenticating with Gladstone APIs.

Query parameters

NameTypeRequiredDescription
dateFromstring (date-time)NoStart of the window, applied to the date each member record was last modified. Omit it and it defaults to the start of yesterday in UTC — not the beginning of time — so a bare call returns roughly the last day's changes. It must not be in the future and must not be later than dateTo; either is rejected with 400. Cannot be combined with returnAllRecords=true.
dateTostring (date-time)NoEnd of that window. Omit it and it defaults to the moment the request is handled, which is why you normally send only dateFrom. It must not be in the future. Cannot be combined with returnAllRecords=true.
continuation-tokenstringNoYour position in the result set. Omit it on the first call to start at the beginning, then send back the continuation-token value from the previous response, verbatim, for each subsequent page. Treat it as opaque and never build one yourself — a malformed value is rejected with 400. It records only the member ID and modified date of the last profile returned, so it carries no memory of your query: every page must repeat the same dateFrom, dateTo, returnAllRecords, filters and include* flags. It is also bound to the mode that produced it, so a token minted by a returnAllRecords=true run is rejected with 400 The continuation-token {token} is not valid while returnAllRecords is false if you then send it on a date-windowed call. The reverse combination is not checked and will page incorrectly rather than fail, so never reuse a token across modes.
returnAllRecordsbooleanNoSet to true to page through every member profile rather than a date window. Defaults to false. Mutually exclusive with dateFrom and dateTo — sending either alongside it is rejected with 400 You cannot specify a dateFrom and/or dateTo if returnAllRecords is set to true. Its value is part of the paging contract as well as the query: send the same value on every page of a run, because continuation tokens are not interchangeable between the two modes.
includeSubscriptionsbooleanNoSet to true to populate subscriptionDetails — the memberships held by each member in the page. Defaults to false. Fetching subscriptions adds work to every page, so leave it off for a change-detection sweep and turn it on for a full export.
includeAddressesbooleanNoSet to true to populate address1 and address2 for each member in the page. Defaults to false.
includeContactDetailsbooleanNoSet to true to populate contactDetails — the email addresses and telephone numbers held for each member in the page. Defaults to false. Note that the top-level email field is returned either way.
siteIdsstringNoComma-separated list of site identifiers — a site is one leisure centre — restricting the results to members at those sites. Whitespace around each value is trimmed, so A01, A02 is accepted. Every value must be a site that exists, or the whole request is rejected with 400 One or more supplied site IDs do not exist. and no indication of which value was wrong.
subscriptionGroupsstringNoComma-separated list of subscription group identifiers, restricting the results to members holding a membership in one of those groups. A subscription group is the operator's categorisation of memberships; take the identifiers from profiles[].subscriptionDetails[].subscriptionGroups[].id. Whitespace around each value is trimmed. Every value must exist, or the request is rejected with 400 One or more supplied subscription groups do not exist.
statusIdsstringNoComma-separated list of member status identifiers. When supplied, only members whose current status matches one of these is returned; take the values from profiles[].status.id. Whitespace around each value is trimmed. Every value must exist, or the request is rejected with 400 One or more supplied status IDs do not exist.

Sample request

cURL
curl -X GET '{base_url}/api/members/profiles' \
  -H 'Authorization: Bearer {accessToken}' \
  -H 'X-Use-SSO: true'

Response fields

FieldTypeDescription
[].profilesarray of objectThe page of member profiles, at most 25. An empty array means there is nothing more to fetch — either you have reached the end of the result set or nothing matched your filters.
[].profiles[].memberIdinteger (int32)The member's identifier in Gladstone, and the value you pass as {memberId} to every per-member endpoint. It is stable for the life of the record, so use it as the key when you mirror members into your own system.
[].profiles[].homeSiteIdstringThe site — a single leisure centre — the member is registered at. Always the same value as site.id; both come from the same value on the member record.
[].profiles[].linkedTointeger (int32)The member ID of the primary member this account is linked to — the parent or lead member who manages it. Linked accounts are what allow one authenticated member to read another's profile, and what makes an inherited email address possible.
[].profiles[].titleIdstringThe code for the member's title, from the operator's configured list of titles. A member with no title recorded is returned as UNKNO rather than null, because a default is substituted — so check for that code, not for an absent field.
[].profiles[].titlestringThe wording that goes with titleId, for display. A member with no title recorded is returned as Unknown.
[].profiles[].firstNamestringThe member's given name.
[].profiles[].lastNamestringThe member's family name.
[].profiles[].address1objectThe first of the two addresses the platform holds against a member. Only populated when you send includeAddresses=true.
[].profiles[].address1.addressLine1stringFirst line of the street address.
[].profiles[].address1.addressLine2stringSecond line of the street address, where one is held.
[].profiles[].address1.addressLine3stringThird line of the street address, where one is held.
[].profiles[].address1.townCitystringThe town or city.
[].profiles[].address1.regionstringThe county, state or region.
[].profiles[].address1.postalCodestringThe postcode for this address.
[].profiles[].address1.countrystringThe country.
[].profiles[].address1.isPrimarybooleantrue on the address the member uses as their main one. Use it to choose between address1 and address2 when you need a single address for the member.
[].profiles[].address2objectThe second of the two addresses the platform holds against a member. Only populated when you send includeAddresses=true, and empty for a member with only one address on file.
[].profiles[].address2.addressLine1stringFirst line of the street address.
[].profiles[].address2.addressLine2stringSecond line of the street address, where one is held.
[].profiles[].address2.addressLine3stringThird line of the street address, where one is held.
[].profiles[].address2.townCitystringThe town or city.
[].profiles[].address2.regionstringThe county, state or region.
[].profiles[].address2.postalCodestringThe postcode for this address.
[].profiles[].address2.countrystringThe country.
[].profiles[].address2.isPrimarybooleantrue when this is the address the member uses as their main one, rather than address1.
[].profiles[].contactDetailsobjectThe email addresses and telephone numbers held for the member. Only populated when you send includeContactDetails=true.
[].profiles[].contactDetails.emailarray of objectThe member's email records. The platform holds a home and a work address per member and flags one of them as primary.
[].profiles[].contactDetails.email[].email1stringOne of the two email addresses held for the member.
[].profiles[].contactDetails.email[].email2stringThe other of the two email addresses held for the member.
[].profiles[].contactDetails.email[].isPrimarybooleantrue when this record holds the member's primary email address — the one to use when you need a single address to write to.
[].profiles[].contactDetails.email[].isInheritedfromPrimaryMemberbooleantrue when the member has no address of their own and uses the primary member's instead, as a junior member does with a parent's. Note that this endpoint does not resolve that inheritance for you: see the top-level email field.
[].profiles[].contactDetails.telephonearray of objectThe member's telephone records.
[].profiles[].contactDetails.telephone[].mobilestringThe member's mobile number.
[].profiles[].contactDetails.telephone[].telephone1stringOne of the two landline numbers held for the member.
[].profiles[].contactDetails.telephone[].telephone2stringThe other of the two landline numbers held for the member.
[].profiles[].contactDetails.telephone[].isPrimarybooleantrue when this record holds the member's primary telephone contact.
[].profiles[].genderobjectThe member's recorded gender. It is a configured lookup rather than free text, so you get an identifier, the operator's wording for it, and any translations of that wording.
[].profiles[].gender.idinteger (int32)Identifies the configured gender option held against the member. The available options are operator configuration, so map on this identifier rather than assuming a fixed set of values.
[].profiles[].gender.namestringThe operator's untranslated wording for that gender option.
[].profiles[].gender.translationsarray of objectLocalised versions of name, one entry per language the operator has configured. Empty when none have been configured, in which case display name.
[].profiles[].gender.translations[].typestringIdentifies the set of configured text this translation belongs to.
[].profiles[].gender.translations[].culturestringThe culture the text is written for, in the form en-GB. Which cultures appear depends on the languages the operator has enabled.
[].profiles[].gender.translations[].textstringThe wording for that culture. Use it in place of name when it matches your user's language.
[].profiles[].dateOfBirthstring (date-time)The member's date of birth. The platform compares it against the operator's configured age of consent, which is what decides whether consent and profile changes for this member need a guardian's name.
[].profiles[].siteobjectThe centre the member is registered at, with its name and translations. site.id always repeats homeSiteId.
[].profiles[].site.idstringIdentifies the centre. This is the same identifier you pass to the siteIds filter.
[].profiles[].site.namestringThe centre's untranslated name.
[].profiles[].site.translationsarray of objectLocalised versions of the centre's name, one entry per language the operator has configured.
[].profiles[].site.translations[].typestringIdentifies the set of configured text this translation belongs to.
[].profiles[].site.translations[].culturestringThe culture the text is written for, in the form en-GB.
[].profiles[].site.translations[].textstringThe centre's name in that culture.
[].profiles[].statusobjectThe member's current status — active, lapsed, suspended and so on, as configured by the operator. Always populated on this endpoint; there is no flag to switch it off, unlike the single-profile endpoint where it is opt-in.
[].profiles[].status.idstringThe status code currently held against the member. These are exactly the values you pass to the statusIds filter, so read them from here rather than hard-coding a list.
[].profiles[].status.statusDatestring (date-time)The date recorded against the member's current status.
[].profiles[].status.descriptionstringThe operator's wording for the status, suitable for display.
[].profiles[].status.textColourstringThe foreground colour the operator configured for showing this status, so your interface can match theirs.
[].profiles[].status.backColourstringThe background colour the operator configured for showing this status.
[].profiles[].priceLevelobjectThe pricing category the member is placed in. Every member is assigned one when they are created, falling back to the operator's default when none is supplied.
[].profiles[].priceLevel.idstringIdentifies the price level held against the member.
[].profiles[].priceLevel.descriptionstringThe operator's untranslated wording for the price level.
[].profiles[].priceLevel.translationsarray of objectLocalised versions of description, one entry per language the operator has configured.
[].profiles[].priceLevel.translations[].typestringIdentifies the set of configured text this translation belongs to.
[].profiles[].priceLevel.translations[].culturestringThe culture the text is written for, in the form en-GB.
[].profiles[].priceLevel.translations[].textstringThe price level description in that culture.
[].profiles[].joinDatestring (date-time)The date the member joined the operator. It is supplied when the member is created rather than derived from the record, so for a member migrated from an older system it can sit well before createdOn.
[].profiles[].emailstringThe email address stored on the member record itself. This endpoint returns it as stored and does not resolve inheritance: where inheritPrimaryMembersEmail is true, the address you should actually write to belongs to the primary member and is not this value. The single-profile endpoint resolves it for you; this one does not.
[].profiles[].inheritPrimaryMembersEmailbooleantrue when the member takes their email address from the primary member on their linked account, as a junior member does from a parent. When it is true, ignore email here and read the address from the primary member identified by linkedTo, or call GET /api/members/{memberId}/profile, which resolves it.
[].profiles[].attendanceCountPast30Daysinteger (int32)How many times the member attended over the past 30 days. Attendances less than an hour apart are deliberately counted as a single visit, so this is lower than the raw number of access events — a member who scans in twice within the hour counts once. 0 where there are no attendances.
[].profiles[].activityCountPast30Daysinteger (int32)How many activities the member took part in over the past 30 days. 0 where there are none.
[].profiles[].lastVisitedobjectThe member's most recent recorded visit. null when no visit has ever been recorded for them, so check before dereferencing it.
[].profiles[].lastVisited.datestring (date-time)When that visit took place.
[].profiles[].lastVisited.siteIdstringThe centre visited, which is not necessarily the member's homeSiteId.
[].profiles[].lastVisited.siteNamestringThe name of that centre, so you do not have to look it up.
[].profiles[].subscriptionDetailsarray of objectThe memberships held by this member. Only populated when you send includeSubscriptions=true; empty otherwise. Memberships are not managed through the profile endpoints, so treat this as a summary and go to the membership endpoints for anything you intend to act on.
[].profiles[].subscriptionDetails[].idstringIdentifies this subscription record.
[].profiles[].subscriptionDetails[].siteIdstringThe site this subscription is recorded against. It is held on the subscription itself, so do not assume it is the member's homeSiteId.
[].profiles[].subscriptionDetails[].membershipRefinteger (int32)
[].profiles[].subscriptionDetails[].autoRenewIndinteger (int32)Indicates whether the subscription is set to renew automatically.
[].profiles[].subscriptionDetails[].renewalStopDatestring (date-time)
[].profiles[].subscriptionDetails[].expiryDatestring (date-time)The date the subscription expires. null where no expiry is recorded against it.
[].profiles[].subscriptionDetails[].lastModifiedDatestring (date-time)When this subscription record was last changed. It tracks the subscription rather than the member, so it moves independently of the profile's own modifiedOn — and changing a subscription will not necessarily bring the member into a dateFrom/dateTo window.
[].profiles[].subscriptionDetails[].createdOnstring (date-time)When this subscription record was created.
[].profiles[].subscriptionDetails[].startDatestring (date-time)The date the subscription starts.
[].profiles[].subscriptionDetails[].membershipStatusstringThe subscription's current status, which is separate from the member's own status.
[].profiles[].subscriptionDetails[].subscriptionGroupsarray of objectThe subscription groups this membership belongs to — the operator's categorisation of memberships.
[].profiles[].subscriptionDetails[].subscriptionGroups[].idstringIdentifies the group. This is the value to pass to the subscriptionGroups filter; supplying one that does not exist is rejected with 400.
[].profiles[].subscriptionDetails[].subscriptionGroups[].descriptionstringThe operator's wording for the group, suitable for display.
[].profiles[].modifiedOnstring (date-time)When the member record was last changed. This is the date the dateFrom/dateTo window filters on and the position the continuation token carries forward, so it is also the order results are paged in. Use it as your high-water mark when polling for changes.
[].profiles[].createdOnstring (date-time)When the member record was first created in Gladstone. Distinct from joinDate, which is a business date supplied at creation and can be earlier.
[].continuation-tokenstringYour position in the result set. Send it back as the continuation-token query parameter, verbatim, to fetch the next page, together with an unchanged copy of the rest of your query. It is an empty string only when the page came back with no profiles at all, which is your signal to stop — a short page still carries a token, so never treat "fewer than 25 profiles" as the end of the data.

Sample response

200 OK
[
  {
    "profiles": [
      {
        "memberId": 12345,
        "homeSiteId": "string",
        "linkedTo": 1,
        "titleId": "string",
        "title": "string",
        "firstName": "string",
        "lastName": "string",
        "address1": {
          "addressLine1": "string",
          "addressLine2": "string",
          "addressLine3": "string",
          "townCity": "string",
          "region": "string",
          "postalCode": "string",
          "country": "string",
          "isPrimary": true
        },
        "address2": {
          "addressLine1": "string",
          "addressLine2": "string",
          "addressLine3": "string",
          "townCity": "string",
          "region": "string",
          "postalCode": "string",
          "country": "string",
          "isPrimary": true
        },
        "contactDetails": {
          "email": [
            {
              "email1": "member@example.com",
              "email2": "member@example.com",
              "isPrimary": true,
              "isInheritedfromPrimaryMember": true
            }
          ],
          "telephone": [
            {
              "mobile": "string",
              "telephone1": "string",
              "telephone2": "string",
              "isPrimary": true
            }
          ]
        },
        "gender": {
          "id": 12345,
          "name": "string",
          "translations": [
            {
              "type": "string",
              "culture": "string",
              "text": "string"
            }
          ]
        },
        "dateOfBirth": "2026-08-14T19:00:00Z",
        "site": {
          "id": "string",
          "name": "string",
          "translations": [
            {
              "type": "string",
              "culture": "string",
              "text": "string"
            }
          ]
        },
        "status": {
          "id": "string",
          "statusDate": "2026-08-14T19:00:00Z",
          "description": "string",
          "textColour": "string",
          "backColour": "string"
        },
        "priceLevel": {
          "id": "string",
          "description": "string",
          "translations": [
            {
              "type": "string",
              "culture": "string",
              "text": "string"
            }
          ]
        },
        "joinDate": "2026-08-14T19:00:00Z",
        "email": "member@example.com",
        "inheritPrimaryMembersEmail": true,
        "attendanceCountPast30Days": 1,
        "activityCountPast30Days": 1,
        "lastVisited": {
          "date": "2026-08-14T19:00:00Z",
          "siteId": "string",
          "siteName": "string"
        },
        "subscriptionDetails": [
          {
            "id": "string",
            "siteId": "string",
            "membershipRef": 1,
            "autoRenewInd": 1,
            "renewalStopDate": "2026-08-14T19:00:00Z",
            "expiryDate": "2026-08-14T19:00:00Z",
            "lastModifiedDate": "2026-08-14T19:00:00Z",
            "createdOn": "2026-08-14T19:00:00Z",
            "startDate": "2026-08-14T19:00:00Z",
            "membershipStatus": "string",
            "subscriptionGroups": [
              {
                "id": "string",
                "description": "string"
              }
            ]
          }
        ],
        "modifiedOn": "2026-08-14T19:00:00Z",
        "createdOn": "2026-08-14T19:00:00Z"
      }
    ],
    "continuation-token": "string"
  }
]

Errors

StatusMeaningWhen
400Bad requestSending dateFrom or dateTo together with returnAllRecords=true; a dateFrom or dateTo in the future; a dateFrom later than dateTo; any siteIds, subscriptionGroups or statusIds value that does not exist; or a continuation-token that is malformed or was produced by a returnAllRecords=true run and then sent without it. The body is a plain-text message naming the specific problem.
500Internal server errorAn unexpected server-side failure while assembling the page. The response carries no body. Retry the same page with the same continuation token — nothing has been consumed — and raise it with Gladstone if it persists.

This page as markdown · All pages · llms.txt