Ticket purchase flow

From discovery to a confirmed order, step by step.

A ticket purchase moves through discovery, event detail with its seating map, ticket selection at checkout, an optional lock, the order, and delivery tracking.

search/events → search/event → search/ticket → orders/lock → orders/create → orders/status
  (discover)     (+ map, seats)   (cart / price)  (if supported)  (confirm)      (track)

Alongside search/event you load search/map (interactive map script) and search/ticketsMap (map-ready tickets). orders/lock is optional and not supported by every ticket.

1. Find an event

Search by destination, performer or venue. Each result carries an event_id.

curl https://production.ticketero.co/api/v4/search/events \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "searchType": "performer", "performerId": "160" }'

Need IDs? Use /search/fastAutocomplete to suggest performers, venues and destinations in one call.

2. Get the event and its map

Fetch the event detail with search/event. In parallel, load the seating map and the map-ready tickets so the customer can browse availability:

  • search/event returns the event detail.
  • search/map returns the interactive map script (see Interactive maps).
  • search/ticketsMap returns the tickets shaped for the map, each with a tgID (used as ticketSku when ordering), the allowed quantities in splits, and a tgSplitsBitmap.
curl https://production.ticketero.co/api/v4/search/event \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "eventId": "5614" }'

curl https://production.ticketero.co/api/v4/search/ticketsMap \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "eventId": "5614" }'

Tickets sell only in specific quantities. Each result already includes them in splits, so pick a quantity from that array. tgSplitsBitmap is also returned because the interactive maps need it; decode it with GET /splits/{tgSplitsBitmap} only when you have a bitmap on its own.

3. Select the ticket (cart / checkout)

When the customer adds a ticket to the cart or reaches checkout, call search/ticket for the chosen ticket to get its full detail and current price.

curl https://production.ticketero.co/api/v4/search/ticket \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "eventId": "5614", "ticketSku": "5113" }'

It returns the ticket detail, including the current ticket_price, the purchasableQuantities, and required_purchase_fields (which attendee fields the order will require).

To revalidate the price right before ordering, call search/ticket again. Prices and availability change in real time, so check just before orders/create.

4. Lock the ticket (if supported)

Some tickets can be held for 5 minutes with orders/lock, which returns a requestId you pass to orders/create. Not every ticket supports locking; if the lock is not available, go straight to step 5.

curl https://production.ticketero.co/api/v4/orders/lock \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "ticketSku": 5113, "quantity": 2, "eventId": "5614" }'
{
  "success": true,
  "data": { "requestId": "9b184bb4-b926-4232-b230-c9a4fb3fed73", "ticket": { "section": "..." } },
  "message": "Lock successfully created."
}

5. Create the order

Pass the requestId from the lock to convert the hold into an order. Some tickets require attendee details (paxes), check required_purchase_fields on the ticket, and a delivery block tells us where to send the tickets.

curl https://production.ticketero.co/api/v4/orders/create \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "orderType": "ticket",
    "ticketSku": 5113,
    "quantity": 2,
    "eventId": "5614",
    "requestId": "9b184bb4-b926-4232-b230-c9a4fb3fed73",
    "delivery": { "first_name": "John", "last_name": "Doe", "email": "[email protected]", "phone": "+5215555555555" }
  }'

If the ticket does not support locking, omit requestId and orders/create books directly. When a lock is available, locking first lets you show the customer a confirmed hold before charging.

If the ticket needs attendees, include paxes (one per ticket). Use /orders/countries for nationality_country_id:

{
  "paxes": [
    { "full_name": "John Doe", "birth_date": "1990-05-24", "nationality_country_id": 1055 },
    { "full_name": "Jane Doe", "birth_date": "1993-02-14", "nationality_country_id": 1055 }
  ]
}

Attendee fields

required_purchase_fields tells you what each ticket needs. Values are strings: "1" means required, "0" means not requested. Send every flagged field on each paxes entry.

required_purchase_fields key Field in paxes[] Format
full_name_required full_name Text, first and last name
birth_date_required birth_date YYYY-MM-DD
passport_info_required passport_number Text
nationality_id_required nationality_country_id Integer, id from /orders/countries
city_of_birth_required city_of_birth Text
email_required email Email
address_required address Text, single line
phone_required phone Text, with country code

address is one text field, not an object. Send the full address on a single line: street and number, area, postal code, city and country.

{
  "paxes": [
    {
      "full_name": "John Doe",
      "email": "[email protected]",
      "address": "221B Baker Street, Marylebone, NW1 6XE, London, United Kingdom",
      "phone": "+44 20 7946 0958"
    }
  ]
}

paxes[].phone is the attendee’s phone; delivery.phone is the buyer’s delivery contact. When phone_required is “1”, send both. Read the whole object instead of assuming a fixed set of keys: new ones are added over time and must not break your parser. The venue enforces these details, so missing or wrong data can block delivery or entry.

Retry safely with an idempotency key

A timeout leaves you not knowing whether the order was created. Send an Idempotency-Key header with a unique value per order (a UUID works well) and reuse the same value on every retry of that order. A retry then never buys twice.

curl https://production.ticketero.co/api/v4/orders/create \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Idempotency-Key: 4f0c2b7e-6a2d-4c5e-9d5a-3f8e1b2c7a10" \
  -H "Content-Type: application/json" \
  -d '{ "orderType": "ticket", "ticketSku": 5113, "quantity": 2, "eventId": "5614" }'
What you send What you get
Same key, same body, first order created The original response again, with the Idempotent-Replayed: true header
Same key while the first request is still running 409 with data.code IDEMPOTENCY_IN_PROGRESS. Wait a few seconds and retry with the same key
Same key, different ticket, event or quantity 409 with IDEMPOTENCY_KEY_REUSED. Use a new key for a new order
The first request ended without a confirmed result 409 with IDEMPOTENCY_OUTCOME_UNKNOWN. Do not retry: contact support with the key

Keys are scoped to your account and kept for 24 hours. A retry that only changes paxes or delivery is the same order and returns the original response: the corrections are not applied and the order keeps the attendee data of the first request. The header in the replayed response only echoes the request of the retry. If the order is rejected (validation, credit or the venue refusing it), the key is released and you can retry with it after fixing the cause. The header is optional. If you lock first and send no header, the requestId of the lock is used as the key. The requestId must be a real lock: do not invent one to use as a key, because it can be rejected. Send the header instead.

Without any key, an identical request that arrives while the first is still running is answered with 409 IDEMPOTENCY_IN_PROGRESS. Idempotency covers ticket orders.

6. Track the order

Poll orders/status with the requestId from the orders/create response (sent as confirmation) to follow delivery. This is not the requestId of the lock.

curl https://production.ticketero.co/api/v4/orders/status \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "confirmation": "ebd5a322-283c-487d-a4fe-169b72bd7ff6" }'
{
  "success": true,
  "data": { "orderStatus": "PE", "orderStatusText": "Pending Delivery", "bookingId": "539323" },
  "message": "Order status successfully obtained."
}

Tips

  • Revalidate the price with search/ticket right before orders/create.
  • Read required_purchase_fields per ticket: it varies by ticket, and the key set grows over time.
  • Validate quantity against tgSplitsBitmap; mismatched quantities are rejected.
  • Locking is optional and not supported by every ticket. When unavailable, orders/create books directly.
  • Send an Idempotency-Key on orders/create and reuse it on every retry of the same order.
  • Two different requestIds: the one from orders/lock goes into orders/create; the one in the orders/create response goes into orders/status as confirmation.
  • Locks expire in 5 minutes. Create the order before then, or lock again.