Buy a ticket

Browse as a stranger, register, hold a reservation, pay, and hold a ticket.

Owned by Customer (Guest) · 14 steps · about 15 minutes

Why this exists

This workflow belongs to the customer, which is why it is owned by the guest persona rather than by a member: it starts with a stranger who has no account, and the account is something that happens during the purchase, not before it.

The design idea that everything else hangs off is the hold. Adding tickets to your cart reserves nothing; the inventory is only taken when a reservation is created, and that reservation has a short TTL. Between those two moments the tier's reserved count goes up, the available count goes down, and if you wander off, a sweeper returns the inventory. Overselling is therefore impossible by construction rather than by luck: the check and the decrement happen in one transaction, and whoever wins the write lock wins the ticket.

Payment is deliberately the last and smallest step. By the time you pay, the price, the tax and the inventory are already pinned down and snapshotted on the order. Paying converts a hold into sold inventory and issues the ticket rows; it does not decide anything.

Before you start

  • An event that is on_sale with at least one tier that has availability.
  • Nothing else — the browsing half of this workflow needs no account.

Practise with

PersonaEmailPasswordNote
membermember@club.test member123an ordinary member; use this once you reach the checkout half
vip_membervip@club.test vip123has a VIP tab, so the house-credit payment option is available
adminadmin@club.test admin123to see the same order from the staff side

Steps 1–5 — Customer (Guest)

their manual →
  1. 1
    Start where a customer starts: the home page. Do this logged out.
    / frontend
    Expected result Upcoming events, plus any site announcement targeted at the public.
  2. 2
    Open the catalogue and find an event that is on sale.
    /events events
    Expected result Only events that are announced or on sale appear. Drafts are invisible to the public.
  3. 3
    Open the event and read the tier breakdown: what each tier costs, what is left, and which zones it opens.
    /events/{event_id} events
    Expected result Live availability per tier.
    Watch out for A tier can be visible but locked — tiers unlock on a schedule or when the previous tier sells out. Sold out is not the same as closed.
  4. 4
    Register. This is the boundary between browsing and buying.
    /register rbac
    Expected result The registration form.
  5. 5
    Submit the registration.
    /auth/register POST rbac
    Expected result You get an account, a session, and the member group automatically. You are a Member from this point on.
    Watch out for The member group is granted at registration — nobody has to approve you. Every other group in the platform is granted by an admin or by a system trigger.

Steps 6–10 — Member

their manual →

Everything from the cart onwards needs a session — the buying half is theirs.

  1. 6
    Open the event's checkout page and choose your tier and quantity.
    /events/{event_id}/checkout payments
    Expected result The tiers with live availability, your cart for this event, and the refund policy that will apply.
    Watch out for There is a per-tier maximum per order. It is a platform setting, not a suggestion.
  2. 7
    Add the tickets to your cart.
    /api/cart/items POST payments
    Expected result A cart line with the price snapshotted at the moment you added it.
    Watch out for A cart reserves NOTHING. Someone else can still buy the last ticket while it sits there. The price snapshot exists so that a price change between adding and checking out is caught and shown to you rather than silently applied.
  3. 8
    Check out. This is the moment that matters: it creates the reservation that actually holds the inventory, and an order to pay for it.
    /api/checkout POST payments
    Expected result An order awaiting payment, with a countdown.
    Watch out for This is where you find out you were too slow. If the tier sold out between your cart and here, checkout fails with an inventory error and nothing is charged — that is the oversell guard doing its job.
  4. 9
    Land on the payment page and watch the hold countdown.
    /checkout/{order_id} payments
    Expected result The order total with tax broken out, your available house credit, and the payment methods.
    Watch out for This page also accepts a reservation id: the events buy button sends you here with the reservation, and the page adopts it into an order for you. Both URLs are legitimate.
  5. 10
    Pay with a card.
    /api/orders/{order_id}/pay POST payments
    Expected result The hold is committed into sold inventory, the payment is recorded, a balanced ledger transaction is posted, and your ticket rows are issued.
    Watch out for If the hold expired while you were finding your wallet, this fails with a conflict and the inventory has already gone back on sale. Start again — nothing was charged.

Steps 11–12 — VIP Member

their manual →

Can settle the same order from house credit or the VIP tab instead of a card.

  1. 11
    As a VIP, check your purchasing power before paying: prepaid credit, earned resale balance, and your remaining tab headroom.
    /my/credit ledger
    Expected result The three balances and the tab limit.
    Watch out for Purchasing power is not one pot. Prepaid is money you put in, earned is money you made reselling, and the tab is money you have not paid yet — the platform spends them in that order.
  2. 12
    Pay the same order with house_credit instead of a card.
    /api/orders/{order_id}/pay POST payments
    Expected result The order settles from promo credit first, then prepaid, then earned, then against your tab headroom — as one balanced ledger transaction.
    Watch out for If the total exceeds what all four can cover, the payment is refused outright rather than partially settled. There is no half-paid order.

Steps 13 — Member

their manual →

Everything from the cart onwards needs a session — the buying half is theirs.

  1. 13
    Look at what you now own.
    /my/tickets payments
    Expected result Your ticket, ready to be turned into a wallet pass.
    Watch out for A ticket and a pass are different things. The ticket is the entitlement; the pass is the door credential minted from it. Getting through the door is its own workflow.

Steps 14 — Admin

their manual →

Sees the finished order from the staff side, and is the only one who can refund it.

  1. 14
    Open the same order from the staff side to see what the customer's purchase looks like to you: line items, tax, the payment, and the refund controls.
    /admin/orders/{order_id} payments
    Expected result The order with its full event history.
    Watch out for Refunding is admin-only, and it is the one action here that moves money outward. A venue manager can read this page but not refund from it.