Get price level by ID
GET /api/configuration/price-levels/{priceLevelId}
Success: 200 OK
- Products: Operator (
FOH) - Features: Front of House Generic Access (
FOHGENERIC)
Overview
Returns a single price level, together with the site- and activity-specific alternative descriptions configured against it.
A price level is the operator-defined pricing band a person is charged under — adult, junior,
concession, staff and so on. It holds no money. Prices are held separately, keyed
on product, time band and price level together, so a price level is one axis of
a price lookup rather than a price in its own right. Nothing in this response is an amount. What a
price level does carry is eligibility (membersAllowed, nonMembersAllowed,
webNonMembersAllowed), an age band, and pointers to two other price levels — nextPriceLevel for
automatic progression such as a junior ageing into adult pricing, and infringementPriceLevel for
the band a member is moved onto when they breach terms. A member record carries a price level id,
and that is what ties a person to the prices they are charged.
Get the id from Get all price levels. Ids are
operator-defined and not comparable across tenants, so never hardcode one. This call gives you two
things the list does not: the alternativeDescriptions block, and a translations array that is
actually populated.
A price level id that does not exist returns 404, not 400. The body is the plain-text
message Unable to locate price level with id of {priceLevelId} — not JSON, and not a
problem-details object.
One thing this response cannot tell you: a price level has an inactive flag which is
neither filtered on nor returned. A price level the operator has retired still comes back as a
normal 200, indistinguishable from a live one.
Endpoint
GET {base_url}/api/configuration/price-levels/{priceLevelId}
{base_url} is the environment URL issued to your integration. See Authenticating with Gladstone APIs.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
priceLevelId | string | Yes | The id of the price level to read, maximum 15 characters. Take it from the id field of Get all price levels rather than constructing it. Ids are uppercase with spaces stripped, because that is how the create endpoint normalises them, so send the value exactly as the platform returned it. No inactive filtering is applied — a retired price level is still returned. |
Sample request
curl -X GET '{base_url}/api/configuration/price-levels/{priceLevelId}' \
-H 'Authorization: Bearer {accessToken}' \
-H 'X-Use-SSO: true'Response fields
| Field | Type | Description |
|---|---|---|
alternativeDescriptions | array of object | Labels that replace description for particular sites or activities — an operator running the same band under a different name at one site, for example. Empty array when none are configured, which is the common case. Each entry is one distinct label text, with the activities and sites it applies at collected under it, so a label used at three sites appears once with three entries in sites. This block is exclusive to this endpoint; the list endpoint does not return it. Overrides scoped to an activity group rather than an individual activity are deliberately excluded and will not appear here. |
alternativeDescriptions[].alternativeDescription | string | The replacement label itself, at most 25 characters — noticeably shorter than description, so expect an abbreviation rather than a full phrase. |
alternativeDescriptions[].activities | array of object | The activities this label applies to. Empty when the override is scoped only to sites. When both activities and sites are populated, they were configured as separate overrides sharing the same label text, not as an activity-and-site intersection. |
alternativeDescriptions[].activities[].id | string | The activity's id, maximum 15 characters, matching the activity ids used elsewhere in the Configuration API. |
alternativeDescriptions[].activities[].name | string | The activity's own description, included so you do not have to look the activity up separately for display. |
alternativeDescriptions[].sites | array of object | The sites this label applies to. Empty when the override is scoped only to activities. |
alternativeDescriptions[].sites[].siteId | string | The site's id, maximum 15 characters and uppercase. |
alternativeDescriptions[].sites[].name | string | The site's own description, for display. |
alternativeDescriptions[].translations | array of object | Localised versions of alternativeDescription. Duplicates are removed before the array is built, so each culture appears once even when several overrides share the label. Empty array when no translations are configured. Note this is a different set of translations from the top-level translations field, which localises description. |
alternativeDescriptions[].translations[].type | string | The property the text replaces. |
alternativeDescriptions[].translations[].culture | string | The culture the text applies to, at most 20 characters. Must be a code the platform knows about — unknown cultures are rejected when translations are written — so you will only see recognised codes here. |
alternativeDescriptions[].translations[].text | string | The translated label for that culture. No culture filtering happens server-side: you receive every configured culture and pick the one you want. |
id | string | The price level's own identifier, maximum 15 characters and unique within the tenant. This is the value you pass back as priceLevelId, and the value that appears as a member's price level elsewhere in the API. Treat it as opaque — a value such as ADULT at one operator says nothing about another. |
description | string | The operator's own label for the band, intended for display. Maximum 255 characters and never blank: an empty description is rejected when the price level is written. Localise it using translations where you have a non-default culture. |
ageRangeStart | integer (int32) | Lower bound in years of the age band this price level covers. Always present, and 0 means "no meaningful lower bound" rather than "applies from birth". Must be less than or equal to ageRangeEnd; writes reject the reverse with The starting age range is greater than the ending age range, so you will not see it violated here. |
ageRangeEnd | integer (int32) | Upper bound in years of the age band. Always present. Read it together with ageRangeStart, and with nextPriceLevel where the operator uses age progression — this is the boundary at which a member moves on. |
backColourHex | string | Background colour the operator has assigned for showing this price level on staff-facing screens, as #RRGGBB. It is converted from a legacy integer colour value, so an unset colour comes back as an empty string, not null. Purely cosmetic; nothing behavioural depends on it. The create endpoint substitutes #E0E0E0 when no colour is sent, so recently created levels are rarely blank. |
textColourHex | string | Foreground colour for the same display, as #RRGGBB, with the same empty-string-when-unset behaviour as backColourHex; the create endpoint defaults it to #000000. It is meant to be legible against backColourHex, but the platform does not check that it is. |
membersAllowed | boolean | Whether members may be charged at this price level. Derived from a legacy numeric indicator where only the value 1 counts as true, so false means "not enabled" and cannot be distinguished from "never configured". This is what filter=Member selects on in Get all price levels. |
nonMembersAllowed | boolean | Whether non-members — casual, pay-as-you-go visitors — may be charged at this price level. Derived the same way as membersAllowed, with the same "unset becomes false" behaviour. Independent of webNonMembersAllowed: a level can allow non-members at the counter without allowing them online. |
infringementPriceLevel | string | The id of the price level a member is moved onto when they breach the terms of their membership — falling into debt or missing payments, for example. null when the operator has configured none, in which case no automatic move happens. The value is validated against existing price levels when it is set, so it always resolves. Do not confuse it with nextPriceLevel; the two exist for entirely different reasons. |
nextPriceLevel | string | The id of the price level a member progresses to automatically, typically on ageing out of the band defined by ageRangeStart/ageRangeEnd. null when no progression is configured, meaning the member stays on this level indefinitely. Also validated to exist when set. |
webNonMembersAllowed | boolean | Whether non-members may be charged at this level through online channels specifically. Never null and defaults to false, so it is always present. Treat it as a narrowing of nonMembersAllowed rather than a substitute for it — it is the flag the webNonMembers=true query parameter filters on in Get all price levels. |
translations | array of object | Localised alternatives to description, and the main reason to call this endpoint rather than the list. Only the description is translated — no other field on the price level has translations — and the array is empty when the operator has configured none. |
translations[].type | string | The property the translated text replaces. Always description here, because that is the only property this endpoint returns translations for. |
translations[].culture | string | The culture the text applies to, at most 20 characters and drawn from the platform's configured culture list. Every configured culture is returned; there is no way to ask for one. |
translations[].text | string | The translated description for that culture. |
Sample response
{
"alternativeDescriptions": [
{
"alternativeDescription": "string",
"activities": [
{
"id": "string",
"name": "string"
}
],
"sites": [
{
"siteId": "string",
"name": "string"
}
],
"translations": [
{
"type": "string",
"culture": "string",
"text": "string"
}
]
}
],
"id": "string",
"description": "string",
"ageRangeStart": 1,
"ageRangeEnd": 1,
"backColourHex": "string",
"textColourHex": "string",
"membersAllowed": true,
"nonMembersAllowed": true,
"infringementPriceLevel": "string",
"nextPriceLevel": "string",
"webNonMembersAllowed": true,
"translations": [
{
"type": "string",
"culture": "string",
"text": "string"
}
]
}Errors
| Status | Meaning | When |
|---|---|---|
400 | Bad request | Not returned by this endpoint: the only lookup failure is the not-found case below. Do not treat 400 as your missing-price-level signal — see the 404 row. |
404 | Not found | No price level exists with that id. The body is the plain-text message Unable to locate price level with id of {priceLevelId}, echoing the id exactly as you sent it. |
500 | Internal server error | An unexpected server-side failure while reading the price level, its alternative descriptions or their translations. The body is empty and carries no diagnostic detail. |