# Ticketlayer > Ticketlayer is a ticketing platform. Sell tickets on any website with one script tag or an npm package (the Live SDK and Elements), manage events, orders and customers through the Backstage API, and receive webhooks when orders and tickets change. API version: 2026-06-13 (dated version, sent as the TL-Version header; additive changes never change it). Generated 2026-09-14 from https://docs.ticketlayer.com. Key facts: - Browser code uses a publishable key (tlpk_...) from a sales channel; it is safe to expose. Server code uses an organisation API key (tlak_...); never ship it to a browser. - The CDN loader (https://cdn.ticketlayer.com/v1/ticketlayer.js) boots from data-* attributes and registers the tl-* web components; today data-api-url and data-checkout-base must be set explicitly (see the HTML quickstart). - Elements bind to window.Ticketlayer, which createLiveClient() publishes. Element tag names, attribute names and tl* event names are part of the contract. - Card details never touch your page: checkout runs in the hosted checkout (an iframe modal on embeds). - Only @ticketlayer/backstage is on npm today; @ticketlayer/live, @ticketlayer/elements and @ticketlayer/elements-react publish once their release workflows run. Use the CDN build until then. --- # Sell tickets on your website Source: https://docs.ticketlayer.com/guides/getting-started/welcome 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: ```html ``` `` lists the events your channel sells. `` opens the buy flow (date, tickets, cart) and hands off to the hosted checkout. Every tag is documented in the [Elements reference](https://docs.ticketlayer.com/reference/elements/). Note (Two more attributes are required today): The loader reads its configuration from `data-*` attributes on the script tag (`live-sdk/src/auto.ts`). Until the production hostnames exist, the defaults do not point anywhere useful, so a working embed against staging is: ```html ``` | Attribute | Required | What it is | |---|---|---| | `data-publishable-key` | yes | The channel's `tlpk_` key. Without it the loader does nothing. | | `data-api-url` | yes | The Live API base URL. The loader logs an error and stops without it. | | `data-checkout-base` | in practice | Where the hosted checkout is served. Defaults to your own page origin, which has no checkout, so set it. | | `data-elements-url` | on staging | The Elements bundle. Defaults to the production CDN, so staging needs it spelled out. | | `data-elements` | no | `"false"` skips loading Elements when you bundle them yourself. | The plan is for the two URL attributes to default to production so the snippet has one attribute; that is tracked in the platform plan and not done. The [HTML quickstart](https://docs.ticketlayer.com/guides/quickstarts/html) 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 ```bash 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. ```tsx import { createLiveClient } from '@ticketlayer/live'; import { defineCustomElements, TlEventList, TlBuyTicketsButton } from '@ticketlayer/elements-react'; // Once, after hydration: defineCustomElements(); await createLiveClient({ baseUrl: 'https://live.staging.t9r.dev', publishableKey: 'tlpk_...', checkout: { mode: 'modal', embedBaseUrl: 'https://hbo.staging.t9r.dev' }, }); // Anywhere in the tree: navigate(`/events/${e.detail.eventId}`)} /> ``` 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](https://docs.ticketlayer.com/guides/quickstarts/nextjs) and the [Vite + React quickstart](https://docs.ticketlayer.com/guides/quickstarts/vite-react). Note (Which packages are on npm today): Only **`@ticketlayer/backstage`** (the management API client) is on the public npm registry. `@ticketlayer/live`, `@ticketlayer/elements` and `@ticketlayer/elements-react` are built in their repositories and publish once their release workflows run; an `npm install` of them fails right now. The CDN build is deployed and is what the quickstarts fall back to. ## 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. Secret keys (`tlsk_`) are for servers and are shown once. Note (Self-serve sign-up is planned, not built): There is no public sign-up yet: organisations are created by Ticketlayer, and Backstage on staging (`backstage.staging.t9r.dev`) is reachable only from the team tailnet. If you are building against Ticketlayer now, ask the team for an organisation and a publishable key. The planned flow (`ticketlayer.com/start`: register, an organisation with a default website channel and key, a sample event, test mode) is described in the platform plan and will replace this paragraph when it ships. 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](https://docs.ticketlayer.com/guides/getting-started/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 `` (it reads `?orderId=` from the URL) or show `` inline. 5. Your server hears about it through [webhooks](https://docs.ticketlayer.com/guides/integrations/webhooks) (`order.confirmed`, `ticket.issued`). ## Keep going - [HTML quickstart](https://docs.ticketlayer.com/guides/quickstarts/html), [Next.js quickstart](https://docs.ticketlayer.com/guides/quickstarts/nextjs), [Vite + React quickstart](https://docs.ticketlayer.com/guides/quickstarts/vite-react) - [Elements reference](https://docs.ticketlayer.com/reference/elements/): every tag, attribute, event and theme token - [Live API](https://docs.ticketlayer.com/api/live/) and [Backstage API](https://docs.ticketlayer.com/api/backstage/) references, and the OpenAPI documents at [/openapi/live.json](https://docs.ticketlayer.com/openapi/live.json) and [/openapi/backstage.json](https://docs.ticketlayer.com/openapi/backstage.json) - [Connect an AI agent](https://docs.ticketlayer.com/guides/agents/mcp) to manage events from Claude Code, Cursor or Claude Desktop - Building with an AI tool? Point it at [/llms.txt](https://docs.ticketlayer.com/llms.txt). --- # HTML quickstart Source: https://docs.ticketlayer.com/guides/quickstarts/html One file, no build tools. Works the same inside Webflow, Framer, Squarespace or any site builder that lets you add a script tag and custom HTML. ## What you need - A publishable key (`tlpk_...`) for a sales channel. See [Get a key](https://docs.ticketlayer.com/guides/getting-started/welcome#3-get-a-key). - At least one event listed on that channel (in Backstage: the event's listing on the channel, with an occurrence and a price scheme on sale). ## The page ```html Tickets

What's on

Featured

``` And `thanks.html`, with the same script tag in its head: ```html ``` ## What each line does | Piece | Behaviour | |---|---| | The script tag | Boots a Live client from its `data-*` attributes, publishes it on `window.Ticketlayer` for the elements, injects the Elements bundle, installs the buy modal and the hosted checkout modal. Idempotent; a no-op without a key. | | `` | Fetches the channel's listings and renders a card per event. Attributes: `columns`, `limit`, `category`. Event: `tlEventClick` with `{ eventId }`. | | `` | Emits `tlClick` and opens the buy modal (date, then tickets) for `event-id`. Attributes include `occurrence-id`, `label`, `price`, `state`, `variant`, `size`. | | `` and `` | The badge shows the item count and opens the drawer; the drawer holds `` with a Checkout button that opens the hosted checkout. | | `checkout:completed` | Emitted on the Live client when the checkout iframe reports success. The payload is the order (`id`, `orderNumber`). | | `` | Order reference, lines, totals and the tickets with QR codes and PDF links. Finds the order from `order-id`, then `?orderId=` in the URL, then the `checkout:completed` event. | ## Production hostnames When the production CDN, Live API and hosted checkout are live the script tag will be: ```html ``` `data-elements-url` is only needed on staging, because the SDK's default Elements URL already points at the production CDN. The planned change to default `data-api-url` and `data-checkout-base` to production would reduce this to the key alone. ## Next - [Elements reference](https://docs.ticketlayer.com/reference/elements/) for every attribute and event - [Theming](https://docs.ticketlayer.com/reference/elements/#theming): the `--tl-*` tokens - [Webhooks](https://docs.ticketlayer.com/guides/integrations/webhooks) to hear about orders on your server --- # Next.js quickstart Source: https://docs.ticketlayer.com/guides/quickstarts/nextjs Two halves. On the **server**, `@ticketlayer/live/server` reads listings, event detail and the theme with plain `fetch`, no DOM, no session, so your pages render with real data and cache however Next.js caches. In the **browser**, `@ticketlayer/live` plus the Elements handle the buy flow, the cart and the hosted checkout. ## Install ```bash npm install @ticketlayer/live @ticketlayer/elements @ticketlayer/elements-react ``` Note (Not on npm yet): These three packages publish once their release workflows run; today the install fails. The code below is the intended shape (it is what the hosted box office, itself a Next.js app, does). To try it before the packages publish, depend on the repositories directly (`"@ticketlayer/live": "github:ticketlayer/live-sdk"` and build them), or use the [HTML quickstart](https://docs.ticketlayer.com/guides/quickstarts/html) script tag in `app/layout.tsx` and plain `` tags in your JSX. ## Environment ```bash title=".env.local" LIVE_API_INTERNAL_URL=https://live.staging.t9r.dev NEXT_PUBLIC_LIVE_API_URL=https://live.staging.t9r.dev NEXT_PUBLIC_CHECKOUT_BASE=https://hbo.staging.t9r.dev LIVE_PUBLISHABLE_KEY=tlpk_... NEXT_PUBLIC_LIVE_PUBLISHABLE_KEY=tlpk_... ``` The publishable key is public by design, so it can be in both a server and a `NEXT_PUBLIC_` variable. Never put an organisation API key (`tlak_`) in a `NEXT_PUBLIC_` variable. ## Server: the catalogue client ```ts title="lib/live.ts" import { createServerClient } from '@ticketlayer/live/server'; export const live = createServerClient({ apiUrl: process.env.LIVE_API_INTERNAL_URL!, publishableKey: process.env.LIVE_PUBLISHABLE_KEY!, // Let Next's fetch cache own revalidation instead of the SDK's TTL cache. cache: false, }); ``` ```tsx title="app/page.tsx" import Link from 'next/link'; import { live } from '@/lib/live'; export default async function HomePage() { const listings = await live.events.list({ fetchInit: { next: { revalidate: 300, tags: ['events'] } }, }); return (

