Retrieve pricing information for different members

POST /api/pricing/slots

Success: 200 OK

Overview

Prices one slot for several people at once, returning a signed pricing quote per person. Use it when more than one person is paying separately for the same session — a parent and a teenager on different memberships, say — because each of them attracts their own membership pricing and their own usage-subscription cover.

Send an array. Every item must carry the same slotReference and a different member.id; both rules are enforced and either breach fails the whole call with 400. Responses come back in pricingDetails in the order you sent them, one for one.

The call is all or nothing. Items are priced one at a time and the first failure aborts the batch, returning that item's status and message for the entire request — you never get a partial result, and you cannot tell from the response body which item failed. Price items individually if you need to know.

Where this sits in the booking flow: get a slot reference from an availability endpoint such as List all available sessions for a specific member, price it here, then create a lease and confirm the booking passing each quote through exactly as returned. Each quote is signed and timestamped, and booking creation rejects a quote that has been altered or is more than an hour old.

Discounts are handled at the group level. When the booking discounts feature is enabled for the tenant, the endpoint looks up the discounts available for the activity on that date, works out the cheapest combination across everyone in the request, and reports it in bookingDiscountDetails. The subTotal, discountTotal and grandTotal fields are always returned whether or not the feature is on; the individual pricingDetails[].totalPrice values are never discounted, so take grandTotal as the amount to collect.

Endpoint

POST {base_url}/api/pricing/slots

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

Request body

FieldTypeRequiredDescription
[].memberobjectYesThe person this quote is for. One array item per person paying separately for the same slot — for example a parent and child booking the same class on separate memberships.
[].member.idinteger (int32)YesThe member being quoted. Send 0 to price the slot for a non-member, which changes the rules: only then may you set member.priceLevelId, and pricing falls back to the site's default price level if you do not. Any other value must be a member that exists, or the request is rejected with 400 MemberID {id} does not exist. Must be unique across the array.
[].member.attendingbooleanYesWhether this person occupies a place themselves. Set false when they are only paying for guests listed in additionalBookees; their own place is then left out of the price entirely and breakdown.memberPrice is omitted from the response. If attending is false and there are no additional bookees, the request is rejected with 400 At least one bookee is required for a pricing quote. Usage-subscription cover is only considered when this is true.
[].member.priceLevelIdstringNoThe price level to charge this person at. Only valid for non-members (member.id of 0) — sending it alongside a real member id fails with 400 Price Levels cannot be specified for members, because a member's price level is resolved from their record and their membership overrides. Omit it for a non-member and the site's default price level is used. The level must exist and must permit purchase by non-members.
[].slotReferencestringYesThe slot reference being priced, taken verbatim from locations[].slots[].slotReferences.inCentre or .virtual on a sessions response such as List all available sessions. It is an opaque JSON string; do not build or edit one. Every item in the array must carry the identical value — this endpoint prices one slot for several people, not several slots. Mixed values fail with 400 All quotes in the request must use the same slotReference.
[].additionalBookeesarray of objectNoGuests this person is paying for on top of their own place, grouped by price level. Defaults to empty. Only accepted for party activities — sending any on a non-party activity fails with 400 Additional Bookees can only be specified for party activities.
[].additionalBookees[].priceLevelIdstringNoThe price level these guests are charged at. Each price level may appear once per item — repeat it and the request fails with 400 Duplicate price levels cannot be specified. The level must exist (404 otherwise) and must allow non-member purchase (400 One or more add-on price levels cannot be purchased).
[].additionalBookees[].countinteger (int32)NoHow many guests at this price level. Must be at least 1; 0 fails with 400 One or more bookees must be specified for each price level. The total across all price levels, plus one if member.attending is true, is checked against the activity's maximum attendees.
[].isMemberbooleanNoRead-only — anything you send is ignored. It is derived as true when member.id is greater than 0. Control it through member.id.
[].isMemberAttendingbooleanNoRead-only — anything you send is ignored. Computed as isMember and member.attending together. Control it through member.id and member.attending.

Sample request

cURL
curl -X POST '{base_url}/api/pricing/slots' \
  -H 'Authorization: Bearer {accessToken}' \
  -H 'X-Use-SSO: true' \
  -H 'Content-Type: application/json' \
  -d '[
  {
    "member": {
      "id": 12345,
      "attending": true,
      "priceLevelId": "string"
    },
    "slotReference": "string",
    "additionalBookees": [
      {
        "priceLevelId": "string",
        "count": 1
      }
    ],
    "isMember": true,
    "isMemberAttending": true
  }
]'

Response fields

