Skip to content
Docs
Task

Sell tickets on your website

One script tag or one npm install puts an event list, a buy button and a hosted checkout on any site. Here is the snippet, the packages, and where the key comes from.

Ticketlayer gives you three things to build with: a drop-in script that turns plain HTML tags into a ticket shop, npm packages for React and Next.js, and two APIs (Live for buyers, Backstage for management). Card details never touch your page: checkout opens in a hosted iframe.

1. The one-line embed (HTML, Webflow, Framer, any site builder)#

Add the loader with your channel's publishable key, then place elements anywhere on the page:

<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 columns="3"></tl-event-list>

<tl-buy-tickets-button event-id="evt_..."></tl-buy-tickets-button>

<tl-event-list> lists the events your channel sells. <tl-buy-tickets-button> opens the buy flow (date, tickets, cart) and hands off to the hosted checkout. Every tag is documented in the Elements reference.

:::caution Why the loader takes more than a key The loader reads its configuration from data-* attributes on the script tag (packages/live/src/auto.ts in ticketlayer/live). It assumes no environment: data-api-url has no default and data-checkout-base falls back to your own page origin, so a working embed names both. The snippet above is the whole configuration.

AttributeRequiredWhat it is
data-publishable-keyyesThe channel's tlpk_ key. Without it the loader does nothing.
data-api-urlyesThe Live API base URL. The loader logs an error and stops without it.
data-checkout-basein practiceWhere the hosted checkout is served. Defaults to your own page origin, which has no checkout, so set it.
data-elements-urlnoThe Elements bundle. Defaults to the production CDN; name it to pin a build or to load the bundle from elsewhere.
data-elementsno"false" skips loading Elements when you bundle them yourself.
:::

The HTML quickstart is a complete page with an event list, a buy button, a cart badge and an order confirmation.

2. npm, for React, Next.js and Vite#

npm install @ticketlayer/live @ticketlayer/elements @ticketlayer/elements-react

@ticketlayer/live is the buyer-facing SDK: it creates the session, owns the cart, applies the channel theme and opens the checkout modal. @ticketlayer/elements is the web components; @ticketlayer/elements-react wraps them as React components with typed onTl... event props.

import { createLiveClient } from '@ticketlayer/live';
import { defineCustomElements, TlEventList, TlBuyTicketsButton } from '@ticketlayer/elements-react';

// Once, after hydration:
defineCustomElements();
await createLiveClient({
  baseUrl: 'https://live.ticketlayer.com',
  publishableKey: 'tlpk_...',
  checkout: { mode: 'modal', embedBaseUrl: 'https://checkout.ticketlayer.com' },
});

// Anywhere in the tree:
<TlEventList columns={3} onTlEventClick={(e) => navigate(`/events/${e.detail.eventId}`)} />
<TlBuyTicketsButton eventId="evt_..." />

For Next.js there is a server-side client, @ticketlayer/live/server, that reads listings and event detail in server components with no DOM and no session. See the Next.js quickstart and the Vite + React quickstart.

:::note Package versions All four packages are on the public npm registry: @ticketlayer/live, @ticketlayer/elements, @ticketlayer/elements-react and @ticketlayer/backstage (the management API client). The CDN build serves the same Elements bundle for pages with no build step. npm view @ticketlayer/live version is the answer for which version is current; this page does not restate it. :::

3. Get a key#

A publishable key (tlpk_...) identifies one sales channel of your organisation. It is safe in a browser: it can list what the channel sells, open a cart and start a checkout, and nothing else.

Where it comes from today: in Backstage, open Sales channels, pick the channel (or create one of type website), and under Keys create a Publishable (browser) key. A secret key (tlsk_) names the same channel and may be held only on a server; the two differ by where they may be held, not by what they sell. Both are shown once.

:::info Signing up gives you a key and something to sell Self-service signup is built (POST /v1/signup on the Backstage API). It creates your organisation in test mode with a website sales channel, a publishable key marked tlpk_test_, a sandbox payment provider that settles test orders without touching a network, and a sample event that is genuinely buyable - on sale, priced, with inventory, and listed on that channel, so it appears in GET /sales/listings for the key you were handed. The console is Backstage, at backstage.ticketlayer.com. :::

For server-side work (creating events, reading orders, registering webhooks) you use an organisation API key (tlak_...) with the Backstage API; see Keys and authentication.

What happens when someone buys#

  1. The page loads the Live SDK, which creates nothing until the customer acts: browsing uses the publishable key alone.
  2. The customer picks a date and tickets in the buy modal; the SDK creates a Live session and a cart (a timed reservation) on the first add.
  3. Checkout opens the hosted box office in an iframe modal on your page. The iframe inherits the session, so it sees the same cart, and takes payment on its own origin.
  4. On success the SDK emits checkout:completed with the order; the modal closes, and you can send the customer to a page with <tl-order-confirmation> (it reads ?orderId= from the URL) or show <tl-order-tickets> inline.
  5. Your server hears about it through webhooks (order.confirmed, ticket.issued).

Keep going#