Skip to navigation

Migration: Areas to Inventory Items

Guide for moving from the Encore API’s GET /api/v4/products/{productId}/areas and detailed availability endpoints to GET /api/v3/events/{eventId}/occurrences/{occurrenceId}/inventory-items in the TTG Storefront API v3, the newer API. The two APIs number their versions separately.

For the full v4 inventory reference, see Product Areas on the legacy portal.

Endpoint Comparison

Legacy (v4)New (v3)
MethodGETGET
Path/api/v4/products/{productId}/areas (+ /detailed availability)/api/v3/events/{eventId}/occurrences/{occurrenceId}/inventory-items
AuthNone — the optional affiliateId header only picks the retailerX-TT-API-Key, X-TT-Retailer and X-TT-Platform headers
Calls per occurrenceTwo — detailed availability, then areasOne
ShapeAreas → groupings → price bandsFlat list of items, each typed

What Changed

One call, not two

The legacy flow used /detailed availability to size up a date and time, then /areas to pull seats and price bands. v3 replaces both with a single call per occurrence (one date and time of an event) that returns every purchasable item — seats and general admission alike.

# Legacy — two calls
GET /api/v4/availability/products/123/quantity/2/from/20260315/to/20260315/detailed
GET /api/v4/products/123/areas?date=20260315&time=1930&quantity=2
# New — one call
GET /api/v3/events/123/occurrences/456/inventory-items?quantity=2

Legacy needed no key. v3 needs the three headers in Authentication & Headers on every call.

You need the occurrence id first — get it from GET /api/v3/events/{eventId}/occurrences (see Availability → Occurrences).

The legacy quantity carries over as the optional ?quantity= query parameter. Seats a party of that size can’t pick can still be listed: they carry selectionBlocked, or no selectionGroup, so show them as unavailable. See Seats for a party. Call again when the customer changes the ticket count.

From areas and price bands to typed items

Legacy nested seats inside areas, and areas inside price bands, controlled by groupBy (lump, priceBand). v3 returns a flat list. Each item carries an inventoryVariant with a _type that tells you what it is:

_typeLegacy equivalentQuantity rule
AssignedSeatA seat inside an area (row, number)Always 1
GeneralAdmissionAn unreserved area / lump1 to quantityAvailable, within the event’s orderLimit

Switch on _type for rendering and quantity logic. A gift-card event’s items are GiftCard, and new types may be added. For the full type reference, see Inventory Types; skip any _type you don’t recognize.

Pricing: all-in sellPrice, not face value plus fees

Legacy split price into faceValue, orderFee, and an includesBookingFee flag, with a percentageDiscount on the side. You had to add them up. v3 gives you sellPrice — the all-in price the customer pays, fees and tax included. When there’s a discount, listPrice carries the original for a strikethrough.

Legacy (v4)New (v3)Notes
faceValue + orderFeesellPriceAll-in, fees and tax included — nothing to add up
percentageDiscountlistPrice presentShow listPrice struck through next to sellPrice
salePrice { value, currency, decimalPlaces }sellPrice { amount, currency }Minor units; get the scale from the currency
One price per bandpriceOptions[] (Adult, Child, Senior…)Each item can carry several price options

Price bands become price options

Legacy price bands were a property of the area. v3 attaches priceOptions[] to each item — one entry per category (Adult, Child, Senior). Each has its own id, which you pass when you add the item to a cart.

Money format

// Legacy
{ "salePrice": [{ "value": 2500, "currency": "GBP", "decimalPlaces": 2 }] }
// New
{ "sellPrice": { "amount": 2500, "currency": "GBP" } }

Both are minor units, but v3 drops decimalPlaces — derive the scale from the currency code with your i18n library. See Money Format.

Seat attributes are always on

Legacy hid seat attributes behind includeSeatsAttributes=true. v3 always returns attributes[], each tagged with a category (POSITIVE, NEGATIVE, ACCESSIBILITY, NEUTRAL, FEATURED) so you can badge them consistently. See Inventory Types.

Response Shape

New (v3)

{
"data": [
{
"id": "v1_eyJwcm92aWRlcklkIjoxMDAwLCJzZWF0SWQiOiJPUkNIRVNUUkEtQS0xMDEifQ",
"inventoryVariant": {
"_type": "AssignedSeat",
"id": "ORCHESTRA-A-101",
"name": "Orchestra A 101",
"section": "Orchestra",
"row": "A",
"seat": "101",
"attributes": []
},
"quantityAvailable": 1,
"priceOptions": [
{
"id": "eyJwcm92aWRlckNvZGUiOiJGVUxMUFJJQ0UiLCJob2xkQ29kZSI6IjE1NzM5In0",
"category": { "name": "Adult" },
"listPrice": { "amount": 15000, "currency": "USD" },
"sellPrice": { "amount": 12500, "currency": "USD" }
}
]
}
],
"pagination": { "limit": 50, "offset": 0, "total": 1 }
}

Key differences:

  • The response is paginated — items are in data[], with a pagination block. See Pagination.
  • The item id is a versioned, opaque token (v1_…) — pass it whole, with a priceOptionId, to POST /api/v3/carts. priceOptionId has no prefix. Never build either by hand.
  • Inventory item and price option IDs are tokens — the same seat, price and rate code give the same token. Still re-fetch inventory before you build a cart: prices and price options can change.
  • inventoryVariant.id is stable across occurrences — the same seat returns the same variant ID on every date, safe to cache for seating charts

Migration Checklist

  1. Send X-TT-API-Key, X-TT-Retailer and X-TT-Platform on every call
  2. Replace the two-call area/detailed flow with one inventory-items call per occurrence
  3. Get the occurrence id first from GET /api/v3/events/{eventId}/occurrences
  4. Switch on inventoryVariant._type instead of walking areas and price bands
  5. Read sellPrice as the all-in price — stop summing faceValue and orderFee
  6. Show listPrice struck through when it’s present; there’s no percentageDiscount to apply
  7. Read each item’s priceOptions[] for its prices; keep the priceOptionId for the cart step
  8. Drop decimalPlaces — derive the scale from the currency code
  9. Treat the item id (the whole v1_… token) and priceOptionId as opaque; re-fetch inventory before each cart, because prices can change
  10. Page with limit / offset until offset >= pagination.total

Next Steps

With inventory in hand, continue the Purchase Flow:

  1. Create Cart — POST /api/v3/carts (see Baskets → Carts)
  2. Checkout — POST /api/v3/orders (see Checkout → Orders)