Lists booking discount usage records with optional filtering and pagination
GET /api/configuration/booking-discount-usage
Success: 200 OK
- Products: Operator (
FOH), Consumer (CONSUMER) (any one of these products, not all) - Features: Front of House Generic Access (
FOHGENERIC), Online Bookings (ONLINEBOOK) (any one of these features, not all)
Overview
Returns a history of booking discounts that have actually been taken: one record per discounted booking line, with the promotion code used, the price before and after the discount, and the member and booking it applied to. Use it to audit promotion use or to show a member why a booking cost what it cost. It reports past use only — to find out which discounts are available, call List booking discounts for an activity and date.
At least one filter is required. Calling with no parameters at all fails with 400; there is no
way to page through every record. Filters combine with AND, and every id you filter on must exist —
filtering on a member, booking, activity or promotion code that does not exist is a 400, not an
empty result.
This endpoint is gated behind the BOOKINGDISCOUNTS feature. Without it, every call returns
403.
Results are paged with a continuation token rather than an offset. Follow links.next until it is
null; do not construct the token yourself. Because a token is emitted whenever a page comes back
full, the last page of an exact multiple of limit will hand you a link that returns an empty
data array — that is the normal way the sequence ends, not an error.
Endpoint
GET {base_url}/api/configuration/booking-discount-usage
{base_url} is the environment URL issued to your integration. See Authenticating with Gladstone APIs.
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
MemberID | integer (int32) | No | Restricts results to discounts taken on bookings this member is on. The member must exist or the call fails with 400 and Member with ID '{MemberID}' does not exist. — an existing member with no discounted bookings returns 200 with an empty data array instead. Note the capitalised parameter name. |
BookingID | integer (int32) | No | Restricts results to one booking. The booking must exist or the call fails with 400 and Booking with ID '{BookingID}' does not exist. Combines with the other filters using AND, so a booking that does not also match them returns nothing. |
ActivityID | string | No | Restricts results to bookings of one activity, matched exactly against the booking's activity id — no partial or case-insensitive matching. The activity must exist or the call fails with 400 and Activity with ID '{ActivityID}' does not exist. |
PromotionCode | string | No | Restricts results to one promotion code, matched exactly against the code string rather than an id. The code must exist or the call fails with 400 and Promotion code '{PromotionCode}' does not exist. |
DateFrom | string (date-time) | No | Keeps only records whose booking start date is on or after this date. Only the date part is used, so a time component has no effect and the boundary day is always included. May be used without DateTo, in which case there is no upper bound. |
DateTo | string (date-time) | No | Keeps only records whose booking end date is on or before this date — note it tests the end of the booking, while DateFrom tests the start, so a booking spanning midnight can fall outside a single-day range. Only the date part is used. If both are supplied and DateTo is earlier than DateFrom, the call fails with 400 and DateTo cannot be before DateFrom. Please enter a valid date. |
continuation-token | string | No | Take this from links.next of the previous response rather than building it. Its form is discount-usage-id:{id} and the next page starts strictly after that record id. Omit it for the first page. It is parsed before anything else is validated, so a malformed value fails with 400 — Invalid continuation token format when it is not two colon-separated parts, Invalid continuation token key when the part before the colon is not discount-usage-id, and Invalid continuation token value when the part after it is not an integer. Repeat the same filters alongside it; changing them mid-sequence silently changes what you are paging through. |
limit | integer (int32) | No | Maximum records in data. Defaults to 50 when omitted. It is not validated: limit=0 fails with 500, because an empty page is mistaken for a full one. There is no documented upper bound, so a very large value is not capped. |
Sample request
curl -X GET '{base_url}/api/configuration/booking-discount-usage' \
-H 'Authorization: Bearer {accessToken}' \
-H 'X-Use-SSO: true'Response fields
| Field | Type | Description |
|---|---|---|
data | array of object | The page of usage records, ordered by id ascending. Empty rather than null when nothing matches. Its length is at most limit; a length equal to limit is what causes links.next to be issued. |
data[].id | integer (int32) | Identifies the discount-usage record, and doubles as the pagination cursor — the last one on a page becomes the continuation token. It is not unique within the response: a single usage record spanning more than one sales invoice or booking member produces one entry per combination. Because the next page starts strictly after the last entry's id, a group of entries sharing an id that straddles a page boundary loses its remainder; use a limit comfortably larger than any such group. |
data[].promotionCode | string | The promotion code string that was applied, not its id. It is the same value the PromotionCode filter matches on. |
data[].priceLevelCombo | string | The price-level combination that qualified for the discount, returned as a single raw string — at most 200 characters, in a bracketed, comma-separated form. Beware: the identically named field on List booking discounts is an array of strings parsed from this same value, so the two endpoints report the same data in different shapes. Parse it yourself if you need the individual price levels. |
data[].originalPrice | number (double) | The combined price the booking would have cost without the discount, held to 2 decimal places. Compare with discountedPrice to derive the saving — the saving itself is not returned. |
data[].discountedPrice | number (double) | The combined price actually charged after the discount, held to 2 decimal places. This is the whole combination's price, not a per-person figure. |
data[].discountSalesInvoiceId | integer (int32) | The sales invoice line recording the discount itself. |
data[].memberId | integer (int32) | The member on the booking this entry relates to. Where a discounted booking covers several members, each produces its own entry against the same usage id, so summing prices across entries double-counts. |
data[].bookingId | integer (int32) | The booking the discount was applied to — the same identifier the BookingID filter takes. |
data[].bookingRef | integer (int32) | The booking's reference number as held against the member's place on it. Nullable, so expect null on older records. |
data[].bookingStartDateTime | string (date-time) | When the booking starts. This is the value DateFrom filters on. Nullable — a booking with no start recorded is still returned, and is excluded by any DateFrom filter. |
data[].bookingEndDateTime | string (date-time) | When the booking ends. This is the value DateTo filters on. Nullable, with the same consequence as for the start. |
links | object | Pagination links. Always present, even on the last page. |
links.next | string | The absolute URL of the next page: this endpoint's public URL with your filters re-applied, plus continuation-token and limit. Follow it as-is. It is null when the page came back shorter than limit, which is the only reliable end-of-sequence signal — a page that is exactly full always yields a link, even when no records remain. |
Sample response
{
"data": [
{
"id": 12345,
"promotionCode": "string",
"priceLevelCombo": "string",
"originalPrice": 10.5,
"discountedPrice": 10.5,
"discountSalesInvoiceId": 12345,
"memberId": 12345,
"bookingId": 12345,
"bookingRef": 1,
"bookingStartDateTime": "2026-08-14T19:00:00Z",
"bookingEndDateTime": "2026-08-14T19:00:00Z"
}
],
"links": {
"next": "string"
}
}Errors
| Status | Meaning | When |
|---|---|---|
400 | Bad request | One of: no filter at all — At least one of the following query parameters must be provided: MemberID, BookingID, ActivityID, PromotionCode, DateFrom, DateTo.; DateTo before DateFrom; a malformed continuation-token; or a MemberID, BookingID, ActivityID or PromotionCode that does not exist, each with its own message naming the value. The body is the plain message string, not JSON. |
403 | Forbidden | Your token does not carry the BOOKINGDISCOUNTS feature. The body is the plain string The requested operation requires Module BOOKINGDISCOUNTS to be enabled. Contact Gladstone Support to have the feature enabled for your integration. |
500 | Internal server error | Any unexpected server-side failure, with an empty body. Two causes are reachable from the request itself: limit=0, and a request that does not come through the gateway, which leaves the endpoint unable to build links.next. |