Migration: Baskets to Carts
Guide for moving from the Encore API’s PATCH /api/v1/baskets flow to the POST /api/v3/carts flow in the TTG Storefront API v3, the newer API. The two APIs number their versions separately.
For the full v1 basket reference, see Baskets on the legacy portal.
Endpoint Comparison
What Changed
Create with POST, not upsert with PATCH
Both APIs make the ID on the server. In v1 you sent PATCH /api/v1/baskets without a reference to create a basket, then sent the returned reference back to change it. In v3 you POST the items you want and the server returns a cart id.
Headers
Legacy baskets needed no key. channelId in the body only picked the retailer. Drop checksum; v3 has no equivalent. v3 needs the three headers in Authentication & Headers on every call.
From reservations to items
Legacy grouped tickets into reservations, each with a productId, a quantity, and opaque aggregateReference item tokens that bundled the price inside them. v3 takes a flat items list. Each item names the occurrence (date and time), the inventory item, and the price option separately.
Get inventoryItemId and priceOptionId from the inventory step (see Areas → Inventory Items). All items must belong to the same occurrence.
The hold timer is explicit
Legacy baskets returned expiredAt, and status turned expired once the hold ran out. v3 returns expiresAt (UTC) on the cart — show a countdown. When it passes, the hold is released and GET /api/v3/carts/{cartId} returns 410 CART_EXPIRED (see Cart state). Create a new cart to continue. To release a hold early, DELETE /api/v3/carts/{cartId} (idempotent, returns 204; 404 for an unknown cart, 409 CART_ALREADY_ORDERED for one that became an order).
Discounts move to a voucher endpoint
Legacy applied a coupon inline on the basket or through applyPromotion. v3 takes the code as voucherCode when the cart is created, or through a dedicated pair:
The discount shows up in the cart’s receiptLines[] and total. Which route to use, and why an access code must go on POST /carts, is in Vouchers.
Changing seats means a new cart; changing extras does not
In v3 a cart’s seats and GA are fixed once created — to change them, create a new cart and pass the old cart’s id as previousCartId: once the new cart is created, the same request attempts to release the old hold so the customer isn’t left holding two sets of inventory. The release is best-effort and never fails the create — an old cart that is unknown, expired, or already turned into an order is left alone, and the old hold then simply times out on its own.
Extras are added, changed and dropped in place on a live cart, with POST, PATCH and DELETE on /api/v3/carts/{cartId}/items — see Add Extras.
Money format
Both are minor units; v3 drops decimalPlaces — derive the scale from the currency. A cart owns its currency: it’s set at creation (base, or the body’s currency when supported) and switched with PATCH /api/v3/carts/{cartId} { "currency": "EUR" }. See Currency.
Totals come from the server
Don’t compute the total yourself. Read total and render receiptLines[] in order — each line has a sign (positive = charge, negative = credit). You’ll pass total straight through as expectedTotal at checkout.
Response Shape
New (v3)
Key differences:
idis the server-generated cart ID — stable. Store it on your server only: it reads the order (see Keep the cart ID)expiresAtis the hold deadline in UTC — drive a countdown from itoptions.extraslists add-ons you can attach; it is an empty list when the event offers noneoptions.currencieslists the currencies the cart can be priced inoptions.paymentMethodslists the methods the cart can be paid with; pick one at checkout (see Paying)
Migration Checklist
- Replace
PATCH /api/v1/basketswithPOST /api/v3/carts; let the server return thecartId - Drop
channelId; sendX-TT-API-Key,X-TT-RetailerandX-TT-Platformon every call - Convert
reservationsto a flatitemslist keyed byoccurrenceId,inventoryItemId, andpriceOptionId - Create the cart with items from one occurrence; an extra with its own schedule can name its own (see Add Extras)
- Read
expiresAtinstead ofexpiredAtand show a countdown; handle410 CART_EXPIREDby creating a new cart - Move coupons to voucher codes on
POST /api/v3/carts/{cartId}/vouchers - Replace single-reservation removal with “create a new cart with
previousCartId”, which makes a best-effort release of the old hold in the same request; useDELETEto release a hold without creating a new cart - Read
totalandreceiptLines[]from the server — don’t recompute; dropdecimalPlaces
Next Steps
With a cart held, continue the Purchase Flow:
- Add Extras (optional) —
POST /api/v3/carts/{cartId}/items - Checkout —
POST /api/v3/orders(see Checkout → Orders)