What's on

    {listings.map((l) => (
  • {l.name}
  • ))}
); } ``` ```tsx title="app/events/[id]/page.tsx" import { notFound } from 'next/navigation'; import { LiveAPIError } from '@ticketlayer/live/server'; import { live } from '@/lib/live'; import { BuyButton } from '@/components/BuyButton'; export default async function EventPage({ params }: { params: Promise<{ id: string }> }) { const { id } = await params; try { const [event, theme] = await Promise.all([ live.events.get(id, { fetchInit: { next: { revalidate: 300, tags: ['events', `event:${id}`] } } }), live.theme.get({ fetchInit: { next: { revalidate: 300, tags: ['theme'] } } }), ]); return (

{event.name}

); } catch (err) { if (err instanceof LiveAPIError && err.status === 404) notFound(); throw err; } } ``` The server client's surface: `events.list()`, `events.get(id)`, `theme.get()`, `session.create()` (a Live session, for a WebView checkout), `get(path)` for any other Live GET, and `clearCache()`. Every call takes `{ fetchInit }` to pass framework fetch options through. ## Browser: boot the SDK and register Elements once ```tsx title="components/TicketlayerProvider.tsx" 'use client'; import { useEffect } from 'react'; import { createLiveClient } from '@ticketlayer/live'; import { defineCustomElements } from '@ticketlayer/elements-react'; export function TicketlayerProvider({ children }: { children: React.ReactNode }) { useEffect(() => { // Register the custom elements after hydration (avoids SSR mismatches). defineCustomElements(); createLiveClient({ baseUrl: process.env.NEXT_PUBLIC_LIVE_API_URL!, publishableKey: process.env.NEXT_PUBLIC_LIVE_PUBLISHABLE_KEY!, // Third-party pages open the hosted checkout in an iframe modal. checkout: { mode: 'modal', embedBaseUrl: process.env.NEXT_PUBLIC_CHECKOUT_BASE! }, }).then((tl) => { tl.on('checkout:completed', (order: { id: string }) => { window.location.href = `/thanks?orderId=${encodeURIComponent(order.id)}`; }); }); }, []); return <>{children}; } ``` Mount it in `app/layout.tsx` around `{children}`. `createLiveClient` publishes the client on `window.Ticketlayer`, which is how every Element finds it; there is no prop to pass. ```tsx title="components/BuyButton.tsx" 'use client'; import { TlBuyTicketsButton } from '@ticketlayer/elements-react'; export function BuyButton({ eventId }: { eventId: string }) { return console.log('opening buy flow')} />; } ``` ```tsx title="app/thanks/page.tsx" 'use client'; import { TlOrderConfirmation } from '@ticketlayer/elements-react'; // reads ?orderId= from the URL itself. export default function ThanksPage() { return ; } ``` Elements are browser-only: every component that renders one needs `'use client'`. Server components should render data from the server client and hand off to a client component for anything interactive. ## Next - [Elements reference](https://docs.ticketlayer.com/reference/elements/): `TlEventList`, `TlCartBadge`, `TlCartDrawer`, `TlMyOrders` and the rest - [Live SDK reference](https://docs.ticketlayer.com/reference/sdk/live) for `createLiveClient` options and the `TicketlayerLive` facade - [Webhooks](https://docs.ticketlayer.com/guides/integrations/webhooks) to update your own database when an order confirms --- # Vite + React quickstart Source: https://docs.ticketlayer.com/guides/quickstarts/vite-react A client-only React app: no server, no backend, no database. The publishable key is public, the cart lives in the Live session, and payment happens in the hosted checkout, so a static bundle is all you deploy. ## Install ```bash npm create vite@latest my-tickets -- --template react-ts cd my-tickets npm install @ticketlayer/live @ticketlayer/elements @ticketlayer/elements-react ``` ```bash title=".env" VITE_LIVE_API_URL=https://live.staging.t9r.dev VITE_CHECKOUT_BASE=https://hbo.staging.t9r.dev VITE_TL_PUBLISHABLE_KEY=tlpk_... ``` Note (Not on npm yet): `@ticketlayer/live`, `@ticketlayer/elements` and `@ticketlayer/elements-react` publish once their release workflows run; today the install fails. Until then, the section [Without the npm packages](#without-the-npm-packages) below is what works, and it is the path to give an AI builder. ## Boot once ```tsx title="src/main.tsx" import React from 'react'; import ReactDOM from 'react-dom/client'; import { createLiveClient } from '@ticketlayer/live'; import { defineCustomElements } from '@ticketlayer/elements-react'; import App from './App'; defineCustomElements(); createLiveClient({ baseUrl: import.meta.env.VITE_LIVE_API_URL, publishableKey: import.meta.env.VITE_TL_PUBLISHABLE_KEY, checkout: { mode: 'modal', embedBaseUrl: import.meta.env.VITE_CHECKOUT_BASE }, }).then((tl) => { tl.on('checkout:completed', (order: { id: string }) => { window.location.href = `/thanks?orderId=${encodeURIComponent(order.id)}`; }); }); ReactDOM.createRoot(document.getElementById('root')!).render( , ); ``` ## Use the elements ```tsx title="src/App.tsx" import { useState } from 'react'; import { TlEventList, TlBuyTicketsButton, TlCartBadge, TlCartDrawer, TlOrderConfirmation, } from '@ticketlayer/elements-react'; export default function App() { const [eventId, setEventId] = useState(null); const orderId = new URLSearchParams(window.location.search).get('orderId'); if (orderId) return ; // reads ?orderId= itself return (

What's on

) => setEventId(e.detail.eventId)} /> {eventId && (

Get tickets

)}
); } ``` Every wrapper renders the matching custom element and turns each `tl*` event into an `onTl*` prop with the `CustomEvent` as its argument. Attributes are camelCased props (`eventId`, `occurrenceId`, `fullWidth`). ## Without the npm packages Load the CDN build from `index.html` and write the tags directly. This is what works today and is also the smallest thing an AI tool can generate correctly. ```html title="index.html" ``` ```tsx title="src/App.tsx" import { useEffect, useRef } from 'react'; export default function App() { const list = useRef(null); useEffect(() => { const el = list.current; const onClick = (e: Event) => console.log((e as CustomEvent<{ eventId: string }>).detail.eventId); el?.addEventListener('tlEventClick', onClick); return () => el?.removeEventListener('tlEventClick', onClick); }, []); return ( <> ); } ``` TypeScript needs to know the tags exist: ```ts title="src/tl-elements.d.ts" import type { DetailedHTMLProps, HTMLAttributes } from 'react'; type TlProps = DetailedHTMLProps, HTMLElement> & Record; declare module 'react' { namespace JSX { interface IntrinsicElements { 'tl-event-list': TlProps; 'tl-buy-tickets-button': TlProps; 'tl-cart-badge': TlProps; 'tl-cart-drawer': TlProps; 'tl-order-confirmation': TlProps; } } } ``` Attributes on raw tags are strings (`columns="3"`), and events are attached with `addEventListener` because React does not bind custom events on intrinsic elements. The `checkout:completed` hook is the same as in the HTML quickstart: `window.ticketlayer.ready.then((tl) => tl.on('checkout:completed', ...))`. ## Next - [Elements reference](https://docs.ticketlayer.com/reference/elements/) for every wrapper, prop and event - [Theming](https://docs.ticketlayer.com/reference/elements/#theming): set `--tl-*` tokens in your CSS - [Webhooks](https://docs.ticketlayer.com/guides/integrations/webhooks) if you later add a server --- # Keys and authentication Source: https://docs.ticketlayer.com/guides/getting-started/authentication Ticketlayer has three kinds of credential. Pick by where the code runs. | Credential | Prefix | Where it runs | What it can do | Header | |---|---|---|---|---| | Publishable key | `tlpk_` | Browsers, mobile apps, site builders | Read what one sales channel sells, create a cart and start checkout through the [Live API](https://docs.ticketlayer.com/api/live/) | `Authorization: Bearer tlpk_...` (or `X-Channel-Key`) | | Organisation API key | `tlak_` | Your server | Everything the key's scopes allow on the [Backstage API](https://docs.ticketlayer.com/api/backstage/): events, orders, customers, webhooks, embed sessions | `Authorization: Bearer tlak_...` plus `X-Ticketlayer-Org: ` | | Staff access token | JWT | Backstage, staff tools, MCP agents | Whatever the signed-in person's role allows | `Authorization: Bearer ` plus `X-Ticketlayer-Org: ` | A channel also has **secret keys** (`tlsk_`), server-only siblings of the publishable key for a backend that talks to the sales surface on a customer's behalf. They are shown once when created and must never reach a browser. ## Publishable keys (browser) The Live SDK and the CDN loader take the key once and send it on every request; you do not write the header yourself. ```html ``` ```ts import { createLiveClient } from '@ticketlayer/live'; const tl = await createLiveClient({ baseUrl: 'https://live.staging.t9r.dev', publishableKey: 'tlpk_...' }); ``` Calling the Live API directly: ```bash curl https://live.staging.t9r.dev/sales/listings \ -H "Authorization: Bearer tlpk_..." ``` Browsing needs nothing more. The first cart creates a Live session; the SDK holds its id and sends it as `X-Live-Session` (or a cookie on a hosted storefront). Customer sign-in is a magic link: `POST /sales/customer-auth/magic-link`, then `POST /sales/customer-tokens` with the code; `` does both. **Where to get one:** Backstage, Sales channels, the channel, Keys, Create key, Publishable (browser). Self-serve sign-up is not built yet; see [Get a key](https://docs.ticketlayer.com/guides/getting-started/welcome#3-get-a-key). ## Organisation API keys (server) An organisation API key is created by a staff user in Backstage (or with `POST /v1/api-keys` while signed in) with a name and a list of scopes such as `events.write`, `orders.read`, `saleschannels.write`. The key material is returned once. ```bash curl https://api.staging.t9r.dev/v1/events \ -H "Authorization: Bearer tlak_..." \ -H "X-Ticketlayer-Org: your-org-slug" ``` With the SDK: ```ts import { BackstageClient } from '@ticketlayer/backstage'; const backstage = new BackstageClient({ baseUrl: 'https://api.staging.t9r.dev', accessToken: process.env.TICKETLAYER_API_KEY, // tlak_... organisationSlug: 'your-org-slug', }); const { events } = await backstage.events.list({ limit: '20' }); ``` Rules the API applies to a `tlak_` bearer: - The key is looked up by hash; revoked or expired keys get `401`. - The `X-Ticketlayer-Org` header must name the key's own organisation. - Each route checks the key's scopes; a missing scope is `404`, not `403` (the platform never confirms that something exists to a caller who cannot see it). - Routes that are for signed-in people only (`/v1/me/*`, `/v1/api-keys`) refuse API keys. API keys also mint **embed sessions** (`POST /v1/embed/sessions`): short-lived tokens pinned to one account that let you mount Backstage widgets in your own app with `@ticketlayer/backstage/embed`. See the Backstage SDK [getting started](https://docs.ticketlayer.com/reference/sdk/typescript/getting-started). ## Staff tokens (Stagedoor OAuth) People sign in through **Stagedoor**, Ticketlayer's identity service, with OAuth 2.1 (authorization code + PKCE). Backstage, the box office and the [MCP server](https://docs.ticketlayer.com/guides/agents/mcp) all use it. A third-party app registers a client with Stagedoor (MCP clients do this automatically through Dynamic Client Registration), sends the person to `/oauth/authorize`, and exchanges the code for an access token that carries the organisation they chose at login. Tokens are short-lived and refreshed with the refresh token. The API also documents `POST /v1/auth/login` (email and password). It exists for first-party tooling; integrations should use API keys for servers and Stagedoor for people. ## Environments | | Staging | Production | |---|---|---| | Backstage API | `https://api.staging.t9r.dev/v1` | `https://api.ticketlayer.com/v1` (not yet deployed) | | Live API | `https://live.staging.t9r.dev` | `https://live.ticketlayer.com` (not yet deployed) | | Hosted checkout | `https://hbo.staging.t9r.dev` | `https://checkout.ticketlayer.com` (not yet deployed) | | CDN | `https://cdn.staging.t9r.dev` | `https://cdn.ticketlayer.com` (not yet deployed) | Staging's Backstage and Stagedoor are on the team tailnet; the API, Live API, hosted checkout and CDN are public. ## Versioning Every request may carry `TL-Version: 2026-06-13` (the dated API version). The SDKs send it for you; a request without it gets the organisation's default, so generated code keeps working across releases. See [API versions](https://docs.ticketlayer.com/api/backstage/versions). --- # Webhooks Source: https://docs.ticketlayer.com/guides/integrations/webhooks Register a URL and Ticketlayer POSTs a signed JSON envelope to it whenever one of the events below happens in your organisation. Payloads are constructed field by field from a fixed, versioned view (never a raw database row), so what is documented here is exactly what arrives. ## Event types | Type | When | Payload | |---|---|---| | `order.created` | A new order was started | Order | | `order.confirmed` | An order was paid and confirmed | Order | | `order.cancelled` | An order was cancelled | Order | | `order.refunded` | An order was refunded | Order | | `customer.created` | A new customer was created | Customer | | `event.created` | A new event was created | Event | | `ticket.issued` | Tickets (passes) were issued for an order | Tickets issued | | `ticket.redeemed` | A ticket was scanned and redeemed | Ticket redeemed | `GET /v1/webhook-event-types` returns this list with descriptions, which is what the Backstage subscription UI shows. ## Payloads Money is in integer minor units with an ISO 4217 `currency` (`"totalAmount": 2500, "currency": "GBP"` is 25.00 GBP). Instants are ISO 8601 strings. Every nullable field is present as `null` rather than omitted. **Order** (`order.*`) ```json { "id": "ord_01J...", "orderNumber": "TL-10432", "status": "confirmed", "currency": "GBP", "totalAmount": 5400, "subtotalAmount": 5000, "customerId": "cus_01J...", "accountId": "acc_01J...", "createdAt": "2026-09-13T19:04:11.000Z", "lineItemCount": 2 } ``` **Customer** (`customer.created`) ```json { "id": "cus_01J...", "email": "ada@example.com", "firstName": "Ada", "lastName": "Lovelace", "accountId": "acc_01J...", "createdAt": "2026-09-13T19:04:11.000Z" } ``` **Event** (`event.created`) ```json { "id": "evt_01J...", "name": "Jazz Night", "status": "draft", "accountId": "acc_01J...", "venueId": "vnu_01J...", "timezone": "Europe/London", "createdAt": "2026-09-13T19:04:11.000Z" } ``` **Tickets issued** (`ticket.issued`) ```json { "orderId": "ord_01J...", "accountId": "acc_01J...", "passCount": 2, "passes": [ { "id": "pas_01J...", "ticketTypeId": "tkt_01J...", "occurrenceId": "occ_01J...", "status": "issued" }, { "id": "pas_01K...", "ticketTypeId": "tkt_01J...", "occurrenceId": "occ_01J...", "status": "issued" } ] } ``` **Ticket redeemed** (`ticket.redeemed`) ```json { "redemptionId": "red_01J...", "passId": "pas_01J...", "entitlementId": "ent_01J...", "accountId": "acc_01J..." } ``` ## The delivery Each delivery is one `POST` with a JSON body: ```json { "id": "whd_01J...", "type": "order.confirmed", "version": "2026-06-13", "createdAt": "2026-09-13T19:04:12.000Z", "data": { "id": "ord_01J...", "orderNumber": "TL-10432", "...": "..." } } ``` | Header | Value | |---|---| | `Content-Type` | `application/json` | | `User-Agent` | `Ticketlayer-Webhooks/1.0` | | `Ticketlayer-Signature` | `t=,v1=` | | `Ticketlayer-Event-Type` | The event type, same as `type` in the body | | `Ticketlayer-Event-Id` | The id of the source event; stable across retries of the same event | | `Ticketlayer-Delivery-Id` | The id of this delivery attempt series, same as `id` in the body | Respond with any `2xx` within 15 seconds. Anything else, or a timeout, is retried with backoff; the delivery is marked failed when retries are exhausted. Deliveries and their responses are listed at `GET /v1/webhook-deliveries` and in Backstage. Use `Ticketlayer-Event-Id` to deduplicate: a retry carries the same value. ## Verify the signature The signing secret is returned once when the endpoint is created. The signature is an HMAC-SHA256 of `"."` with that secret, hex encoded; reject deliveries whose `t` is more than five minutes from now. ```ts import crypto from 'node:crypto'; export function verifyTicketlayerSignature(rawBody: string, header: string, secret: string, toleranceSeconds = 300): boolean { const parts = Object.fromEntries(header.split(',').map((kv) => kv.split('=').map((s) => s.trim()))); const t = Number(parts.t); const v1 = parts.v1; if (!t || !v1) return false; if (Math.abs(Math.floor(Date.now() / 1000) - t) > toleranceSeconds) return false; const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex'); const a = Buffer.from(v1, 'hex'); const b = Buffer.from(expected, 'hex'); return a.length === b.length && crypto.timingSafeEqual(a, b); } ``` Compute the HMAC over the **raw** request body, before any JSON parsing or re-serialisation. ```ts title="Express" app.post('/webhooks/ticketlayer', express.raw({ type: 'application/json' }), (req, res) => { const raw = req.body.toString('utf8'); if (!verifyTicketlayerSignature(raw, req.get('Ticketlayer-Signature') ?? '', process.env.TL_WEBHOOK_SECRET!)) { return res.status(400).send('bad signature'); } const envelope = JSON.parse(raw); if (envelope.type === 'order.confirmed') { // envelope.data is the Order payload above } res.sendStatus(204); }); ``` ## Register an endpoint With an organisation API key or a staff token: ```bash curl -X POST https://api.staging.t9r.dev/v1/webhook-endpoints \ -H "Authorization: Bearer tlak_..." \ -H "X-Ticketlayer-Org: your-org-slug" \ -H "Content-Type: application/json" \ -d '{ "accountId": "acc_01J...", "url": "https://hooks.example.com/ticketlayer", "description": "Orders to the CRM", "eventTypes": ["order.confirmed", "ticket.issued"] }' ``` The response carries the endpoint and, once only, its `secret`. Omit `eventTypes` to receive every type. Endpoints are per account (the organisation's sub-unit that owns the events); the same URL can be registered for several accounts. Operations: [create](https://docs.ticketlayer.com/api/backstage/webhook-endpoints/createwebhookendpoint), [list](https://docs.ticketlayer.com/api/backstage/webhook-endpoints/listwebhookendpoints), [get](https://docs.ticketlayer.com/api/backstage/webhook-endpoints/getwebhookendpoint), [update](https://docs.ticketlayer.com/api/backstage/webhook-endpoints/updatewebhookendpoint) (URL, description, event types, `enabled`/`disabled`), [delete](https://docs.ticketlayer.com/api/backstage/webhook-endpoints/deletewebhookendpoint) and [test](https://docs.ticketlayer.com/api/backstage/webhook-endpoints/testwebhookendpoint), which sends a signed sample delivery. ## Payload versions Webhook payloads are a public contract. Each endpoint pins the payload version current when it was created (`2026-06-13` today) and keeps receiving that shape: when a payload changes in a breaking way a new dated version is added with a transform back to the previous one, and deliveries are transformed down to the endpoint's pinned version before sending. The version is stamped in every envelope as `version`. ## Local development Run a tunnel (for example `ngrok http 3000`) and register the tunnel URL as the endpoint. The test operation above is the quickest way to see a delivery without buying a ticket. --- # Connect an AI agent (MCP) Source: https://docs.ticketlayer.com/guides/agents/mcp Ticketlayer ships a **remote [MCP](https://modelcontextprotocol.io) server** so you can point your own AI agent - Claude Desktop, Claude Code, an MCP Inspector session, or anything that speaks MCP - at your Ticketlayer account and have it read your catalogue, orders and customers, **query your analytics**, and (with the right permission) create and update events. The agent acts **as you**. Every tool call carries your own credential to the same permissioned API the dashboard uses, so an agent can never do more than your own role allows, and never sees another organisation's data. | | | |---|---| | **Endpoint** | `https://mcp.staging.t9r.dev/mcp` (staging; production is not deployed yet) | | **Transport** | Streamable HTTP | | **Auth** | OAuth 2.1 - Dynamic Client Registration + PKCE | | **Connect scope** | `mcp` | ## Where it runs today The staging server is at `https://mcp.staging.t9r.dev/mcp` and is public. Its authorization server, **Stagedoor** (`stagedoor.staging.t9r.dev`), is published only on the Ticketlayer team tailnet, and the OAuth flow below has to reach it from your browser. So today: - from a machine on the tailnet, every client below connects and authenticates; - from anywhere else, the client registers and starts the login, and the browser redirect to Stagedoor does not resolve, so the connection cannot complete. Production, where Stagedoor is public, is not stood up yet. An API-key mode for the MCP server (so a server-side agent can connect without the browser flow) is planned in the platform plan and not built. When you run the stack locally with `tt dev`, the endpoint is `https://mcp.staging.t9r.dev/mcp`. ## How it works ``` your agent ──OAuth 2.1 (register → log in → consent)──▶ stagedoor (identity) │ issues access token │ Streamable HTTP + Bearer token (org chosen at login) ▼ Ticketlayer MCP server ──forwards your token──▶ Ticketlayer API · validates the token + `mcp` scope · your RBAC permissions · org taken from the token · scope limits writes ``` 1. Your MCP client discovers the server's metadata at `/.well-known/oauth-protected-resource/mcp` and finds the authorization server. 2. It **registers itself** automatically (Dynamic Client Registration - no pre-configuration, no client secret) and starts an OAuth login. 3. You log in, **choose which organisation** the agent may act for, and **consent** to the scopes it requested. 4. The agent receives an access token and calls tools. The MCP server validates the token and forwards it to the Ticketlayer API under your organisation and your permissions. The organisation is baked into the signed token, never chosen by the agent - so an agent connected to one org can't reach another. ## Connect your client The server URL is `https://mcp.staging.t9r.dev/mcp`. Every client below discovers auth and runs the login/consent flow in your browser the first time - there is no API key to paste and nothing to pre-register. (Read the note above about the tailnet first: the browser step needs to reach Stagedoor.) ### Claude Code (CLI) Add the server, then authenticate from inside a session: ```bash # Add it (available in the current project) claude mcp add --transport http ticketlayer https://mcp.staging.t9r.dev/mcp # …or make it available across all your projects claude mcp add --scope user --transport http ticketlayer https://mcp.staging.t9r.dev/mcp ``` ```text # Start Claude Code, then run the /mcp command: claude > /mcp # Select "ticketlayer" → Authenticate. Your browser opens to log in + consent; # the token is stored and refreshed automatically. ``` Manage it: ```bash claude mcp list # shows connection / auth status claude mcp get ticketlayer # details for one server claude mcp remove ticketlayer # remove it ``` To share it with a repo, commit a project-scoped `.mcp.json` at the repo root (use `--scope project` when adding, or write the file directly): ```json { "mcpServers": { "ticketlayer": { "type": "http", "url": "https://mcp.staging.t9r.dev/mcp" } } } ``` ### Claude Desktop Settings → **Connectors** → **Add custom connector** → name it `ticketlayer` and paste `https://mcp.staging.t9r.dev/mcp`. Claude Desktop registers itself and opens the browser for login + consent. (Custom connectors require a paid plan.) If you prefer a config file, or your Claude Desktop only supports stdio servers, bridge through `mcp-remote` in `claude_desktop_config.json` (Settings → Developer → Edit Config): ```json { "mcpServers": { "ticketlayer": { "command": "npx", "args": ["-y", "mcp-remote", "https://mcp.staging.t9r.dev/mcp"] } } } ``` ### Cursor Add to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project): ```json { "mcpServers": { "ticketlayer": { "url": "https://mcp.staging.t9r.dev/mcp" } } } ``` Then open **Settings → MCP** and authenticate the server. ### VS Code (GitHub Copilot) ```bash code --add-mcp '{"name":"ticketlayer","type":"http","url":"https://mcp.staging.t9r.dev/mcp"}' ``` …or commit `.vscode/mcp.json` (note VS Code uses the `servers` key): ```json { "servers": { "ticketlayer": { "type": "http", "url": "https://mcp.staging.t9r.dev/mcp" } } } ``` ### MCP Inspector (to test) ```bash npx @modelcontextprotocol/inspector ``` Open it, choose transport **Streamable HTTP**, enter `https://mcp.staging.t9r.dev/mcp`, and **Connect** - it walks you through the OAuth flow and lets you call tools by hand. ### Any other (stdio-only) client For a client that only speaks stdio, bridge to the remote server with [`mcp-remote`](https://www.npmjs.com/package/mcp-remote) (it handles the OAuth flow for you): ```json { "mcpServers": { "ticketlayer": { "command": "npx", "args": ["-y", "mcp-remote", "https://mcp.staging.t9r.dev/mcp"] } } } ``` ### Codex CLI Add to `~/.codex/config.toml`: ```toml [mcp_servers.ticketlayer] url = "https://mcp.staging.t9r.dev/mcp" ``` Once connected (any client), ask things like *"list my upcoming events"* or *"how many orders did the jazz night take?"*. ## Scopes & permissions Access is bounded **twice**: by the OAuth scopes you consent to, and by your own role (RBAC). An agent gets the **intersection** of the two. | Scope | Grants | |---|---| | `mcp` | Connect, and **read** across your catalogue, orders and customers | | `events.write` | **Create and update events** | | `orders.read`, `customers.read` | Granular read access (alternative to broad `mcp`) | - **Reads** work with the `mcp` scope alone. - **Writes** require the matching write scope (e.g. `events.write`). If your token doesn't carry it, the write tool returns a clear error telling you to reconnect and grant it - your agent can prompt you to re-authorise. - Admin operations and sensitive actions are **never** reachable through an agent token, regardless of your role. ## Tools **Read (run automatically):** events, occurrences, price schemes, venues and layouts, inventory and reservations, orders and order passes, customers, sales channels and listings, accounts, your own profile/permissions, and **analytics** (see below). **Write (require approval + a write scope):** | Tool | Action | |---|---| | `createEvent` | Create a new event | | `updateEvent` | Update an event's details or status | Write tools are marked **destructive**, so your MCP client asks you to confirm each one before it runs - that confirmation is the human-in-the-loop gate. Pricing and seating-layout edits are not yet exposed as agent tools. ## Analytics & reporting The agent can answer data questions ("how did the jazz night sell?", "revenue by channel last month") through **Insights** - the governed Reporting layer that serves the same numbers your dashboards show. These are read tools, available with the `mcp` scope; no writes, no approval needed. The pattern is always two steps: 1. **`getReportsMeta`** - discover the available data models, **measures** and **dimensions**. Always call this first; you can only query members it lists. 2. **`runReportsQuery`** - run an ad-hoc query built from those members. `runReportsQuery` takes a query object: ```json { "query": { "measures": ["sales_line_items.grossRevenue", "sales_line_items.ticketsSold"], "dimensions": ["sales_line_items.eventName"], "order": { "sales_line_items.grossRevenue": "desc" }, "limit": 10 } } ``` …with optional `timeDimensions` (e.g. `[{ "dimension": "orders.createdAt", "dateRange": "last 30 days", "granularity": "day" }]`) and `filters`. Other read tools cover saved reports and dashboards (`listSavedReports` / `runSavedReport`, `listDashboards` / `getDashboard`, `listReportTemplates`) and pre-baked rollups (`getReportsSummary`, `getReportsTimeseries`, `getReportsInventory`). Two conventions to read results correctly: - **Money is in integer minor units** (`"grossRevenue": "229350"` = £2,293.50) and carries a **currency** dimension - never sum across currencies. - **Timestamps are ISO 8601 UTC**; render in the venue/org timezone for display. Everything is **tenant-scoped automatically** - a query only ever sees your own organisation's data, enforced server-side in the Reporting layer. ## Security model - **You can't exceed yourself.** Tools call the same permissioned routes the UI uses, with your token. RBAC, the `404`-not-`403` rule, and the platform's field-stripped views all apply unchanged. - **One org per connection.** The org is carried in the signed token; switching orgs means logging in again. - **Least privilege.** Agent tokens are capped to their granted scopes, so even an organisation owner's agent only does what it was consented to do. - **No raw data path.** The MCP server holds no database connection and no model key - it only forwards your authenticated calls. ## Limitations (today) - Read-first: only `createEvent` / `updateEvent` writes are exposed. - One organisation per token. - Self-registered (DCR) agents are public PKCE clients with `https` or loopback redirect URIs only. --- # Sell tickets on your website Source: https://docs.ticketlayer.com/scenarios/sell-tickets-on-website 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](https://docs.ticketlayer.com/guides/agents/mcp) 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. There is no self-serve sign-up yet, so the organisation itself comes from the Ticketlayer team; see [Get a key](https://docs.ticketlayer.com/guides/getting-started/welcome#3-get-a-key). ## 3. Put the elements on the page Plain HTML or a site builder: the [HTML quickstart](https://docs.ticketlayer.com/guides/quickstarts/html). React: the [Vite quickstart](https://docs.ticketlayer.com/guides/quickstarts/vite-react) or the [Next.js quickstart](https://docs.ticketlayer.com/guides/quickstarts/nextjs). The minimum is the loader script and two tags: ```html ``` Match your brand with the `--tl-*` [theme tokens](https://docs.ticketlayer.com/reference/elements/#theming), 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: ```js window.ticketlayer.ready.then((tl) => tl.on('checkout:completed', (order) => { location.href = '/thanks?orderId=' + encodeURIComponent(order.id); }), ); ``` On `/thanks`, `` 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](https://docs.ticketlayer.com/guides/integrations/webhooks) 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](https://docs.ticketlayer.com/api/backstage/). ## 7. Returning customers `` signs a customer in with a magic link (no passwords), and `` lists their orders with the tickets. `` redeems presale and promo codes against the cart. All three are on the [Elements reference](https://docs.ticketlayer.com/reference/elements/). --- # SDKs Source: https://docs.ticketlayer.com/reference/sdk Ticketlayer ships two official TypeScript SDKs, one per API surface. Both are generated from the same OpenAPI documents that power the API reference, so their types always match the contract, and each sends the dated API version (`TL-Version`) it was generated against. ## Which packages are on npm today | Package | What | npm | |---|---|---| | `@ticketlayer/backstage` | Backstage API client (servers, staff tools, embed loader) | **Published**, 0.1.x | | `@ticketlayer/live` | Live API client for browsers, React Native and servers (`/server`) | Not yet: publishes when its release workflow runs | | `@ticketlayer/elements` | The `tl-*` web components | Not yet: same | | `@ticketlayer/elements-react` | React wrappers for the elements | Not yet: same | `@ticketlayer/backstage-sdk` was the old name of the Backstage package and is no longer maintained; use `@ticketlayer/backstage`. Until the three Live packages publish, the browser path that works is the CDN build (`cdn.staging.t9r.dev/v1/ticketlayer.js`); see the [HTML quickstart](https://docs.ticketlayer.com/guides/quickstarts/html). ## [Backstage SDK](https://docs.ticketlayer.com/reference/sdk/backstage) - `@ticketlayer/backstage` The server-side SDK for the **Backstage API**: events, venues, inventory, sales channels, orders, customers, payments, webhooks, organisations and the full admin surface. Use it in Node.js backends and internal tooling with an organisation API key, or in staff apps with a Stagedoor token. It also carries `@ticketlayer/backstage/embed`, the loader for Backstage widgets in your own app. ```bash npm install @ticketlayer/backstage ``` See the [getting started guide](https://docs.ticketlayer.com/reference/sdk/typescript/getting-started) and the [full reference](https://docs.ticketlayer.com/reference/sdk/backstage). ## [Live SDK](https://docs.ticketlayer.com/reference/sdk/live) - `@ticketlayer/live` The buyer-facing SDK for the **Live API**: sessions, listings, the cart, the hosted checkout modal, customer sign-in and orders. It runs in the browser and React Native, publishes itself on `window.Ticketlayer` for the [Elements](https://docs.ticketlayer.com/reference/elements/), and has a stateless server entry (`@ticketlayer/live/server`) for Next.js and edge runtimes. ```bash npm install @ticketlayer/live ``` See the [Next.js quickstart](https://docs.ticketlayer.com/guides/quickstarts/nextjs) and the [full reference](https://docs.ticketlayer.com/reference/sdk/live). ## Reference is auto-generated These reference pages are generated from each package's TypeScript source with TypeDoc (`npm run docs:sdk:gen` in the docs repository) and refreshed whenever the SDKs are rebuilt. --- # API versions Source: https://docs.ticketlayer.com/api/backstage/versions The Backstage API uses **dated versions** - each version is named after the day it was released, for example `2026-06-13`. The current version is **`2026-06-13`**. Within a version the API only ever changes additively: new endpoints, new optional parameters and new response fields may appear, but existing behaviour never changes. Breaking changes are only ever introduced in a new dated version, so an integration pinned to a version keeps working unchanged. ## How versioning works - **Pin with the `TL-Version` header.** Send the version date on every request to pin the API behaviour your integration expects. Responses echo the version that served the request in a `TL-Version` response header. - **Organisations are pinned at signup.** When an organisation is created it is pinned to the then-current version. Requests that omit `TL-Version` use the organisation's pinned version, so existing integrations are never broken by a new release. - **SDK majors pin a version.** Each major release of an official SDK hardcodes the version it speaks (the current TypeScript SDK sends `2026-06-13`). Upgrading the SDK is how most integrations move between API versions. - **Additive changes only within a version.** We may add endpoints, optional request fields and response fields at any time without releasing a new version. Your integration should ignore response fields it does not recognise. - **Twelve-month deprecation windows.** When a version is deprecated you have at least 12 months before it is sunset. While deprecated, responses include [`Deprecation`](https://datatracker.ietf.org/doc/html/rfc9745) and [`Sunset`](https://datatracker.ietf.org/doc/html/rfc8594) headers telling you when the version stops being served. ### Pinning a version ```bash curl https://api.ticketlayer.com/v1/events \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "TL-Version: 2026-06-13" ``` ### Discovering versions at runtime The full version list, including deprecation and sunset dates, is available from the API itself: ```bash curl https://api.ticketlayer.com/v1/meta/versions ``` ## Version status | Version | Status | Summary | Deprecated | Sunset | |---------|--------|---------|------------|--------| | **`2026-06-13`** | Current | Baseline dated version - all prior behaviour, no transforms. | - | - | ## Version history ### 2026-06-13 Current Baseline dated version - all prior behaviour, no transforms. No breaking changes - this is the baseline dated version. ## See also - [API changelog](./changelog) - additive changes and fixes within versions - [Backstage API introduction](https://docs.ticketlayer.com/api/backstage/) --- # Elements reference ## Elements Source: https://docs.ticketlayer.com/reference/elements Elements are web components (custom HTML tags prefixed `tl-`) that list events, take a customer through ticket selection, cart and checkout, and show the tickets they bought. They work in plain HTML, in Webflow or any site builder that lets you add a script tag, and in React through the generated wrappers in `@ticketlayer/elements-react`. Every element binds to the Live client the page publishes on `window.Ticketlayer`. Elements take no API key of their own: create the client once (the CDN loader does this from its `data-*` attributes, or call `createLiveClient()` from `@ticketlayer/live`) and the elements find it. ### Get them onto the page **CDN, no build step.** One script tag loads the Live SDK, the Elements bundle and the hosted checkout modal. The tags below then just work. ```html ``` See the [HTML quickstart](https://docs.ticketlayer.com/guides/quickstarts/html) for the attributes each environment needs today. **npm, for React and bundlers.** ```bash npm install @ticketlayer/live @ticketlayer/elements @ticketlayer/elements-react ``` ```tsx import { createLiveClient } from '@ticketlayer/live'; import { defineCustomElements, TlEventList } from '@ticketlayer/elements-react'; defineCustomElements(); // once, after hydration await createLiveClient({ baseUrl: 'https://live.staging.t9r.dev', publishableKey: 'tlpk_...' }); console.log(e.detail.eventId)} /> ``` Note (Package status): `@ticketlayer/live`, `@ticketlayer/elements` and `@ticketlayer/elements-react` are built in their repositories but are not on the public npm registry yet; they publish once their release workflows run. Until then use the CDN build, which staging serves at `cdn.staging.t9r.dev`. See the [Vite quickstart](https://docs.ticketlayer.com/guides/quickstarts/vite-react) for the workaround in the meantime. ### Elements ### Discovery List and present events. | Element | React | What it does | |---|---|---| | [``](./tl-event-card) | `TlEventCard` | | | [``](./tl-event-list) | `TlEventList` | | | [``](./tl-occurrence-selector) | `TlOccurrenceSelector` | A smart occurrence selector component that fetches and displays event occurrences from the Ticketlayer API. | ### Purchase Choose a date, pick tickets, open the buy flow. | Element | React | What it does | |---|---|---| | [``](./tl-buy-modal) | - | | | [``](./tl-buy-tickets-button) | `TlBuyTicketsButton` | | | [``](./tl-buy-tickets-wrapper) | `TlBuyTicketsWrapper` | | | [``](./tl-promo-code) | `TlPromoCode` | tl-promo-code - an input plus Apply button that redeems a presale or promo code for the current cart (POST /sales/presale-codes/redeem through the SDK). | | [``](./tl-seat-map) | `TlSeatMap` | | | [``](./tl-ticket-selector) | `TlTicketSelector` | | ### Cart Show and edit what the customer is about to buy. | Element | React | What it does | |---|---|---| | [``](./tl-cart) | `TlCart` | | | [``](./tl-cart-badge) | `TlCartBadge` | | | [``](./tl-cart-drawer) | `TlCartDrawer` | | ### Checkout Hand off to the hosted checkout and confirm the order. | Element | React | What it does | |---|---|---| | [``](./tl-checkout-wrapper) | `TlCheckoutWrapper` | | | [``](./tl-order-confirmation) | `TlOrderConfirmation` | tl-order-confirmation - the "thank you" page block: order reference, customer email, event and date, ticket lines, totals, then the tickets themselves (tl-order-tickets, each with a Download PDF link) | ### Tickets Render issued tickets with QR codes and PDF downloads. | Element | React | What it does | |---|---|---| | [``](./tl-order-tickets) | `TlOrderTickets` | tl-order-tickets - renders all the tickets for an order as scannable QR cards with PDF download. | | [``](./tl-ticket) | `TlTicket` | tl-ticket - a single event ticket: a scannable QR (the redemption token), ticket name / seat / holder, and a PDF download. | ### Account Sign in with a magic link and show past orders. | Element | React | What it does | |---|---|---| | [``](./tl-login) | `TlLogin` | tl-login - magic-link sign-in. | | [``](./tl-my-orders) | `TlMyOrders` | tl-my-orders - the signed-in customer's orders (GET /sales/my-orders through the SDK): event, date, ticket count, total and status per row. | ### Events Every element emits `CustomEvent`s whose names start with `tl` and whose payload is on `event.detail`. In HTML: ```html ``` In React each event is a prop named `onTl...`: ` ...} />`. ### Theming Elements read CSS custom properties prefixed `--tl-`. The Live SDK injects the values of the channel's theme (configured in Backstage) when `applyTheme` is on, which it is by default; set any token yourself on `:root` or on a wrapper to override. The defaults below come from the Elements global stylesheet and apply when nothing else sets the token. ### General | Token | Default | |---|---| | `--tl-font-family` | `system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif` | | `--tl-font-family-mono` | `ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace` | ### Colours | Token | Default | |---|---| | `--tl-primary` | `#6366f1` | | `--tl-primary-foreground` | `#ffffff` | | `--tl-secondary` | `#f3f4f6` | | `--tl-secondary-foreground` | `#111827` | | `--tl-background` | `#ffffff` | | `--tl-foreground` | `#111827` | | `--tl-muted` | `#f9fafb` | | `--tl-muted-foreground` | `#6b7280` | | `--tl-border` | `#e5e7eb` | | `--tl-success` | `#10b981` | | `--tl-success-foreground` | `#ffffff` | | `--tl-warning` | `#f59e0b` | | `--tl-warning-foreground` | `#ffffff` | | `--tl-error` | `#ef4444` | | `--tl-error-foreground` | `#ffffff` | ### Shape | Token | Default | |---|---| | `--tl-radius-sm` | `0.25rem` | | `--tl-radius-md` | `0.5rem` | | `--tl-radius-lg` | `0.75rem` | ### Spacing | Token | Default | |---|---| | `--tl-spacing-1` | `0.25rem` | | `--tl-spacing-2` | `0.5rem` | | `--tl-spacing-3` | `0.75rem` | | `--tl-spacing-4` | `1rem` | | `--tl-spacing-6` | `1.5rem` | | `--tl-spacing-8` | `2rem` | ```css :root { --tl-primary: #0f766e; --tl-primary-foreground: #ffffff; --tl-radius-md: 0.25rem; --tl-font-family: 'Inter', system-ui, sans-serif; } ``` Elements render in shadow DOM, so ordinary CSS selectors from the page do not reach inside them; the tokens are the styling contract. ## Source: https://docs.ticketlayer.com/reference/elements/tl-buy-modal | | | |---|---| | HTML tag | `` | | React | No wrapper: this element is mounted by the SDK, not placed in markup | | Category | Purchase | | Runs in | web (browser DOM) | ### Properties | Property | Attribute | Description | Type | Default | | ---------------------- | --------------- | ----------------------------------------------------------------- | --------------------- | ----------- | | `eventId` _(required)_ | `event-id` | Event to sell tickets for. | `string` | `undefined` | | `occurrenceId` | `occurrence-id` | Optionally open straight to ticket selection for this occurrence. | `string \| undefined` | `undefined` | ### Events | Event | Description | Type | | ------------ | ----------- | ----------------------------------- | | `tlCheckout` | | `CustomEvent` | | `tlClose` | | `CustomEvent` | | `tlError` | | `CustomEvent<{ message: string; }>` | Events are `CustomEvent`s; the payload is on `event.detail`. In HTML, listen with `element.addEventListener('tlXxx', handler)`; in React the wrapper exposes each one as an `onTlXxx` prop. ### Related elements Renders: [``](./tl-occurrence-selector), [``](./tl-ticket-selector) ## Source: https://docs.ticketlayer.com/reference/elements/tl-buy-tickets-button | | | |---|---| | HTML tag | `` | | React | `import { TlBuyTicketsButton } from '@ticketlayer/elements-react'` | | Category | Purchase | | Runs in | web (browser DOM) | ### Properties | Property | Attribute | Description | Type | Default | | ---------------------- | --------------- | ------------------------------------------------- | -------------------------------------------------------- | ------------- | | `currency` | `currency` | Currency code for price formatting | `string` | `'GBP'` | | `disabled` | `disabled` | Disabled state | `boolean` | `false` | | `eventId` _(required)_ | `event-id` | Event ID to purchase tickets for | `string` | `undefined` | | `fullWidth` | `full-width` | Full width button | `boolean` | `false` | | `label` | `label` | Button label override (default depends on state) | `string \| undefined` | `undefined` | | `occurrenceId` | `occurrence-id` | Optional pre-selected occurrence ID | `string \| undefined` | `undefined` | | `price` | `price` | Price to display (in minor units e.g. pence) | `number \| undefined` | `undefined` | | `pricePrefix` | `price-prefix` | Show price prefix text | `string` | `'From'` | | `size` | `size` | Button size | `"lg" \| "md" \| "sm"` | `'md'` | | `state` | `state` | Button state - determines colour, label, and icon | `"available" \| "comingSoon" \| "soldOut" \| "waitlist"` | `'available'` | | `variant` | `variant` | Button variant | `"outline" \| "primary" \| "secondary"` | `'primary'` | ### Events | Event | Description | Type | | --------- | --------------------------------------------------- | ----------------------------------------------------------------------- | | `tlClick` | Emitted when button is clicked (before modal opens) | `CustomEvent<{ eventId: string; occurrenceId?: string \| undefined; }>` | Events are `CustomEvent`s; the payload is on `event.detail`. In HTML, listen with `element.addEventListener('tlXxx', handler)`; in React the wrapper exposes each one as an `onTlXxx` prop. ## Source: https://docs.ticketlayer.com/reference/elements/tl-buy-tickets-wrapper | | | |---|---| | HTML tag | `` | | React | `import { TlBuyTicketsWrapper } from '@ticketlayer/elements-react'` | | Category | Purchase | | Runs in | web (browser DOM) | ### Properties | Property | Attribute | Description | Type | Default | | ---------------------- | --------------- | ----------------------------------------------------------- | --------------------- | ----------- | | `disabled` | `disabled` | Whether the wrapper is disabled | `boolean` | `false` | | `eventId` _(required)_ | `event-id` | The event ID to purchase tickets for | `string` | `undefined` | | `occurrenceId` | `occurrence-id` | Optional specific occurrence ID (skips occurrence selector) | `string \| undefined` | `undefined` | ### Events | Event | Description | Type | | ------------- | -------------------------------------------- | ----------------------------------- | | `tl-close` | Emitted when the modal closes | `CustomEvent` | | `tl-complete` | Emitted when purchase completes successfully | `CustomEvent` | | `tl-error` | Emitted when an error occurs | `CustomEvent<{ message: string; }>` | Events are `CustomEvent`s; the payload is on `event.detail`. In HTML, listen with `element.addEventListener('tlXxx', handler)`; in React the wrapper exposes each one as an `onTlXxx` prop. ### Slots | Slot | Description | | ---- | --------------------------------------- | | | Content to display (typically a button) | ## Source: https://docs.ticketlayer.com/reference/elements/tl-cart-badge | | | |---|---| | HTML tag | `` | | React | `import { TlCartBadge } from '@ticketlayer/elements-react'` | | Category | Cart | | Runs in | web (browser DOM) | ### Properties | Property | Attribute | Description | Type | Default | | ----------- | ------------ | ---------------------------------------------------------------- | ---------------------- | ----------- | | `badgeOnly` | `badge-only` | Badge only mode - only shows the count bubble, no icon or button | `boolean` | `false` | | `icon` | `icon` | Custom icon (emoji or text). If not provided, uses cart SVG | `string \| undefined` | `undefined` | | `showEmpty` | `show-empty` | Show the badge even when count is 0 | `boolean` | `false` | | `size` | `size` | Size variant | `"lg" \| "md" \| "sm"` | `'md'` | ### Events | Event | Description | Type | | --------- | --------------------------------- | ------------------------------------- | | `tlClick` | Emitted when the badge is clicked | `CustomEvent<{ itemCount: number; }>` | Events are `CustomEvent`s; the payload is on `event.detail`. In HTML, listen with `element.addEventListener('tlXxx', handler)`; in React the wrapper exposes each one as an `onTlXxx` prop. ## Source: https://docs.ticketlayer.com/reference/elements/tl-cart-drawer | | | |---|---| | HTML tag | `` | | React | `import { TlCartDrawer } from '@ticketlayer/elements-react'` | | Category | Cart | | Runs in | web (browser DOM) | ### Properties | Property | Attribute | Description | Type | Default | | --------- | --------- | ---------------------------------------------------------------------- | ------------------- | ------------- | | `heading` | `heading` | Heading shown at the top of the panel. | `string` | `'Your cart'` | | `open` | `open` | Controlled open state (also driven by the `ui:cart-requested` intent). | `boolean` | `false` | | `side` | `side` | Edge the panel slides in from. | `"left" \| "right"` | `'right'` | ### Events | Event | Description | Type | | --------- | ----------- | ------------------- | | `tlClose` | | `CustomEvent` | | `tlOpen` | | `CustomEvent` | Events are `CustomEvent`s; the payload is on `event.detail`. In HTML, listen with `element.addEventListener('tlXxx', handler)`; in React the wrapper exposes each one as an `onTlXxx` prop. ### Related elements Renders: [``](./tl-cart) ## Source: https://docs.ticketlayer.com/reference/elements/tl-cart | | | |---|---| | HTML tag | `` | | React | `import { TlCart } from '@ticketlayer/elements-react'` | | Category | Cart | | Runs in | web (browser DOM), native (planned React Native set) | ### Properties | Property | Attribute | Description | Type | Default | | -------------------- | ---------------------- | --------------------------------- | --------- | ------------ | | `checkoutLabel` | `checkout-label` | Checkout button label | `string` | `'Checkout'` | | `compact` | `compact` | Compact mode - hides some details | `boolean` | `false` | | `showCheckoutButton` | `show-checkout-button` | Show checkout button | `boolean` | `true` | | `showRemoveButtons` | `show-remove-buttons` | Show remove item buttons | `boolean` | `true` | ### Events | Event | Description | Type | | --------------- | -------------------------------- | ------------------------------------ | | `tlCartUpdated` | Emitted when cart is updated | `CustomEvent<{ cart: TlCartData; }>` | | `tlCheckout` | Emitted when checkout is clicked | `CustomEvent<{ cart: TlCartData; }>` | | `tlError` | Emitted on error | `CustomEvent<{ message: string; }>` | | `tlItemRemoved` | Emitted when item is removed | `CustomEvent<{ itemId: string; }>` | Events are `CustomEvent`s; the payload is on `event.detail`. In HTML, listen with `element.addEventListener('tlXxx', handler)`; in React the wrapper exposes each one as an `onTlXxx` prop. ### Related elements Used by: [``](./tl-cart-drawer) ## Source: https://docs.ticketlayer.com/reference/elements/tl-checkout-wrapper | | | |---|---| | HTML tag | `` | | React | `import { TlCheckoutWrapper } from '@ticketlayer/elements-react'` | | Category | Checkout | | Runs in | web (browser DOM) | ### Properties | Property | Attribute | Description | Type | Default | | ---------- | ---------- | ------------------------------- | --------- | ------- | | `disabled` | `disabled` | Whether the wrapper is disabled | `boolean` | `false` | ### Events | Event | Description | Type | | ------------- | -------------------------------------------- | ----------------------------------- | | `tl-close` | Emitted when the modal closes | `CustomEvent` | | `tl-complete` | Emitted when checkout completes successfully | `CustomEvent` | | `tl-error` | Emitted when an error occurs | `CustomEvent<{ message: string; }>` | Events are `CustomEvent`s; the payload is on `event.detail`. In HTML, listen with `element.addEventListener('tlXxx', handler)`; in React the wrapper exposes each one as an `onTlXxx` prop. ### Slots | Slot | Description | | ---- | ------------------------------------------------ | | | Content to display (typically a checkout button) | ## Source: https://docs.ticketlayer.com/reference/elements/tl-event-card | | | |---|---| | HTML tag | `` | | React | `import { TlEventCard } from '@ticketlayer/elements-react'` | | Category | Discovery | | Runs in | web (browser DOM), native (planned React Native set) | ### Properties | Property | Attribute | Description | Type | Default | | --------- | ---------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------- | ----------- | | `event` | -- | Event data to display (tl-event-list passes this) | `TlEventCardEvent \| undefined` | `undefined` | | `eventId` | `event-id` | Load the event from the SDK by id when no `event` is given, so a single card works standalone (e.g. on a Webflow page). | `string \| undefined` | `undefined` | ### Events | Event | Description | Type | | --------- | ------------------------------------------------ | ----------------------------------- | | `tlClick` | Emitted when the card is clicked | `CustomEvent<{ eventId: string; }>` | | `tlError` | Emitted when the event could not be loaded by id | `CustomEvent<{ message: string; }>` | Events are `CustomEvent`s; the payload is on `event.detail`. In HTML, listen with `element.addEventListener('tlXxx', handler)`; in React the wrapper exposes each one as an `onTlXxx` prop. ### Related elements Used by: [``](./tl-event-list) ## Source: https://docs.ticketlayer.com/reference/elements/tl-event-list | | | |---|---| | HTML tag | `` | | React | `import { TlEventList } from '@ticketlayer/elements-react'` | | Category | Discovery | | Runs in | web (browser DOM), native (planned React Native set) | ### Properties | Property | Attribute | Description | Type | Default | | ---------- | ---------- | --------------------------------------- | --------------------- | ----------- | | `category` | `category` | Category filter | `string \| undefined` | `undefined` | | `columns` | `columns` | Columns for grid layout (1, 2, 3, or 4) | `number` | `3` | | `limit` | `limit` | Maximum number of events to display | `number` | `12` | ### Events | Event | Description | Type | | -------------- | ------------------------------------- | ----------------------------------- | | `tlEventClick` | Emitted when an event card is clicked | `CustomEvent<{ eventId: string; }>` | Events are `CustomEvent`s; the payload is on `event.detail`. In HTML, listen with `element.addEventListener('tlXxx', handler)`; in React the wrapper exposes each one as an `onTlXxx` prop. ### Related elements Renders: [``](./tl-event-card) ## Source: https://docs.ticketlayer.com/reference/elements/tl-login | | | |---|---| | HTML tag | `` | | React | `import { TlLogin } from '@ticketlayer/elements-react'` | | Category | Account | | Runs in | web (browser DOM), native (planned React Native set) | tl-login - magic-link sign-in. The customer enters an email, we ask the SDK to send a link (POST /sales/customer-auth/magic-link), then either the link lands back on this page with `?code=` or the customer types the code from the email; both exchange through the SDK (POST /sales/customer-tokens). No password is ever handled here. States: enter email -> check your inbox (resend, enter code) -> signed in (email + sign out). ```html ``` ### Properties | Property | Attribute | Description | Type | Default | | ---------------- | ------------------ | ------------------------------------------------------------------------ | --------- | ----------- | | `allowCodeEntry` | `allow-code-entry` | Offer a "enter the code" path alongside the emailed link (default true). | `boolean` | `true` | | `heading` | `heading` | Heading for the email step. | `string` | `'Sign in'` | ### Events | Event | Description | Type | | ----------------- | ----------- | ----------------------------------- | | `tlAuthChanged` | | `CustomEvent` | | `tlError` | | `CustomEvent<{ message: string; }>` | | `tlMagicLinkSent` | | `CustomEvent<{ email: string; }>` | Events are `CustomEvent`s; the payload is on `event.detail`. In HTML, listen with `element.addEventListener('tlXxx', handler)`; in React the wrapper exposes each one as an `onTlXxx` prop. ### Related elements Used by: [``](./tl-my-orders) ## Source: https://docs.ticketlayer.com/reference/elements/tl-my-orders | | | |---|---| | HTML tag | `` | | React | `import { TlMyOrders } from '@ticketlayer/elements-react'` | | Category | Account | | Runs in | web (browser DOM), native (planned React Native set) | tl-my-orders - the signed-in customer's orders (GET /sales/my-orders through the SDK): event, date, ticket count, total and status per row. Clicking a row expands it to show the order's tickets (tl-order-tickets). Shows tl-login inline when nobody is signed in. ```html ``` ### Properties | Property | Attribute | Description | Type | Default | | -------------- | --------------- | ------------------------------------- | -------- | -------------------------------------------------------------------------- | | `columns` | `columns` | Columns for the expanded ticket grid. | `number` | `2` | | `emptyMessage` | `empty-message` | Copy for the empty state. | `string` | `"When you buy tickets they'll show up here, ready to view and download."` | ### Events | Event | Description | Type | | --------------- | ----------- | ----------------------------------- | | `tlError` | | `CustomEvent<{ message: string; }>` | | `tlOrderSelect` | | `CustomEvent<{ orderId: string; }>` | Events are `CustomEvent`s; the payload is on `event.detail`. In HTML, listen with `element.addEventListener('tlXxx', handler)`; in React the wrapper exposes each one as an `onTlXxx` prop. ### Related elements Renders: [``](./tl-order-tickets), [``](./tl-login) ## Source: https://docs.ticketlayer.com/reference/elements/tl-occurrence-selector | | | |---|---| | HTML tag | `` | | React | `import { TlOccurrenceSelector } from '@ticketlayer/elements-react'` | | Category | Discovery | | Runs in | web (browser DOM) | A smart occurrence selector component that fetches and displays event occurrences from the Ticketlayer API. ### Features - **Automatic data fetching** - Fetches occurrences via the Ticketlayer SDK - **Adaptive display modes** - Automatically chooses list, slots, or calendar view based on occurrence count - **Loading & error states** - Built-in spinner and error handling with retry - **Responsive** - Works on mobile and desktop with auto-adjusting layouts - **Themeable** - Fully customizable via CSS custom properties ### Usage ```tsx import { TlOccurrenceSelector } from '@ticketlayer/elements-react'; console.log('Selected:', e.detail.occurrence)} /> ``` ### Properties | Property | Attribute | Description | Type | Default | | ---------------------- | -------------- | --------------------------------------------------------------------- | ---------------------------------------------- | ----------- | | `displayMode` | `display-mode` | Force a specific display mode (auto-detected if not set) | `"calendar" \| "list" \| "slots" \| undefined` | `undefined` | | `eventId` _(required)_ | `event-id` | Event ID to fetch occurrences for | `string` | `undefined` | | `orientation` | `orientation` | Layout orientation (auto = horizontal on desktop, vertical on mobile) | `"auto" \| "horizontal" \| "vertical"` | `'auto'` | | `theme` | -- | Theme configuration | `TlOccurrenceSelectorTheme \| undefined` | `undefined` | ### Events | Event | Description | Type | | ---------- | -------------------------------------- | -------------------------------------------- | | `tlSelect` | Emitted when an occurrence is selected | `CustomEvent<{ occurrence: TlOccurrence; }>` | Events are `CustomEvent`s; the payload is on `event.detail`. In HTML, listen with `element.addEventListener('tlXxx', handler)`; in React the wrapper exposes each one as an `onTlXxx` prop. ### Related elements Used by: [``](./tl-buy-modal) ## Source: https://docs.ticketlayer.com/reference/elements/tl-order-confirmation | | | |---|---| | HTML tag | `` | | React | `import { TlOrderConfirmation } from '@ticketlayer/elements-react'` | | Category | Checkout | | Runs in | web (browser DOM), native (planned React Native set) | tl-order-confirmation - the "thank you" page block: order reference, customer email, event and date, ticket lines, totals, then the tickets themselves (tl-order-tickets, each with a Download PDF link). Finds its order three ways, in priority order: 1. the `order-id` prop 2. the URL (`?orderId=`), the contract the hosted box office confirmation page uses; `?redirect_status=` from a Stripe return is honoured too 3. the SDK's `checkout:completed` event, for a page that mounts this before the customer pays ```html ``` ### Properties | Property | Attribute | Description | Type | Default | | --------------- | ---------------- | -------------------------------------------------------------------------------------- | --------------------- | ----------- | | `columns` | `columns` | Columns for the ticket grid. | `number` | `2` | | `customerEmail` | `customer-email` | Email to show when the order view carries none (a host that collected it at checkout). | `string \| undefined` | `undefined` | | `orderId` | `order-id` | The order to show. Falls back to `?orderId=` in the page URL. | `string \| undefined` | `undefined` | | `showTickets` | `show-tickets` | Mount tl-order-tickets under the summary (default true). | `boolean` | `true` | ### Events | Event | Description | Type | | --------------- | ----------- | -------------------------------------- | | `tlError` | | `CustomEvent<{ message: string; }>` | | `tlOrderLoaded` | | `CustomEvent<{ order: TlOrderData; }>` | Events are `CustomEvent`s; the payload is on `event.detail`. In HTML, listen with `element.addEventListener('tlXxx', handler)`; in React the wrapper exposes each one as an `onTlXxx` prop. ### Related elements Renders: [``](./tl-order-tickets) ## Source: https://docs.ticketlayer.com/reference/elements/tl-order-tickets | | | |---|---| | HTML tag | `` | | React | `import { TlOrderTickets } from '@ticketlayer/elements-react'` | | Category | Tickets | | Runs in | web (browser DOM), native (planned React Native set) | tl-order-tickets - renders all the tickets for an order as scannable QR cards with PDF download. Fetches the order through the SDK (order-access gated by the session), so it works on a confirmation page or in an account. ```html ``` ### Properties | Property | Attribute | Description | Type | Default | | ---------------------- | ---------- | -------------------------------- | -------- | ----------- | | `columns` | `columns` | Columns in the grid (default 2). | `number` | `2` | | `orderId` _(required)_ | `order-id` | The order whose tickets to show. | `string` | `undefined` | ### Related elements Renders: [``](./tl-ticket) Used by: [``](./tl-my-orders), [``](./tl-order-confirmation) ## Source: https://docs.ticketlayer.com/reference/elements/tl-promo-code | | | |---|---| | HTML tag | `` | | React | `import { TlPromoCode } from '@ticketlayer/elements-react'` | | Category | Purchase | | Runs in | web (browser DOM) | tl-promo-code - an input plus Apply button that redeems a presale or promo code for the current cart (POST /sales/presale-codes/redeem through the SDK). Redemption unlocks gated pricing on the customer; the SDK re-reads the cart and publishes cart:updated, so tl-cart and badges re-render on their own. The API has no un-redeem, so the applied state offers only "use a different code", which clears the input for another redemption. ```html ``` ### Properties | Property | Attribute | Description | Type | Default | | ------------- | -------------- | ------------------- | -------- | ------------------------- | | `buttonLabel` | `button-label` | Apply button label. | `string` | `'Apply'` | | `placeholder` | `placeholder` | Input placeholder. | `string` | `'Promo or presale code'` | ### Events | Event | Description | Type | | ---------------- | ----------- | ----------------------------------- | | `tlError` | | `CustomEvent<{ message: string; }>` | | `tlPromoApplied` | | `CustomEvent` | Events are `CustomEvent`s; the payload is on `event.detail`. In HTML, listen with `element.addEventListener('tlXxx', handler)`; in React the wrapper exposes each one as an `onTlXxx` prop. ## Source: https://docs.ticketlayer.com/reference/elements/tl-seat-map | | | |---|---| | HTML tag | `` | | React | `import { TlSeatMap } from '@ticketlayer/elements-react'` | | Category | Purchase | | Runs in | web (browser DOM) | ### Properties | Property | Attribute | Description | Type | Default | | --------------------------- | --------------- | ------------------------------------------ | -------- | ------------------------------------ | | `apiUrl` | `api-url` | API URL for the seat map data | `string` | `'https://api.ticketlayer.com'` | | `hboUrl` | `hbo-url` | Base URL for the hosted seat map (HBO URL) | `string` | `'https://checkout.ticketlayer.com'` | | `height` | `height` | Height of the seat map | `string` | `'600px'` | | `occurrenceId` _(required)_ | `occurrence-id` | Occurrence ID to show seat map for | `string` | `undefined` | | `width` | `width` | Width of the seat map | `string` | `'100%'` | ### Events | Event | Description | Type | | --------------- | ---------------------------------------- | -------------------------------------------------------- | | `tlCartChange` | Emitted when cart seats change | `CustomEvent<{ seatIds: string[]; }>` | | `tlError` | Emitted when an error occurs | `CustomEvent<{ error: string; }>` | | `tlLoad` | Emitted when seat map is loaded | `CustomEvent<{ seatMapId: string; }>` | | `tlReady` | Emitted when seat map is ready | `CustomEvent` | | `tlSeatAdded` | Emitted when a seat is added to cart | `CustomEvent<{ seatId: string; ticketTypeId: string; }>` | | `tlSeatRemoved` | Emitted when a seat is removed from cart | `CustomEvent<{ seatId: string; }>` | Events are `CustomEvent`s; the payload is on `event.detail`. In HTML, listen with `element.addEventListener('tlXxx', handler)`; in React the wrapper exposes each one as an `onTlXxx` prop. ## Source: https://docs.ticketlayer.com/reference/elements/tl-ticket-selector | | | |---|---| | HTML tag | `` | | React | `import { TlTicketSelector } from '@ticketlayer/elements-react'` | | Category | Purchase | | Runs in | web (browser DOM), native (planned React Native set) | ### Properties | Property | Attribute | Description | Type | Default | | --------------------------- | --------------- | ----------------------- | --------- | --------------- | | `buttonLabel` | `button-label` | Button label | `string` | `'Add to Cart'` | | `eventId` _(required)_ | `event-id` | Event ID | `string` | `undefined` | | `occurrenceId` _(required)_ | `occurrence-id` | Occurrence ID | `string` | `undefined` | | `showButton` | `show-button` | Show add to cart button | `boolean` | `true` | ### Events | Event | Description | Type | | ------------------ | ------------------------------------ | ------------------------------------------------------------------------- | | `tlAddToCart` | Emitted when items are added to cart | `CustomEvent<{ items: AddToCartItem[]; }>` | | `tlError` | Emitted on error | `CustomEvent<{ message: string; }>` | | `tlQuantityChange` | Emitted when quantity changes | `CustomEvent<{ ticketTypeId: string; quantity: number; total: number; }>` | Events are `CustomEvent`s; the payload is on `event.detail`. In HTML, listen with `element.addEventListener('tlXxx', handler)`; in React the wrapper exposes each one as an `onTlXxx` prop. ### Related elements Used by: [``](./tl-buy-modal) ## Source: https://docs.ticketlayer.com/reference/elements/tl-ticket | | | |---|---| | HTML tag | `` | | React | `import { TlTicket } from '@ticketlayer/elements-react'` | | Category | Tickets | | Runs in | web (browser DOM), native (planned React Native set) | tl-ticket - a single event ticket: a scannable QR (the redemption token), ticket name / seat / holder, and a PDF download. Greys out + stamps Used/Void when redeemed or cancelled. ### Properties | Property | Attribute | Description | Type | Default | | ---------------------- | ---------- | ------------------------------------------------------- | -------------- | ----------- | | `orderId` _(required)_ | `order-id` | Order id this ticket belongs to (for the PDF download). | `string` | `undefined` | | `ticket` _(required)_ | -- | The ticket to render. | `TlTicketData` | `undefined` | ### Related elements Used by: [``](./tl-order-tickets) --- # API operation index ## Backstage API Base URL: https://api.ticketlayer.com/v1 (staging: https://api.staging.t9r.dev/v1). OpenAPI document: https://docs.ticketlayer.com/openapi/backstage.json. Reference pages: https://docs.ticketlayer.com/api/backstage/. ### Meta - GET /meta/versions - List API versions (listApiVersions) ### Authentication - POST /auth/login - User login (login) - POST /auth/refresh - Refresh access token (refresh) - POST /auth/redeem - Redeem invitation (redeem) - POST /auth/federate - Federate user to organisation (federate) ### Me - GET /me - Get current user (getCurrentUser) - GET /me/organisations - Get my organisations (getMyOrganisations) - GET /me/roles - Get my roles (getMyRoles) - GET /me/permissions - Get my permissions (getMyPermissions) ### Organisations - GET /organisations/{id} - Get organisation (getOrganisation) - PATCH /organisations/{id} - Update organisation (updateOrganisation) ### Accounts - GET /accounts - List accounts (listAccounts) - POST /accounts - Create account (createAccount) - GET /accounts/{id} - Get account (getAccount) - PATCH /accounts/{id} - Update account (updateAccount) - DELETE /accounts/{id} - Delete account (deleteAccount) ### Identity Providers - GET /identity-providers - List identity providers (listIdentityProviders) - GET /identity-providers/{id} - Get identity provider (getIdentityProvider) - PATCH /identity-providers/{id} - Update identity provider (updateIdentityProvider) ### User Invitations - POST /users/invitations - Create user invitation (createUserInvitation) - GET /users/invitations - List user invitations (listUserInvitations) - GET /users/invitations/{id} - Get user invitation (getUserInvitation) - DELETE /users/invitations/{id} - Cancel user invitation (cancelUserInvitation) - POST /users/invitations/{id}/resend - Resend user invitation (resendUserInvitation) ### Roles - GET /roles - List roles (listRoles) - POST /roles - Create role (createRole) - GET /roles/{id} - Get role (getRole) - PATCH /roles/{id} - Update role (updateRole) - DELETE /roles/{id} - Delete role (deleteRole) ### User Account Roles - GET /user-accounts - List all role assignments (listUserAccountRoles) - POST /user-accounts - Assign role to user (assignRole) - PUT /user-accounts - Update user roles on account (updateUserAccountRoles) - DELETE /user-accounts/{id} - Remove role assignment (removeRoleAssignment) - GET /user-accounts/user/{userId} - List role assignments for user (listUserAccountRolesByUser) - GET /user-accounts/account/{accountId} - List role assignments for account (listUserAccountRolesByAccount) ### Partners - POST /partners/accounts - Provision a partner customer account (createPartnerAccount) ### API Keys - POST /api-keys - Create an organisation API key (createApiKey) - GET /api-keys - List organisation API keys (listApiKeys) - DELETE /api-keys/{id} - Revoke an organisation API key (revokeApiKey) ### Embed Sessions - POST /embed/sessions - Mint an embed session (createEmbedSession) - GET /embed/sessions/current - Describe the current embed session (getCurrentEmbedSession) ### Events - GET /events - List events (listEvents) - POST /events - Create event (createEvent) - GET /events/{id} - Get event (getEvent) - PATCH /events/{id} - Update event (updateEvent) - DELETE /events/{id} - Delete event (deleteEvent) ### Event Occurrences - GET /events/{eventId}/occurrences - List occurrences for event (listEventOccurrences) - POST /events/{eventId}/occurrences - Create event occurrence (createEventOccurrence) - GET /events/{eventId}/occurrences/{occurrenceId} - Get event occurrence (getEventOccurrence) - PATCH /events/{eventId}/occurrences/{occurrenceId} - Update event occurrence (updateEventOccurrence) - DELETE /events/{eventId}/occurrences/{occurrenceId} - Delete event occurrence (deleteEventOccurrence) ### Event Price Schemes - GET /events/{eventId}/price-schemes - List price schemes for event (listEventPriceSchemes) - POST /events/{eventId}/price-schemes - Create price scheme for event (createEventPriceScheme) - GET /events/{eventId}/price-schemes/{priceSchemeId} - Get price scheme (getEventPriceScheme) - PATCH /events/{eventId}/price-schemes/{priceSchemeId} - Update price scheme (updateEventPriceScheme) - DELETE /events/{eventId}/price-schemes/{priceSchemeId} - Delete price scheme (deleteEventPriceScheme) ### Venues - GET /venues - List venues (listVenues) - POST /venues - Create venue (createVenue) - GET /venues/{id} - Get venue (getVenue) - PATCH /venues/{id} - Update venue (updateVenue) - DELETE /venues/{id} - Delete venue (deleteVenue) ### Venue Layouts - GET /venues/{id}/layouts - List layouts for venue (listVenueLayouts) - POST /venues/{id}/layouts - Create venue layout (createVenueLayout) - GET /venues/{id}/layouts/{layoutId} - Get venue layout (getVenueLayout) - PATCH /venues/{id}/layouts/{layoutId} - Update venue layout (updateVenueLayout) - DELETE /venues/{id}/layouts/{layoutId} - Delete venue layout (deleteVenueLayout) ### Venue Layout Areas - POST /venues/{id}/layouts/{layoutId}/areas - Add area to venue layout (addAreaToVenueLayout) - PATCH /venues/{id}/layouts/{layoutId}/areas/{areaId} - Update venue layout area (updateVenueLayoutArea) - DELETE /venues/{id}/layouts/{layoutId}/areas/{areaId} - Delete venue layout area (deleteVenueLayoutArea) ### Venue Layout Categories - POST /venues/{id}/layouts/{layoutId}/categories - Add category to venue layout (addCategoryToVenueLayout) - PATCH /venues/{id}/layouts/{layoutId}/categories/{categoryId} - Update venue layout category (updateVenueLayoutCategory) - DELETE /venues/{id}/layouts/{layoutId}/categories/{categoryId} - Delete venue layout category (deleteVenueLayoutCategory) ### Venue Layout Seats - POST /venues/{id}/layouts/{layoutId}/areas/{areaId}/seats - Add seat to area (addSeatToArea) - POST /venues/{id}/layouts/{layoutId}/areas/{areaId}/seats/bulk - Bulk add seats to area (bulkAddSeatsToArea) - POST /venues/{id}/layouts/{layoutId}/areas/{areaId}/seats/generate - Generate seats for area (generateSeatsForArea) - PUT /venues/{id}/layouts/{layoutId}/areas/{areaId}/seats/sync - Sync seats in area (syncSeatsInArea) - PATCH /venues/{id}/layouts/{layoutId}/areas/{areaId}/seats/{seatId} - Update seat in area (updateSeatInArea) - DELETE /venues/{id}/layouts/{layoutId}/areas/{areaId}/seats/{seatId} - Delete seat from area (deleteSeatFromArea) ### Billing - GET /billing/packages - List credit packages (listCreditPackages) - GET /organisations/{organisationId}/billing/can-sell - Check if organisation can sell (checkCanSell) - GET /billing/balance - Get credit balance (getCreditBalance) - GET /billing/transactions - List credit transactions (listCreditTransactions) - POST /billing/purchases - Purchase credits (createCreditPurchase) - GET /billing/invoices - List invoices (listInvoices) - GET /billing/invoices/{invoiceId} - Get invoice (getInvoice) - GET /billing/payments - List billing payments (listBillingPayments) - POST /billing/subscriptions - Create subscription (createSubscription) - GET /billing/subscriptions - List subscriptions (listSubscriptions) - DELETE /billing/subscriptions/{subscriptionId} - Cancel subscription (cancelSubscription) - GET /billing/auto-topup - Get auto top-up configuration (getAutoTopup) - PUT /billing/auto-topup - Update auto top-up configuration (updateAutoTopup) - GET /billing/payment-methods - List payment methods (listPaymentMethods) - POST /billing/payment-methods - Save payment method (savePaymentMethod) - POST /billing/setup-intent - Create setup intent (createSetupIntent) - DELETE /billing/payment-methods/{paymentMethodId} - Delete payment method (deletePaymentMethod) - PUT /billing/payment-methods/{paymentMethodId}/default - Set default payment method (setDefaultPaymentMethod) - GET /billing/ai/packages - List AI credit packages (listAiCreditPackages) - GET /billing/ai/balance - Get AI credit balance (getAiBalance) - GET /billing/ai/transactions - List AI credit transactions (listAiCreditTransactions) - POST /billing/ai-topup - Top up AI credits (createAiTopup) ### Inventory - POST /inventory - Create inventory (createInventory) - GET /inventory - List inventory (listInventory) - GET /inventory/{id} - Get inventory (getInventory) - DELETE /inventory/{id} - Delete inventory (deleteInventory) - PATCH /inventory/{id}/capacity - Update inventory capacity (updateInventoryCapacity) - GET /inventory/{id}/audit-log - Get inventory audit log (getInventoryAuditLog) ### Inventory Seats - POST /inventory/{id}/seats - Bulk import seats (bulkImportSeats) - GET /inventory/{id}/seats - List inventory seats (listInventorySeats) ### Inventory Reservations - POST /inventory/reserve - Reserve inventory (reserveInventory) - POST /inventory/check-availability - Check availability (checkAvailability) - GET /inventory/reservations - List reservations (listReservations) - GET /inventory/reservations/{id} - Get reservation (getReservation) - POST /inventory/reservations/{id}/confirm - Confirm reservation (confirmReservation) - POST /inventory/reservations/{id}/release - Release reservation (releaseReservation) - PATCH /inventory/reservations/{id}/extend - Extend reservation (extendReservation) ### Inventory Holds - POST /inventory/holds - Create hold (createHold) - POST /inventory/holds/{id}/release - Release hold (releaseHold) ### Customers - POST /customers - Create customer (createCustomer) - GET /customers - List customers (listCustomers) - GET /customers/{customerId} - Get customer (getCustomer) - PATCH /customers/{customerId} - Update customer (updateCustomer) - POST /customers/{customerId}/block - Block customer (blockCustomer) - POST /customers/{customerId}/unblock - Unblock customer (unblockCustomer) ### Orders - POST /orders - Create order (createOrder) - GET /orders - List orders (listOrders) - GET /orders/{orderId} - Get order (getOrder) - PATCH /orders/{orderId} - Update order (updateOrder) - GET /orders/number/{orderNumber} - Get order by number (getOrderByNumber) - POST /orders/{orderId}/cancel - Cancel order (cancelOrder) - POST /orders/{orderId}/status - Transition order status (transitionOrderStatus) - POST /orders/{orderId}/validate - Validate order (validateOrder) - POST /orders/{orderId}/items - Add line item (addOrderLineItem) - PATCH /orders/{orderId}/items/{itemId} - Update line item (updateOrderLineItem) - DELETE /orders/{orderId}/items/{itemId} - Remove line item (removeOrderLineItem) - POST /orders/{orderId}/payment - Initiate payment (initiateOrderPayment) - GET /orders/{orderId}/payment/status - Get payment status (getOrderPaymentStatus) - GET /orders/{orderId}/passes/{passId}/ticket.pdf - Download a pass as a PDF ticket (getOrderPassPdf) - POST /orders/{orderId}/resend-confirmation - Resend order confirmation email (resendOrderConfirmation) - GET /orders/{orderId}/passes - Get order passes (getOrderPasses) - POST /orders/{orderId}/passes/{passId}/print - Print a pass to a device (printPass) ### Payments - POST /payments - Create payment (createPayment) - GET /payments - List payments (listPayments) - GET /payments/{paymentId} - Get payment (getPayment) - POST /payments/{paymentId}/cancel - Cancel payment (cancelPayment) - POST /payments/{paymentId}/refunds - Create refund (createPaymentRefund) - GET /payments/{paymentId}/refunds - List refunds (listPaymentRefunds) ### Payment Providers - POST /payment-providers - Create payment provider (createPaymentProvider) - GET /payment-providers - List payment providers (listPaymentProviders) - GET /payment-providers/default - Get default payment provider (getDefaultPaymentProvider) - GET /payment-providers/{providerId} - Get payment provider (getPaymentProvider) - PATCH /payment-providers/{providerId} - Update payment provider (updatePaymentProvider) - DELETE /payment-providers/{providerId} - Delete payment provider (deletePaymentProvider) - POST /payment-providers/ticketlayer-pay/enable - Enable Ticketlayer Pay (enableTicketlayerPay) - GET /payment-providers/ticketlayer-pay - Ticketlayer Pay status (getTicketlayerPay) - POST /payment-providers/ticketlayer-pay/onboarding-session - Account Session for embedded Ticketlayer Pay onboarding (createTicketlayerPayOnboardingSession) - POST /payment-providers/ticketlayer-pay/onboarding-link - Hosted onboarding link for Ticketlayer Pay (createTicketlayerPayOnboardingLink) - POST /payment-providers/stripe-connect - Link the organisation's own Stripe account (linkStripeConnect) - GET /payment-providers/stripe-connect - The organisation's Stripe Connect provider (getStripeConnect) - GET /payment-providers/{providerId}/accounts - Per-Account routing rows on a Stripe Connect provider (listPaymentProviderAccounts) - GET /payment-providers/{providerId}/accounts/{accountId} - One Account's routing on a Stripe Connect provider (getPaymentProviderAccount) - PUT /payment-providers/{providerId}/accounts/{accountId} - Set how an Account charges through a Stripe Connect provider (setPaymentProviderAccountMode) - POST /payment-providers/{providerId}/accounts/{accountId}/onboarding-session - Account Session for embedded onboarding of an Account's connected account (createPaymentProviderAccountOnboardingSession) - POST /payment-providers/{providerId}/accounts/{accountId}/onboarding-link - Hosted onboarding link for an Account's connected account (createPaymentProviderAccountOnboardingLink) ### Sales Channels - POST /sales-channels - Create sales channel (createSalesChannel) - GET /sales-channels - List sales channels (listSalesChannels) - GET /sales-channels/{channelId} - Get sales channel (getSalesChannel) - PATCH /sales-channels/{channelId} - Update sales channel (updateSalesChannel) - DELETE /sales-channels/{channelId} - Delete sales channel (deleteSalesChannel) ### Keys - POST /sales-channels/{channelId}/keys - Issue channel key (issueSalesChannelKey) - GET /sales-channels/{channelId}/keys - List channel keys (listSalesChannelKeys) - POST /sales-channels/{channelId}/keys/{keyId}/revoke - Revoke channel key (revokeSalesChannelKey) ### Listings - POST /sales-channels/{channelId}/listings - List event on channel (createSalesChannelListing) - GET /sales-channels/{channelId}/listings - List channel listings (listSalesChannelListings) - DELETE /sales-channels/{channelId}/listings/{listingId} - Remove channel listing (deleteSalesChannelListing) ### Carts - POST /sales-channels/{channelId}/carts - Create staff cart (createStaffCart) - GET /sales-channels/{channelId}/carts/{cartId} - Get staff cart (getStaffCart) - POST /sales-channels/{channelId}/carts/{cartId}/items - Add staff cart item (addStaffCartItem) - DELETE /sales-channels/{channelId}/carts/{cartId}/items/{itemId} - Remove staff cart item (removeStaffCartItem) - POST /sales-channels/{channelId}/carts/{cartId}/checkout - Checkout staff cart (checkoutStaffCart) ### Presale Codes - POST /presale-codes - Create presale code (createPresaleCode) - GET /presale-codes - List presale codes (listPresaleCodes) - POST /presale-codes/{codeId}/deactivate - Deactivate presale code (deactivatePresaleCode) ### Fee Profiles - POST /fee-profiles - Create fee profile (createFeeProfile) - GET /fee-profiles - List fee profiles (listFeeProfiles) - GET /fee-profiles/{profileId} - Get fee profile (getFeeProfile) - PATCH /fee-profiles/{profileId} - Update fee profile (updateFeeProfile) - DELETE /fee-profiles/{profileId} - Delete fee profile (deleteFeeProfile) ### Sales Listings - GET /sales/listings - List active listings (listSalesListings) ### Sales Customer Auth - POST /sales/customer-auth/magic-link - Request magic link (requestSalesMagicLink) ### Sales Customer Tokens - POST /sales/customer-tokens - Exchange identity proof for customer token (createSalesCustomerToken) - POST /sales/customer-tokens/refresh - Refresh a customer token (refreshSalesCustomerToken) ### Sales Carts - POST /sales/carts - Create cart (createSalesCart) - GET /sales/carts/{cartId} - Get cart (getSalesCart) - POST /sales/carts/{cartId}/items - Add cart item (addSalesCartItem) - DELETE /sales/carts/{cartId}/items/{itemId} - Remove cart item (removeSalesCartItem) - POST /sales/carts/{cartId}/checkout - Checkout cart (checkoutSalesCart) ### Sales My Orders - GET /sales/my-orders - List my orders (listMySalesOrders) ### Sales Orders - GET /sales/orders/{orderId} - Get order (getSalesOrder) - GET /sales/orders/{orderId}/passes/{passId}/ticket.pdf - Download a ticket PDF (getSalesOrderTicketPdf) ### Sales Order Payments - POST /sales/orders/{orderId}/payments - Create order payment (createSalesOrderPayment) ### Sales Refund Requests - POST /sales/orders/{orderId}/refund-requests - Request refund or exchange (createSalesOrderRefundRequest) ### Sales Customers - POST /sales/customers - Create customer (createSalesCustomer) - GET /sales/customers/{customerId} - Get customer (getSalesCustomer) - PATCH /sales/customers/{customerId} - Update customer (updateSalesCustomer) ### Sales Presale Codes - POST /sales/presale-codes/redeem - Redeem presale code (redeemSalesPresaleCode) ### Sales - GET /sales/channel - Resolve a channel by domain (resolveSalesChannel) - GET /sales/events/{eventId} - Get event catalogue detail (getSalesEvent) - GET /sales/theme - Get channel theme (getSalesTheme) ### Themes - GET /themes - List themes (listThemes) - POST /themes - Create theme (createTheme) - GET /themes/{id} - Get theme (getTheme) - PATCH /themes/{id} - Update theme (updateTheme) - DELETE /themes/{id} - Delete theme (deleteTheme) - GET /themes/{id}/resolved - Get resolved theme (getResolvedTheme) ### Entitlements - POST /passes/{barcode}/redeem - Redeem a pass (redeemPass) ### Ticket Templates - GET /ticket-templates - List ticket templates (listTicketTemplates) - POST /ticket-templates - Create ticket template (createTicketTemplate) - GET /ticket-templates/{id} - Get ticket template (getTicketTemplate) - PATCH /ticket-templates/{id} - Update ticket template (updateTicketTemplate) - DELETE /ticket-templates/{id} - Delete ticket template (deleteTicketTemplate) ### Scan Configs - POST /scan-configs - Create a scan configuration (createScanConfig) - GET /scan-configs - List scan configurations (listScanConfigs) - GET /scan-configs/{configId} - Get a scan configuration (getScanConfig) - PATCH /scan-configs/{configId} - Update a scan configuration (updateScanConfig) - DELETE /scan-configs/{configId} - Delete a scan configuration (deleteScanConfig) - PUT /scan-configs/{configId}/devices - Assign scanner devices to a configuration (setScanConfigDevices) ### Scan - GET /scan/config - Get the device scan scope (getScanConfigForDevice) - GET /scan/manifest - Get the offline validation dataset (getScanManifest) - POST /scan/operations - Submit scan operations (submitScanOperations) ### Scans - GET /scans - List scans (staff reporting) (listScans) - POST /redemptions/{redemptionId}/reverse - Reverse a redemption (reverseRedemption) ### Assets - GET /assets - List assets (listAssets) - POST /assets - Upload an asset (uploadAsset) - GET /assets/{id} - Get an asset (getAsset) - DELETE /assets/{id} - Delete an asset (deleteAsset) ### Device Pairing - POST /devices/pairing - Start device pairing (startDevicePairing) - GET /devices/pairing/{pairingId} - Poll device pairing status (getDevicePairing) - POST /devices/pairing/claim - Claim a device pairing (claimDevicePairing) - POST /devices/pairing/{pairingId}/confirm - Confirm device adoption (confirmDevicePairing) - POST /devices/pairing/{pairingId}/reject - Reject device adoption (rejectDevicePairing) ### Device Auth - POST /devices/token - Mint a device token (issueDeviceToken) - GET /devices/jwks - Device JWKS (getDeviceJwks) ### Device Self - GET /devices/me - Get own device record (getDeviceMe) - POST /devices/me/heartbeat - Send a device heartbeat (deviceHeartbeat) - PUT /devices/me/peripherals - Declare peripherals (declareDevicePeripherals) - GET /devices/me/commands - Long-poll for commands (fetchDeviceCommands) - POST /devices/me/commands/{commandId}/progress - Report command progress (reportCommandProgress) - POST /devices/me/commands/{commandId}/result - Report command result (reportCommandResult) - POST /devices/me/events - Upload device events (ingestDeviceEvents) - GET /devices/me/certificate - Get local TLS certificate (getDeviceCertificate) ### Devices - GET /devices/printers - List printers (listPrinters) - GET /devices/media-catalog - Print capability & standard-media catalog (getDeviceMediaCatalog) - GET /devices - List devices (listDevices) - GET /devices/{deviceId} - Get device (getDevice) - PATCH /devices/{deviceId} - Update device (updateDevice) - DELETE /devices/{deviceId} - Delete device (deleteDevice) - POST /devices/{deviceId}/revoke - Revoke device (revokeDevice) - PUT /devices/{deviceId}/roles - Assign device roles (assignDeviceRoles) - POST /devices/{deviceId}/credentials/rotate - Rotate device credential (rotateDeviceCredential) - POST /devices/{deviceId}/commands - Dispatch a command (dispatchDeviceCommand) - GET /devices/{deviceId}/commands - List device commands (listDeviceCommands) - GET /devices/commands/{commandId} - Get a command (getDeviceCommand) - GET /devices/{deviceId}/events - List device events (listDeviceEvents) - POST /devices/{deviceId}/local-tokens - Mint a Local Command Token (mintLocalToken) ### Locations - POST /locations - Create location (createLocation) - GET /locations - List locations (listLocations) - GET /locations/{locationId} - Get location (getLocation) - PATCH /locations/{locationId} - Update location (updateLocation) - DELETE /locations/{locationId} - Delete location (deleteLocation) ### Reports - GET /reports/summary - Sales summary KPIs (getReportsSummary) - GET /reports/timeseries - Sales over time (getReportsTimeseries) - GET /reports/inventory - Inventory sell-through (getReportsInventory) - GET /reports/meta - Semantic model (getReportsMeta) - POST /reports/query - Run an ad-hoc query (runReportsQuery) - GET /reports/saved - List saved reports (listSavedReports) - POST /reports/saved - Create a saved report (createSavedReport) - GET /reports/saved/{id} - Get a saved report (getSavedReport) - PATCH /reports/saved/{id} - Update a saved report (updateSavedReport) - DELETE /reports/saved/{id} - Delete a saved report (deleteSavedReport) - POST /reports/saved/{id}/run - Run a saved report (runSavedReport) - GET /reports/dashboards - List dashboards (listDashboards) - POST /reports/dashboards - Create a dashboard (createDashboard) - GET /reports/dashboards/{id} - Get a dashboard (getDashboard) - PATCH /reports/dashboards/{id} - Update a dashboard (updateDashboard) - DELETE /reports/dashboards/{id} - Delete a dashboard (deleteDashboard) - GET /reports/templates - List standard templates (listReportTemplates) - POST /reports/templates/{key}/install - Install a template (installReportTemplate) ### Webhook Endpoints - POST /webhook-endpoints - Create a webhook endpoint (createWebhookEndpoint) - GET /webhook-endpoints - List webhook endpoints (listWebhookEndpoints) - GET /webhook-endpoints/{endpointId} - Get a webhook endpoint (getWebhookEndpoint) - PATCH /webhook-endpoints/{endpointId} - Update a webhook endpoint (updateWebhookEndpoint) - DELETE /webhook-endpoints/{endpointId} - Delete a webhook endpoint (deleteWebhookEndpoint) - POST /webhook-endpoints/{endpointId}/test - Send a test delivery (testWebhookEndpoint) ### Webhook Event Types - GET /webhook-event-types - List subscribable webhook event types (listWebhookEventTypes) ### Webhook Deliveries - GET /webhook-inbound - List recent inbound webhook events (ingress log) (listInboundWebhooks) - GET /webhook-deliveries - List webhook deliveries (listWebhookDeliveries) - GET /webhook-deliveries/{deliveryId} - Get a webhook delivery (getWebhookDelivery) ### Integrations - GET /integrations - List the integration marketplace (listIntegrations) - GET /integrations/connected-apps - List connected OAuth apps for the org (listConnectedApps) - GET /integrations/{id} - Get an integration (getIntegration) - DELETE /integrations/{id}/connection - Revoke a connected app (revokeIntegrationConnection) ## Live API Base URL: https://live.ticketlayer.com (staging: https://live.staging.t9r.dev). OpenAPI document: https://docs.ticketlayer.com/openapi/live.json. Reference pages: https://docs.ticketlayer.com/api/live/. ### Session - POST /session - Bootstrap a Live session (createLiveSession) - GET /session - Get the current session (getLiveSession) - DELETE /session - Destroy the current session (deleteLiveSession) - POST /session/order-access - Attach an order access token to the session (attachLiveOrderAccess) ### Queue - GET /queue/status - Get waiting-room status (getLiveQueueStatus) - POST /queue/join - Join the waiting room (joinLiveQueue) ### Sales Listings - GET /sales/listings - List active listings (listSalesListings) ### Sales Customer Auth - POST /sales/customer-auth/magic-link - Request magic link (requestSalesMagicLink) ### Sales Customer Tokens - POST /sales/customer-tokens - Exchange identity proof for customer token (createSalesCustomerToken) - POST /sales/customer-tokens/refresh - Refresh a customer token (refreshSalesCustomerToken) ### Sales Carts - POST /sales/carts - Create cart (createSalesCart) - GET /sales/carts/{cartId} - Get cart (getSalesCart) - POST /sales/carts/{cartId}/items - Add cart item (addSalesCartItem) - DELETE /sales/carts/{cartId}/items/{itemId} - Remove cart item (removeSalesCartItem) - POST /sales/carts/{cartId}/checkout - Checkout cart (checkoutSalesCart) ### Sales My Orders - GET /sales/my-orders - List my orders (listMySalesOrders) ### Sales Orders - GET /sales/orders/{orderId} - Get order (getSalesOrder) - GET /sales/orders/{orderId}/passes/{passId}/ticket.pdf - Download a ticket PDF (getSalesOrderTicketPdf) ### Sales Order Payments - POST /sales/orders/{orderId}/payments - Create order payment (createSalesOrderPayment) ### Sales Refund Requests - POST /sales/orders/{orderId}/refund-requests - Request refund or exchange (createSalesOrderRefundRequest) ### Sales Customers - POST /sales/customers - Create customer (createSalesCustomer) - GET /sales/customers/{customerId} - Get customer (getSalesCustomer) - PATCH /sales/customers/{customerId} - Update customer (updateSalesCustomer) ### Sales Presale Codes - POST /sales/presale-codes/redeem - Redeem presale code (redeemSalesPresaleCode) ### Sales - GET /sales/channel - Resolve a channel by domain (resolveSalesChannel) - GET /sales/events/{eventId} - Get event catalogue detail (getSalesEvent) - GET /sales/theme - Get channel theme (getSalesTheme)