# Retrieves system configuration settings grouped by configuration group IDs

`GET /api/configuration/system`

- **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: [Retrieves system configuration settings grouped by configuration group IDs](https://support.gladstonesoftware.cloud/reference/configuration/retrieves-system-configuration-settings-grouped-by-configuration-group-ids)

## Overview

Reads the environment's configuration settings for one or more configuration groups. A **configuration group** is a numbered category of settings — the numbers are environment data, not platform constants, so discover them with [Retrieves all available system configuration groups](retrieves-all-available-system-configuration-groups.md) rather than hard-coding them.

Two behaviours will shape everything you build on this endpoint.

**The response is filtered by your token, silently.** Three separate filters are applied after the settings are fetched, and none of them tells you anything was removed:

- Settings marked `STAFF` in `accessLevel` are returned only if your token carries the `FOH` feature. Without it you see only `PUBLIC` settings.
- Settings marked `isBeta` are returned only if your token carries the `beta` feature.
- Settings with a non-null `requiredModule` are returned only if your token's features include that exact module name, matched case-sensitively.

So two integrations asking for the same group can legitimately get different, and differently sized, results — and a setting you cannot see is indistinguishable from a setting that does not exist. If a key you expect is missing, suspect your feature claims before you suspect the configuration.

**`siteId` changes the shape of the response, not just its values.** Supply it and each setting's `value` is resolved for that site and `overrides` comes back as `null`. Omit it and `value` is the environment-wide value while `overrides` lists every site that has its own. You cannot get both a resolved value and the override list in one call.

**Group ids are all-or-nothing.** If any id in `groupIds` does not exist, or a supplied `siteId` does not exist, the whole request is `404` — you do not get partial results for the ids that were valid.

Finally, note that when the filters leave nothing to return the response is `200` with a **completely empty body**, not `200` with `[]`. A client that parses the body unconditionally will throw. See the Errors table.

## Endpoint

`GET {base_url}/api/configuration/system`

`{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 | Yes | One or more configuration group ids as a **comma-separated string** in a single parameter — `?groupIds=1,4,9`, not a repeated parameter. Take the ids from [Retrieves all available system configuration groups](retrieves-all-available-system-configuration-groups.md); they are environment data, so do not hard-code them. Despite being a query parameter it is effectively required: omitting it, or sending it empty, is rejected with `400` and the body `Invalid group IDs in the query string`. Every element must parse as an integer — one that does not fails the whole request with `400` and `Invalid group ID "{value}".` Duplicate ids are collapsed, so repeating an id does not repeat its settings. Every id must exist or the whole request is `404`, with no partial result. |
| `siteId` | string | No | Resolves each setting's `value` for one site instead of returning the environment-wide value. Use a site code from [Get all sites with optional filtering](get-all-sites-with-optional-filtering.md); matching is case-insensitive. When supplied, a setting that has an override for that site reports the override in `value`, a setting whose override is present but blank falls back to the environment value, and **`overrides` is returned as `null` for every setting** — so you cannot see other sites' overrides in the same call. Omit it to get environment-wide values plus the full `overrides` list. A site code that does not exist returns `404` for the whole request, using the same message as an unknown group id, so the two causes are indistinguishable from the response. |

## Sample request

```bash title="cURL"
curl -X GET '{base_url}/api/configuration/system' \
  -H 'Authorization: Bearer {accessToken}' \
  -H 'X-Use-SSO: true'
```

## Response fields

| Field | Type | Description |
|-------|------|-------------|
| `[].groupId` | integer (int32) | The configuration group this setting belongs to, echoing one of the ids you asked for. The response is a **flat list of settings, not a list of groups** — settings from all the groups you requested are interleaved in one array, so group by this field yourself if you need them separated. Settings from a group that returned nothing after filtering simply do not appear. |
| `[].description` | string | A short label for the setting, up to 100 characters, intended for an administration screen rather than for members. May be null. Not a substitute for `helpText`, which carries the explanation. |
| `[].configKey` | string | The setting's key, and its real identity: required, at most 50 characters, and **unique across the whole environment**, not just within its group. This is the value the single-setting endpoints take, the value you send to update a setting, and the key translations are stored against. Match on this, never on `description`. |
| `[].value` | string | The setting's value, always as a string however it is used — numbers, booleans, comma-separated lists and JSON all arrive as text, so you must know each key's expected shape to parse it. Never null. **What it resolves to depends on whether you passed `siteId`**: with a site, it is that site's override when one exists and is non-blank, otherwise the environment value; without a site, it is always the environment value regardless of any overrides. |
| `[].helpText` | string | The operator-facing explanation of what the setting does, up to 4000 characters. May be null, and is written for someone administering the system rather than for an end user. It is the only place the meaning of a key is recorded, so surface it rather than inventing your own description. |
| `[].accessLevel` | string | Who the setting is exposed to: `PUBLIC` or `STAFF`. Required, so never null. **This field also determines whether you see the setting at all** — `STAFF` settings are filtered out unless your token carries the `FOH` feature, so a response containing only `PUBLIC` values may mean your token is limited rather than that the group holds nothing else. |
| `[].allowOverrides` | boolean | Whether this setting may be given a different value per site. `false` means the environment value is the only one there can be, and an attempt to write a site override for it should be expected to fail. It describes what is permitted, not what exists — check `overrides` for that. |
| `[].isBeta` | boolean | Whether the setting controls a feature still in beta. Always `false` in practice for most callers, because settings with this set are filtered out of the response entirely unless your token carries the `beta` feature — so seeing `true` here means you have that feature. |
| `[].requiredModule` | string | The licensed module this setting belongs to, up to 40 characters, or `null` for a setting that needs no module. **Doubles as a visibility filter**: a non-null value means the setting is only returned when your token's features include this exact string, compared case-sensitively. A setting you never see in the response may be gated on a module you do not have. |
| `[].overrides` | array of object | Every site-specific value recorded for this setting. **`null` — not an empty array — whenever you passed `siteId`**, because the endpoint resolves rather than lists in that mode; guard for null before iterating. When you omit `siteId`, it is an array, empty when no site has its own value. A site absent from this list uses the environment-wide `value`. |
| `[].overrides[].siteId` | string | The site whose value differs, matching the `id` used by the site endpoints. Casing is as stored, so compare case-insensitively. |
| `[].overrides[].value` | string | The value that applies at that site instead of the setting's environment-wide `value`, again always a string. A blank value here does not override: the resolution logic treats an empty override as absent and falls back to the environment value. |
| `[].translations` | array of object | Localised text for this setting, looked up by `configKey`. Always present and never null; an empty array `[]` where nothing has been translated. Each entry translates one property into one culture, and coverage is not guaranteed — fall back to the base `description` or `helpText`. These translate the setting's own labels, not its `value`. |
| `[].translations[].type` | string | Which property of the setting this entry translates, matching the field name — for example `Description` or `HelpText`. Up to 50 characters, stored verbatim from whatever the translation import supplied, so treat an unrecognised value as data to ignore. |
| `[].translations[].culture` | string | The culture the `text` is written in, up to 20 characters. Compare it against the codes from [Retrieves all system-supported languages](retrieves-all-system-supported-languages-and-localization-settings.md) rather than assuming a fixed set. |
| `[].translations[].text` | string | The translated value, to be used in place of the base property named by `type` for the matching `culture`. Unbounded length. |

## Sample response

```json title="200 OK"
[
  {
    "groupId": 12345,
    "description": "string",
    "configKey": "string",
    "value": "string",
    "helpText": "string",
    "accessLevel": "string",
    "allowOverrides": true,
    "isBeta": true,
    "requiredModule": "string",
    "overrides": [
      {
        "siteId": "string",
        "value": "string"
      }
    ],
    "translations": [
      {
        "type": "string",
        "culture": "string",
        "text": "string"
      }
    ]
  }
]
```

## Errors

| Status | Meaning | When |
|--------|---------|------|
| `200` | OK | Success. **When no settings survive the group and feature filters, the response is `200` with a completely empty body** rather than `200` with `[]`. Check for an empty body before parsing, and remember this is also what you get when every setting in the group was filtered out by your token's features. |
| `400` | Bad request | `groupIds` was missing or empty. Body: `Invalid group IDs in the query string`. |
| `400` | Bad request | An element of `groupIds` is not an integer. Body: `Invalid group ID "{value}".`, naming the first offending element. The whole request fails; valid ids in the same list are not processed. |
| `404` | Not found | At least one group id does not exist, **or** the supplied `siteId` does not exist. Body: `Either the site ID {siteId} or at least one group ID in {groupIds} was not found `. The message deliberately does not say which, so check both — and note it is all-or-nothing: no settings are returned for the ids that were valid. |
| `500` | Internal server error | An unexpected server-side failure reading the settings, their overrides or their translations. The response has no body. There is nothing in the request to correct, so retry rather than adjust it. |