FieldTypeDescription
pricingDetailsarray of objectOne quote per request item, in the same order — index n of this array answers index n of your request. Each quote is signed and priced independently.
pricingDetails[].memberIdinteger (int32)The member this quote is for, echoing member.id from the matching request item. 0 for a non-member quote.
pricingDetails[].totalPriceobjectWhat this one person owes for the slot, covering their own place and their guests. It is the sum of breakdown.priceLevels[].totalPrice. Discounts are not applied here — for the discounted figure use grandTotal.
pricingDetails[].totalPrice.amountnumber (double)The amount, in major units of currency. Zero when the booking is covered by a usage subscription.
pricingDetails[].totalPrice.currencystringThe currency configured for the site the activity belongs to.
pricingDetails[].breakdownobjectHow the total was arrived at, so you can show the member a line-by-line price.
pricingDetails[].breakdown.memberPriceobjectThe cost of this person's own place, split out for display. It is a view of one of the entries already in priceLevels, not an extra charge — do not add it to totalPrice. Omitted entirely when member.attending was false.
pricingDetails[].breakdown.memberPrice.priceLevelIdstringThe price level actually applied to this person. For a member it is resolved from their record and then improved on: if a membership carries a price level override that is cheaper for this slot, the cheaper one is used, so it may differ from the level you would predict.
pricingDetails[].breakdown.memberPrice.totalPricenumber (double)The cost of this person's own place, being the sum of productPrices[].amount × quantity. Forced to zero when the booking is covered by a usage subscription.
pricingDetails[].breakdown.memberPrice.productPricesarray of objectThe individual charges making up that place — a court hire and an equipment charge, for instance. One entry per priced product on the activity.
pricingDetails[].breakdown.memberPrice.productPrices[].idstringThe product being charged for.
pricingDetails[].breakdown.memberPrice.productPrices[].quantityinteger (int32)How many units of the product are needed for one place. Multiply by amount to get the line cost.
pricingDetails[].breakdown.memberPrice.productPrices[].timeBandIdstringThe time band the slot falls in, which is why the same product can cost different amounts at different times of day.
pricingDetails[].breakdown.memberPrice.productPrices[].amountnumber (double)The unit price, chosen from the in-centre or virtual price according to which slotReferences value you priced. Forced to zero when a usage subscription covers the booking.
pricingDetails[].breakdown.memberPrice.productPrices[].taxCodeIdstringThe tax code applied to this line.
pricingDetails[].breakdown.memberPrice.productPrices[].taxRatenumber (double)The rate for that tax code. amount is the gross price, so this is for display and reporting rather than something to add on.
pricingDetails[].breakdown.currencystringThe currency all amounts in the breakdown are expressed in. Always the same as totalPrice.currency.
pricingDetails[].breakdown.priceLevelsarray of objectEvery price level charged on this quote, one entry each, including the member's own — their level appears here with count incremented to include them. These entries are what totalPrice sums, so this array is the authoritative breakdown.
pricingDetails[].breakdown.priceLevels[].countinteger (int32)How many people are charged at this level: the count you sent for the matching additionalBookees entry, plus one if this is also the member's own price level and they are attending.
pricingDetails[].breakdown.priceLevels[].pricePerAdditionalBookeenumber (double)The price for one person at this level, being the sum of productPrices[].amount × quantity. Despite the name it is also the per-person price of the member's own level.
pricingDetails[].breakdown.priceLevels[].idstringThe price level identifier. Match it against memberPrice.priceLevelId to find the member's own line.
pricingDetails[].breakdown.priceLevels[].totalPricenumber (double)pricePerAdditionalBookee × count — the cost of everyone at this level. Forced to zero when a usage subscription covers the booking.
pricingDetails[].breakdown.priceLevels[].productPricesarray of objectThe individual charges making up one place at this level. Same shape and meaning as memberPrice.productPrices.
pricingDetails[].breakdown.priceLevels[].productPrices[].idstringThe product being charged for.
pricingDetails[].breakdown.priceLevels[].productPrices[].quantityinteger (int32)How many units of the product one place needs.
pricingDetails[].breakdown.priceLevels[].productPrices[].timeBandIdstringThe time band the slot falls in.
pricingDetails[].breakdown.priceLevels[].productPrices[].amountnumber (double)The unit price for the in-centre or virtual variant you priced.
pricingDetails[].breakdown.priceLevels[].productPrices[].taxCodeIdstringThe tax code applied to this line.
pricingDetails[].breakdown.priceLevels[].productPrices[].taxRatenumber (double)The rate for that tax code; amount is already gross.
pricingDetails[].paidForbyUsageSubstringThe usage subscription covering this booking, if the member holds one with uses left for the activity. When set, every amount on the quote is zeroed and no payment is due. Null when there is none, when member.attending was false, or when the activity is a party activity — party bookings can never be paid by usage subscription.
pricingDetails[].usagesRemaininginteger (int32)Uses left on that subscription. 0 means none was applied, and paidForbyUsageSub is null alongside it.
pricingDetails[].timeStampstringWhen the quote was signed, ISO-8601 with offset. It is checked when you use the quote to create a booking: a quote older than one hour is rejected, as is one dated more than ten minutes in the future. Price first, book promptly.
pricingDetails[].signaturestringAn HMAC over the whole quote, computed with a server-side key. Booking creation recomputes it and rejects the quote with The pricing quote is invalid. if anything differs, so pass the quote object back byte for byte — reordering, rounding or re-serialising the amounts will break it.
bookingDiscountDetailsarray of objectThe discounts that were applied across the whole request. Present only when the booking discounts feature is enabled for the tenant and a discount combination beat the undiscounted price; otherwise null. The discounts available for the activity on the slot's date are evaluated and the cheapest combination for the group as a whole is picked, which is why discounts sit at the top level rather than on individual quotes.
bookingDiscountDetails[].discountTypestringThe configured discount that was applied. The values are tenant configuration, so treat this as a label to display rather than a fixed set.
bookingDiscountDetails[].priceLevelComboIDinteger (int32)The identifier of the price-level combination that qualified for the discount — the configured grouping of levels, such as two adults and two juniors, that the discount was defined against.
bookingDiscountDetails[].priceLevelIDstringAlways the literal STAND, so it carries no information — do not branch on it.
bookingDiscountDetails[].discountValuenumber (double)The change in price this discount caused, calculated as discounted cost minus base cost — so it is negative. Note the opposite sign to discountTotal.
subTotalnumber (double)The sum of every pricingDetails[].totalPrice.amount, before discounts. Always returned.
discountTotalnumber (double)The total taken off, as a positive number (the negated sum of bookingDiscountDetails[].discountValue). 0 when no discount applied or the feature is off.
grandTotalnumber (double)What the group actually owes: subTotal when nothing was discounted, otherwise the discounted cost. This is the figure to show and to collect.

