Skip to content
Docs
Concept

A buyer on your website

The elements on your page talk to Live, Live holds the channel's publishable key, and a customer token escalates the Live session without ever reaching the browser.

The common case. Your page loads @ticketlayer/live (or the CDN loader) with a publishable key, the elements talk to Live, and Live holds the credentials. The page itself never sends a key on a request.

The credential. Live authenticates every call to the Backstage API with the channel's publishable key (tlpk_, low trust), held at the edge on behalf of the browser session. The channel is the key's, so nothing names it. When the buyer signs in, the customer token is kept in the Live session and never handed to the browser: it escalates the session; the publishable key still authenticates.

A buyer on your website: the elements talk to Live, Live holds the key1 List what is on sale: Your page (browser) to Live: GET /sales/listings (no key on the page); Live to Backstage API: GET /internal/live/listings (Live's service token, tlpk_ (held by Live), channel: the key's); Backstage API to Your page (browser): what the channel sells, in the low-trust view shape. 2 Make an order: Your page (browser) to Live: POST /sales/carts, items, POST /sales/carts/{id}/checkout (no key on the page, X-Live-Session); Live to Backstage API: POST /internal/live/carts, items, .../checkout (Live's service token, tlpk_ (held by Live), channel: the key's); Live to Backstage API: POST /internal/live/orders/{id}/payments (Live's service token, tlpk_ (held by Live)); Backstage API to Your page (browser): the order; Live keeps its order access token in the session. 3 Authenticate a customer: Your page (browser) to Live: POST /sales/customer-auth/magic-link (no key on the page); Live to Backstage API: POST /internal/live/customer-auth/magic-link (Live's service token, tlpk_ (held by Live)); A 15 minute code is emailed to the buyer.; Your page (browser) to Live: POST /sales/customer-tokens { magic_link, code } (no key on the page); Live to Backstage API: POST /internal/live/customer-tokens { magic_link, code } (Live's service token, tlpk_ (held by Live)); Backstage API to Live: customer token, 30 minutes (customer token); Live keeps the customer token in the session; the client never holds it. It escalates the session. The publishable key still authenticates every call.. 4 Read the order back: Your page (browser) to Live: GET /sales/my-orders (no key on the page, X-Live-Session); Live to Backstage API: GET /internal/live/my-orders (Live's service token, tlpk_ (held by Live), customer token); Live to Backstage API: GET /internal/live/orders/{id} (Live's service token, tlpk_ (held by Live), order access token); Backstage API to Your page (browser): the buyer's orders, or the one order the session may see1 List what is on sale2 Make an order3 Authenticate a customer4 Read the order backYour page (browser)LiveBackstage APIA 15 minute code is emailed to the buyer.Live keeps the customer token in the session; the client never holds it.It escalates the session. The publishable key still authenticates every call.GET /sales/listingsno key on the pageGET /internal/live/listingsLive's service tokentlpk_ (held by Live)channel: the key'swhat the channel sells, in the low-trust view shapePOST /sales/carts, items, POST /sales/carts/{id}/checkoutno key on the pageX-Live-SessionPOST /internal/live/carts, items, .../checkoutLive's service tokentlpk_ (held by Live)channel: the key'sPOST /internal/live/orders/{id}/paymentsLive's service tokentlpk_ (held by Live)the order; Live keeps its order access token in the sessionPOST /sales/customer-auth/magic-linkno key on the pagePOST /internal/live/customer-auth/magic-linkLive's service tokentlpk_ (held by Live)POST /sales/customer-tokens { magic_link, code }no key on the pagePOST /internal/live/customer-tokens { magic_link, code }Live's service tokentlpk_ (held by Live)customer token, 30 minutescustomer tokenGET /sales/my-ordersno key on the pageX-Live-SessionGET /internal/live/my-ordersLive's service tokentlpk_ (held by Live)customer tokenGET /internal/live/orders/{id}Live's service tokentlpk_ (held by Live)order access tokenthe buyer's orders, or the one order the session may seeLow trust: publishable keyHigh trust: staff, organisation key, deviceWhere the channel comes fromCarried on top: escalates, never authenticatesNot a credential

The four moments#

MomentWhat happensCredential
List what is on saleGET /sales/listings to Live. Live forwards it under the channel key it holds for the session.tlpk_, held by Live; the channel is the key's
Make an orderPOST /sales/carts, add items, POST /sales/carts/{id}/checkout, then POST /sales/orders/{id}/payments. The browser sends its X-Live-Session; Live forwards under the key. The queue gate sits in front of Live when the on-sale is gated.tlpk_, held by Live
Authenticate a customerPOST /sales/customer-auth/magic-link emails a 15 minute code; POST /sales/customer-tokens with { type: "magic_link", code } exchanges it. Live stores the customer token in the session at the edge.tlpk_ authenticates; the customer token is carried on top
Read the order backGET /sales/orders/{id} when the session holds an order access token for it, or GET /sales/my-orders once the session has been escalated with a customer token.tlpk_, plus the token carried on top

Why it is shaped this way#

  • The browser never sees a key. The elements talk to Live over a session, Live talks to the Backstage API under the key. A page that is a partner's site builder, a marketing site or a static export all work the same way.
  • The low-trust surface leaks nothing by construction. Every /sales/* response is a declared view, so what a buyer can see is a matter of what the view names, not of what a handler remembered to strip.
  • Live is the only way in. GET /sales/listings on Live is relayed to the same operation on the Backstage API, which serves it to Live alone: a page, an app or a partner's server calls Live.
  • The customer token is an escalation, never a login. There is no customer principal. A request for a buyer's orders that carries no customer token is refused with CUSTOMER_TOKEN_REQUIRED, and identity is read from the verified token, never from the request body.

Checkout on your page is hosted: the cart hands the session to the hosted box office's /embed/checkout in an iframe, which collects payment on its own origin. Sell tickets on your website walks through the page; the HTML, Vite and Next.js quickstarts are the code.