Migration: Areas to Inventory Items
Migration: Areas to Inventory Items
Guide for migrating from the legacy GET /api/v4/products/{productId}/areas and detailed availability endpoints to the new GET /api/v3/events/{eventId}/occurrences/{occurrenceId}/inventory-items endpoint.
For the full v4 inventory reference, see Product Areas on the legacy portal.
Endpoint Comparison
What Changed
One call, not two
The legacy flow used /detailed availability to size up a performance, then /areas to pull seats and price bands. v3 replaces both with a single call per occurrence that returns every purchasable item — seats and general admission alike.
You need the occurrence id first — get it from GET /api/v3/events/{eventId}/occurrences (see Availability → Occurrences).
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:
Switch on _type for rendering and quantity logic. For the full type reference, see Inventory Types.
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 included. When there’s a discount, listPrice carries the original for a strikethrough.
Price tiers 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
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)
Key differences:
- The response is paginated — items are in
data[], with apaginationblock (limitdefault 50, max 1000). Page withlimit/offsetuntiloffset >= pagination.total. See Pagination. - The item
idis a versioned, opaque token (v1_…) — pass it whole, with apriceOptionId, toPOST /api/v3/carts.priceOptionIdhas no prefix. Never build either by hand. - Inventory item and price option IDs are ephemeral — re-fetch inventory to get fresh ones (see IDs)
inventoryVariant.idis stable across occurrences — the same seat returns the same variant ID on every date, safe to cache for seating charts
Migration Checklist
- Replace the two-call area/detailed flow with one
inventory-itemscall per occurrence - Get the occurrence
idfirst fromGET /api/v3/events/{eventId}/occurrences - Switch on
inventoryVariant._typeinstead of walking areas and price bands - Read
sellPriceas the all-in price — stop summingfaceValueandorderFee - Show
listPricestruck through when it’s present; there’s nopercentageDiscountto apply - Read each item’s
priceOptions[]for tiers; keep thepriceOptionIdfor the cart step - Drop
decimalPlaces— derive the scale from the currency code - Store the item
id(the wholev1_…token) andpriceOptionIdas opaque, ephemeral values; re-fetch to refresh them - Page the response with
limit/offsetuntil you’ve readpagination.totalitems
Next Steps
With inventory in hand, continue the Purchase Flow:
- Create Cart —
POST /api/v3/carts(see Baskets → Carts) - Checkout —
POST /api/v3/orders(see Checkout → Orders)