Sell tickets on your own website, end to end
From a sales channel and a publishable key to an event list, a buy button, the hosted checkout and a confirmation on your page and your server.
The whole path, in order. Each step links to the page with the detail.
1. Have something to sell#
In Backstage create an event with at least one occurrence (a date and
time) and a price scheme (the ticket types and prices). Set it on sale.
With the API this is POST /v1/events, POST /v1/events/{eventId}/occurrences
and POST /v1/events/{eventId}/price-schemes; an MCP agent
can do the first two from a sentence.
2. Create a sales channel and a key#
A sales channel is one place you sell: your website, a partner site, the
box office. Create one of type website in Backstage (Sales channels, New),
list the event on it, and under Keys create a Publishable (browser)
key. That tlpk_ value is all the page needs.
Signing up creates the organisation with a website channel, a publishable key and a sample event already listed, so a new organisation can skip this step; see Get a key.
3. Put the elements on the page#
Plain HTML or a site builder: the HTML quickstart. React: the Vite quickstart or the Next.js quickstart. The minimum is the loader script and two tags:
<script src="https://cdn.ticketlayer.com/v1/ticketlayer.js"
data-publishable-key="tlpk_..."
data-api-url="https://live.ticketlayer.com"
data-checkout-base="https://checkout.ticketlayer.com"
data-elements-url="https://cdn.ticketlayer.com/elements/v1/ticketlayer-elements/ticketlayer-elements.esm.js"></script>
<tl-event-list></tl-event-list>
<tl-cart-badge></tl-cart-badge>
<tl-cart-drawer></tl-cart-drawer>Match your brand with the --tl-* theme tokens,
or set a theme on the channel in Backstage and the SDK applies it.
4. Checkout#
Checkout is hosted. When the customer presses Checkout in the cart, the SDK
opens the hosted box office's /embed/checkout in an iframe modal, hands it
the session so it sees the same cart, and the iframe collects contact
details and payment on its own origin. Your page never sees card data. The
iframe talks back over postMessage; the SDK turns that into
checkout:completed, checkout:error and a close.
5. Confirm on your page#
Listen for the completion and show the order:
window.ticketlayer.ready.then((tl) =>
tl.on('checkout:completed', (order) => {
location.href = '/thanks?orderId=' + encodeURIComponent(order.id);
}),
);On /thanks, <tl-order-confirmation> reads ?orderId= and renders the
reference, the lines, the totals and the tickets with QR codes and PDF links.
The customer also gets a confirmation email with the PDF passes.
6. Confirm on your server#
Register a webhook endpoint for
order.confirmed and ticket.issued. Verify Ticketlayer-Signature, then
update your CRM, mailing list or spreadsheet from the envelope. For
server-side reads (all orders for an event, a customer's history) use an
organisation API key with the Backstage API.
7. Returning customers#
<tl-login> signs a customer in with a magic link (no passwords), and
<tl-my-orders> lists their orders with the tickets. <tl-promo-code>
redeems presale and promo codes against the cart. All three are on the
Elements reference. The customer token the magic
link produces stays in the Live session and escalates it to that buyer; the
publishable key is still what authenticates every request, and
A buyer on your website draws the whole
sequence.