# Get membership types by membership type groups

`GET /api/configuration/membership-types/groups`

- **Success:** `200 OK`
- **Products:** Operator (`FOH`)
- **Features:** Front of House Generic Access (`FOHGENERIC`)

HTML version: [Get membership types by membership type groups](https://support.gladstonesoftware.cloud/reference/configuration/get-membership-types-by-membership-type-groups)

## Overview

Expands membership type groups into the membership types they contain. Each element of the array is
one group, carrying its own id and description plus a nested `membershipTypes` array of every
membership type mapped to it, with translated descriptions.

This is the call that resolves a group id into concrete membership type ids, and you will need it
more often than you expect, because **nothing else on the platform expands groups for you**.
Anywhere an API asks for membership type ids — audience and query filters being the usual case — a
group id is not accepted in their place. The pattern is: let the user pick the group, call this
endpoint with that group id, collect the `id` of every entry under `membershipTypes`, and send
those individual ids onward.

Call it with no parameters to get the entire group-to-type map in one request, which is the
cheapest way to build a local lookup. Call it with `groupIds` to narrow the result.

Two behaviours worth knowing before you write the client:

- **The id check is all-or-nothing.** If any id in `groupIds` does not exist, the whole request
  fails with `404` and nothing is returned — you do not get partial results for the ids that were
  valid. The error body names exactly which ids were rejected.
- **A group with no membership types is still returned**, with `membershipTypes` set to `[]`. An
  empty array means the group exists but has nothing mapped to it, which is quite different from
  the group not existing; do not collapse the two cases in your client.

## Endpoint

`GET {base_url}/api/configuration/membership-types/groups`

`{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 |
|------|------|----------|-------------|
| `groupIds` | string | No | A comma-separated list of membership type group ids to restrict the result to, for example `groupIds=MEMBER,CORPORATE`. Take each id from [Get all membership type groups](get-all-membership-type-groups.md). **Omit it, or send it empty, to return every group** — that is the documented way to fetch the whole map, not an error. The value is split on commas with no trimming, so `MEMBER, CORPORATE` sends a second id beginning with a space and fails; do not pad the list. Ids must also match the case exactly. Every id supplied must exist or the entire request returns `404`, so validate against the group list first if your ids come from user input. Repeating an id is harmless — each matching group appears once regardless. |

## Sample request

```bash title="cURL"
curl -X GET '{base_url}/api/configuration/membership-types/groups?groupIds=MEMBER,CORPORATE' \
  -H 'Authorization: Bearer {accessToken}' \
  -H 'X-Use-SSO: true'
```

## Response fields

| Field | Type | Description |
|-------|------|-------------|
| `[].id` | string | The group's key, maximum 15 characters — an operator-defined code such as `MEMBER`, not a generated identifier. This is the value you pass back as `groupIds`, and the value that identifies the group in [Get membership type group by ID](get-membership-type-group-by-id.md). |
| `[].description` | string | The group's display label, maximum 25 characters. It can be `null` on groups created before the description became mandatory; fall back to `id` if you need something to show. |
| `[].comments` | string | The group's free-text note, maximum 255 characters, drawn from the same field returned as `comments` by [Get membership type group by ID](get-membership-type-group-by-id.md). `null` when never set, which is the common case. Only the primary-language text is returned. |
| `[].membershipTypes` | array of object | Every membership type mapped to this group. `[]` when the group has nothing mapped to it — the group is still listed. A membership type may belong to more than one group, so the same entry can appear under several groups in a single response; de-duplicate by `id` if you are building a flat list. Membership types not mapped to any group do not appear anywhere in this response — use [Get all membership types](get-all-membership-types-with-optional-filtering.md) if you need the complete catalogue. |
| `[].membershipTypes[].id` | string | The membership type's key, maximum 15 characters. This is the id other endpoints expect wherever a membership type is named, including [Get membership type by ID](get-membership-type-by-id.md) and [Get membership type restrictions](get-membership-type-restrictions.md). |
| `[].membershipTypes[].description` | string | The membership type's label in the tenant's primary language, maximum 25 characters; nullable. Translated variants are in `translations` — this field is not itself localised, so do not display it directly to a member browsing in another language without checking `translations` first. |
| `[].membershipTypes[].translations` | array of object | Localised descriptions for this membership type, one entry per culture that has been translated. `[]` when the tenant has configured no translations, which is the case for most single-language tenants — it is not an error. Only the `description` is translated here; nothing else in this response is. |
| `[].membershipTypes[].translations[].type` | string | **Misleadingly named**: this is the name of the *property* the translation applies to, not a translation type. For this endpoint it is always `Description`, because description is the only translated field returned. Treat any other value as unexpected rather than writing a switch on it. |
| `[].membershipTypes[].translations[].culture` | string | The culture the translation is for, maximum 20 characters, matching a code in the platform's culture list — `cy-gb`, `en-gb`, `fr`, `de`, `es`, `pt`, `gd` and similar. **The codes are lower-case**, so compare case-insensitively rather than against a hard-coded `en-GB`. At most one entry exists per culture for a given property. |
| `[].membershipTypes[].translations[].text` | string | The translated description for that culture. It has no length limit, so it is not held to the 25-character limit that applies to `description` — size your UI accordingly. Never null for an entry that exists. |

## Sample response

```json title="200 OK"
[
  {
    "id": "MEMBER",
    "description": "Standard memberships",
    "comments": null,
    "membershipTypes": [
      {
        "id": "ADULT",
        "description": "Adult membership",
        "translations": [
          {
            "type": "Description",
            "culture": "cy-gb",
            "text": "Aelodaeth Oedolion"
          }
        ]
      },
      {
        "id": "JUNIOR",
        "description": "Junior membership",
        "translations": []
      }
    ]
  },
  {
    "id": "CORPORATE",
    "description": "Corporate memberships",
    "comments": null,
    "membershipTypes": []
  }
]
```

## Errors

| Status | Meaning | When |
|--------|---------|------|
| `404` | Not found | At least one id in `groupIds` does not match a group. The body is a plain-text string naming them: `No membership group ids found for the following IDs: X, Y`. Nothing is returned for the ids that were valid — the request fails as a whole. Wrong case, or a space after a comma, produces this too, so check the exact strings named in the message before assuming the group is missing. |
| `500` | Internal server error | An unexpected server-side failure reading the groups, their membership types or the translations. The body is empty. |