Sample response

200 OK
{
  "pricingDetails": [
    {
      "memberId": 12345,
      "totalPrice": {
        "amount": 10.5,
        "currency": "GBP"
      },
      "breakdown": {
        "memberPrice": {
          "priceLevelId": "string",
          "totalPrice": 10.5,
          "productPrices": [
            {
              "id": "string",
              "quantity": 1,
              "timeBandId": "string",
              "amount": 10.5,
              "taxCodeId": "string",
              "taxRate": 10.5
            }
          ]
        },
        "currency": "GBP",
        "priceLevels": [
          {
            "count": 1,
            "pricePerAdditionalBookee": 10.5,
            "id": "string",
            "totalPrice": 10.5,
            "productPrices": [
              {
                "id": "string",
                "quantity": 1,
                "timeBandId": "string",
                "amount": 10.5,
                "taxCodeId": "string",
                "taxRate": 10.5
              }
            ]
          }
        ]
      },
      "paidForbyUsageSub": "string",
      "usagesRemaining": 1,
      "timeStamp": "string",
      "signature": "string"
    }
  ],
  "bookingDiscountDetails": [
    {
      "discountType": "string",
      "priceLevelComboID": 12345,
      "priceLevelID": "string",
      "discountValue": 10.5
    }
  ],
  "subTotal": 10.5,
  "discountTotal": 10.5,
  "grandTotal": 10.5
}

Errors

StatusMeaningWhen
400Bad requestThe array is empty; the items do not all share one slotReference (All quotes in the request must use the same slotReference.); two items use the same member (Each quote in the request must use a different Member ID.); the slot reference cannot be read; member.id is not 0 and does not exist (MemberID {id} does not exist); member.priceLevelId was sent for a real member (Price Levels cannot be specified for members); additionalBookees were sent for a non-party activity; a bookee entry has count of 0; a price level is repeated; nobody is being charged (At least one bookee is required for a pricing quote); a price level does not permit purchase; the slot is not sellable at the resolved price level; or the attendee count exceeds the activity's maximum.
404Not foundA price level named in member.priceLevelId or additionalBookees[].priceLevelId does not exist: One or more price levels do not exist.
422Unprocessable entityThe activity has several pricing products on different calendars, which cannot be priced: Multiple pricing products with different calendars for activity "{activityId}" is not permitted. Fix the activity configuration; retrying will not help.
500Internal server errorAn unexpected server-side failure, including an unexpected failure while pricing. No body is returned.
503Service unavailablePricing or booking discounts could not be reached: At least one of the services is unavailable. Nothing was priced; the call is safe to retry.

This page as markdown · All pages · llms.txt