Skip to content

Changelog

Track SeatLayer API, Buyer SDK, Designer, webhook, and platform releases, behavior changes, fixes, and migration notes.

Updated View as Markdown

Notable changes to the SeatLayer API, embed SDK, and webhooks, newest first.

2026-10-08

  • Server API: inventory calls answer 503, not 500, when the event is briefly unavailable. Hold, extend, release, book, and the best-available calls now answer 503 with retryable: true, Retry-After: 1, and code: event_temporarily_unavailable when the event’s inventory restarts or does not answer in time. Release, book, and the hold check inside book retry once on their own first. A hold, block, or extend that answered this 503 may still have been made, so read the hold or the seats before repeating it. See which errors to retry.

2026-10-04

  • Browser SDK 0.106.1 (@seatlayer/js, React, Vue and Angular). Upgrade from 0.106.0; nothing to change in your code.
    • Fixed: the Control room shows the drag-a-box hint only when the room has a tool that takes seats by box. A watch-only room, such as a season seat map, no longer shows it.
    • Fixed: pages built from npm (React, Vue, Angular, @seatlayer/js) now report their SDK version with each chart load, as CDN pages already did.
    • Added: seatDisplayParts in @seatlayer/core/core/sections. Seat labels are unchanged.

2026-10-02

  • Browser SDK 0.106.0 (@seatlayer/js, React, Vue and Angular): the full Control room, in Vue and Angular too. Upgrade from 0.105.1; every new option is additive.
    • Vue and Angular: SeatManager is now on @seatlayer/vue/manager and @seatlayer/angular/manager, with the same board and options as React and @seatlayer/js/manager.
    • onOpenDesigner (Angular: the (openDesigner) output). When it is set, Sections on a chart that has no sections offers “Open the designer”. Leave it out and the empty state keeps its words only.
    • Venue view captions: a sold-out section turns solid grey and reads SOLD OUT. A section that is all blocked or all reserved is hatched and reads BLOCKED or RESERVED. A closed one reads CLOSED, with its opening time when it has one.
    • Seat history shows how long a seat sat in a cart. Saved selections show the date the chart changed, when the API sends it.
    • Changed: the Rows and Ticket types pickers add free seats only. A table with chairs in a cart is no longer locked; “All …” leaves it out and says so. A reservation that ended on its own stays in the Reserve list, greyed, until the room reloads.
    • Fixed: a free ticket type reads “Free” in the buyer’s price list and phone price rail, not “$0”. Channels counted sold seats as free. The sold-out alert fired on blocked sections. Seat history closed on live changes. The seat card asked for a seat’s history several times while the room opened.

2026-10-01

  • React, Vue and Angular 0.105.1: the React SeatManager passes the new options through. In 0.105.0 the React component accepted the Control room options listed below but did not hand them to the room, so they had no effect. 0.105.1 passes every one of them on. @seatlayer/js 0.105.1 is the same as 0.105.0; upgrade the React package to use the options from React.
  • Browser SDK 0.105.0: the embedded Control room. SeatManager gains optional options, and every one of them is additive: leave them out and the room behaves as it did on 0.104.1.
    • Showing the room: kpis: false hides the room’s own number strip when your page shows the numbers itself. timeZone shows times in the event’s zone. mapInsets keeps the map clear of your own chrome.
    • Opening at a place: focusSection, focusSeat, focusSeats and focusCategory open the room framed on seats.
    • Telling the room about the sale: sale (the host’s words, tone, when sales opened and the buyers’ page) and organizationName.
    • Following the room: onRoomStateChange reports the room’s link state, such as paused or offline, so your header can say it too. onOpenOrder lets the room’s search open a booking in your own orders page. See Embedded Control room.
  • Browser SDK 0.105.0: the buyer picker. On a phone, the fitted venue keeps clear of the level stack. A ticket type whose name is too long to sit beside the quantity stepper moves to its own row instead of being cut. The picker’s chrome follows the buyer’s language once it loads. @seatlayer/react, @seatlayer/vue and @seatlayer/angular 0.105.0 pin this release.
  • Doors time on events. Events gain an optional doorsAt (epoch ms, read in the event’s timezone). Set it with PATCH /v1/events/{key}, or send null to clear it. A doors time after the event’s start is refused with 422 doors_after_start. Events without one return doorsAt: null.

2026-09-30

  • API: the event log names its seats. GET /v1/events/:key/log pages now carry displayLabels, the name each label reads as where that differs from the label, such as a general admission area’s places. labels are unchanged. See Audit log.
  • Webhooks: seat.released says when single tickets were refunded. When some tickets of a SeatLayer order are refunded or cancelled from the dashboard, the seat.released for exactly those seats carries source: "ticket_refund" and the order’s bookingRef, so you can match the release to the order; the rest of the order stays booked. Every other release sends the same payload as before. See seat.released.

2026-09-29

  • Browser SDK 0.104.1: the buyer’s language on @0 embeds. A page that loads the SDK from the major channel (seatlayer-js@0/…) showed every buyer the English map, because the language file was requested under the channel path, where it does not exist. The SDK now loads its language file, the 3D view, the seat view and the checkout card from its own release directory, so they always match the running bundle and no longer take an extra redirect. If that request fails (for example a Content Security Policy that allows only the @0/ path), it falls back to the old address, as before. Pinned, self-hosted and npm installs behave as before. @seatlayer/react, @seatlayer/vue and @seatlayer/angular 0.104.1 pin this release.

2026-09-28

  • Browser SDK 0.104.0: level buttons, taps that keep the seat in view, updates behind proxies. A multi-level chart now shows one stack of level buttons above the zoom buttons instead of the “Levels:” menu, and a wide map keeps room for it on the right. “All levels” stays a vertical stack unless the chart is set to “As drawn” in the Designer. The mini-map steps aside when the whole venue is in view. On a phone, the first tap on a table chair keeps that chair on screen while the map zooms in. When a buyer’s network blocks the live connection (some proxies, VPNs and antivirus tools do), the map checks for seat changes every 15 seconds while the page is visible, and goes back to live updates as soon as the connection works. A section name size set in the Designer is now used in the whole-venue view. Removed: the retired isometric and 2.5D projections. setViewMode() and initialView still accept those values and show the flat map, and @seatlayer/core no longer exports createPerspectiveCamera and its projection helpers. @seatlayer/react, @seatlayer/vue and @seatlayer/angular 0.104.0 pin this release.
  • Browser SDK 0.103.0: venue signs and names on the buyer map, sessions that renew. The buyer map now draws what the Designer places for wayfinding: venue icons, gate signs, map badges and the step-free route. Named areas and landmarks such as a dance floor, a bar or an entrance keep a readable name when the whole venue is in view, and drop it only when the shape is too small to hold it. SeasonPicker and PerformanceGroupPicker renew their 30-minute buyer session before it ends, and a session that has expired is asked for once instead of on every refresh. The idle card now reads “Your session expired” with a “Show latest seats” button, in all 43 languages. A performance group’s seat list is revalidated with its ETag. @seatlayer/react, @seatlayer/vue and @seatlayer/angular 0.103.0 pin this release.

2026-09-27

  • Browser SDK 0.102.0: aisle seats, standing areas sold as one box, booth details. Aisle seats are marked on the seat card and the hover card, and best available takes an opt-in preferAisle. A standing area of up to 100 guests can be sold as one box: the buyer books the whole area or picks a party size, and chooses the ticket type. Standing areas can hold wheelchair places, and under the wheelchair filter an area with none free says “No wheelchair space”. Buyer cards show a booth’s type, the entrance and chair numbers. SeasonPicker takes a header option, and its map now fills its box. PerformanceGroupPicker supports hosted checkout. On a 404, onError now receives the API’s explanation, and developers see it in a console.warn; the buyer’s message is unchanged. A refused public bootstrap is asked once, not retried. @seatlayer/react, @seatlayer/vue and @seatlayer/angular 0.102.0 pin this release.

2026-09-25

  • Browser SDK 0.101.0: 3D that moves like a venue. At the overview a drag turns the venue, and the near side follows the pointer. Zoomed in, a drag moves you; right-drag, Shift-drag or a two-finger twist turns. The seat card opens on the view from that seat. After a pick, a figure sits in the chosen seat under a spotlight. Section tags carry the category colour and a free wheelchair-space count, and gates are signed with an arrow on the ground. When an app sends its own prices, the seat card shows them, the same as the price list. No breaking changes. @seatlayer/react, @seatlayer/vue and @seatlayer/angular 0.101.0 pin this release, and the Flutter package seatlayer 0.12.0 loads it.

  • Browser SDK 0.100.0: 3D on phones, seat types in 3D, arena floors. On a phone, the first tap in 3D zooms to the seats and a second tap picks one. Wheelchair, companion, access, limited-view and premium seats show their icon in 3D, as in 2D. On desktop, hovering a seat in 3D shows the same seat card as the 2D map. Picking a seat no longer moves the camera, and aisles run straight through a section. In estimated arenas, floors stay level, straight banks stand as one tier, and floor seats face the stage. No breaking changes. @seatlayer/react, @seatlayer/vue and @seatlayer/angular 0.100.0 pin this release, and the Flutter package seatlayer 0.11.0 loads it.

2026-09-24

  • Browser SDK 0.99.0: host prices in mobile apps, season prices for managers, steadier 3D. Apps that show the map through the mobile bridge can pass their own prices with the pricing option or the picker.setPricing command, so the map, seat card and cart show the price the app charges. The server still prices every hold. SeatManager takes categoryPrices (and setCategoryPrices() on the handle) to show a different price on hover, or null to hide it. In 3D, the view keeps responding to drag, pinch and wheel while a seat card is open, and only a tap outside the card closes it. The Find count now sits inside the Find box. Stage captions take a direction (horizontal, vertical or automatic), and estimated theatre tiers sit at more realistic heights. No breaking changes: FLOOR_STACK_MIN_SURFACE_PX stays exported but is no longer used. @seatlayer/react, @seatlayer/vue and @seatlayer/angular 0.99.0 pin this release.

  • Seasons from your own server. Secret-key REST routes now list season holders, refund, cancel, cancel one date, resend tickets, manage hosted renewal links and reminders, and read season reports and CSVs. New webhooks season.order.paid and season.order.refunded tell your system when a season sale is paid or refunded. See Run the year from your server.

2026-09-23

  • Browser SDK 0.98.0: easier 3D navigation and indoor halls. Wheel and pinch zoom toward the point under the pointer, tapping a stand frames the whole stand, and tapping a seat when zoomed in picks it without moving the camera. “View from here” lands behind the seat, the picked seat stays easy to spot, taken seats share one muted grey, and stadium overviews show seats. Drawn walls now form a room at any size, and a zone and section with the same name are labelled once. New for managers: SeatManager takes unavailableObjects and unavailableObjectsReason to show extra seats as unavailable, with setUnavailableObjects() on the handle. In Select mode a row-label tap now follows the same selection rules as a seat tap. @seatlayer/react, @seatlayer/vue and @seatlayer/angular 0.98.0 pin this release.

  • Season ticket sales are reported on the season. Event totals, the Orders list and orders.csv no longer include season ticket orders; see the season’s Reports tab.

  • Browser SDK 0.97.0: 3D for every chart, clearer closed states, six more languages. Charts drawn without 3D details now open in 3D with estimated tiers and stands, and five new playing surfaces (pitch, track, diamond, court, ring) draw on both the 2D map and in 3D. When an event exists but isn’t selling, the map, card and button all say the same thing: “Sales haven’t opened yet”, “Sales are paused” or “Sales are closed”. An unknown or removed event shows “This event isn’t available” in place of the map, with no retry button. Buyer text now also ships in Vietnamese, Thai, Indonesian, Malay, Korean and Hindi. No breaking changes. @seatlayer/react, @seatlayer/vue and @seatlayer/angular 0.97.0 pin this release.

2026-09-22

  • Hosted Ticketing: refund or cancel any order from one place. Each order has one Refund or cancel… action. Refund in full or in part through the gateway the buyer paid with; a full refund puts the seats back on sale, a partial one leaves them sold. Cancel without refund covers money handled outside SeatLayer, such as a refund in the gateway dashboard, a lost dispute or cash returned at the counter; it releases the seats and voids the tickets. Refunds made in the Stripe or Razorpay dashboard sync back to the order. See Refunds and cancellations.

  • Box office: printing, order lookup and a staff role. The counter prints tickets on an 80 mm roll or A4, chosen once per device. Find order searches by name, email, phone, order number or ticket code, and reprints and resends are logged on the order. A new Box office team role can sell, find orders, print, email, change seats and check people in, and the server refuses anything else, including refunds. See Box office and Staff roles.

  • Browser SDK 0.96.0: a clearer checkout card. The hosted checkout card now lists every ticket with its section, row and seat, its category and price tier, and the order total in a footer that stays in view with one button to continue to payment. It asks for one email and an optional name, marks test mode in one line, and becomes a bottom sheet on phones, in light and dark. Checkout follows a payment redirect only when it is a secure https URL. New optional fields: CheckoutLineItem.categoryLabel and tierLabel, CheckoutOrderSummary.lines, and CheckoutMount.event. @seatlayer/react, @seatlayer/vue and @seatlayer/angular 0.96.0 pin this release.

  • Browser SDK 0.95.1: the whole venue fits the map. The overview fit now measures section blocks, standing areas and shapes by their outline, so a chart whose blocks pad beyond their seats opens fully in frame instead of cutting the outer blocks at the edge; curved sections count only the arc they draw. With chrome: 'minimal', SeatManager keeps the fitted venue clear of its zoom buttons when there is room. Row letters at the screen edge no longer cover a seat number. @seatlayer/react, @seatlayer/vue and @seatlayer/angular 0.95.1 pin this release.

  • Browser SDK 0.95.0: sold-out ticket types say so, a lost hold no longer ends the session, and the control room has one colour language. For buyers, a ticket type with nothing left reads “Sold out” and is not offered for best seats (and a best-seats call for it answers sold_out without a request); a saved hold that can no longer be resumed after a reload shows a short notice and the picker carries on; and chart-load failures report why they failed. In the control room, a legend that stays on at every zoom carries a Colour by: How full · Ticket type switch that colours the section blocks, the seats and the minimap together (it opens on How full); the minimap follows sales as they happen; Full screen is a proper toolbar button; and a table sold as one unit shows all its chairs as sold. SeatManager gains chrome: 'minimal' (just the map, zoom and Venue), onAreaClick for standing areas in Select mode, focusSection(label) and colourBy. @seatlayer/react, @seatlayer/vue and @seatlayer/angular 0.95.0 pin this release.

2026-09-21

  • A buyer who reloads mid-hold keeps their seats. Minting a buyer access session again with the same clientRequestId now moves the earlier session’s live holds to the new session. Before, the holds stayed with the revoked session and the new session could not resume them. Behaviour change: a live session that names a hold another session owns now gets the same answer as for a hold that does not exist, instead of 401 buyer_access_invalid. That is 404 hold_not_found on resume and checkout, 409 cannot_extend on extend, and 409 conflict on a replacement hold. Revoked tokens, and expired sessions resuming another session’s hold, still get 401.
  • Browser SDK 0.94.0: the control room gets one way to choose seats, a map that reads at every zoom, and a picker that pauses politely. Block, Categories, Channels and Select share one seat chooser (tap · drag box · lasso · category · section · rows · seat list · Find), and Categories gains “Reset to chart defaults”. The map has a Find box and a View menu (seat labels, row labels, category colours, channel colours, booking momentum, remembered per browser), a hover card that says status · channel · for sale, a crumb, zoom pills and a minimap; section blocks wear an availability band and their state word, and a dense chart opens on its blocks. A control-room session that can no longer be renewed ends with one “Try again”. For buyers, the seat picker pauses after thirty idle minutes and refreshes in place, and its chart-load telemetry counts page loads and socket reconnects. @seatlayer/react, @seatlayer/vue and @seatlayer/angular 0.94.0 pin this release.

2026-09-19

  • Publishing a chart no longer updates linked events by itself. Every event keeps its current map until it is updated explicitly: in the dashboard’s post-publish dialog, one checkbox per event, or per event with POST /v1/events/{key}/update-chart. Behaviour change for secret-key publishes, which used to move events with no bookings automatically. The publish response gains linkedEvents (each event still on an older map, with its booked, held and blocked counts and whether the update is safe or reviewed); refreshedEvents is now always 0.
  • Publish answers sooner. The dashboard’s publish reports live as soon as the publication is saved, and new events can be created immediately after publish. bundlePending in the status shows the short window while the buyer map finishes preparing.

2026-09-18

  • Browser SDK 0.93.0: the embedded Designer fits short and padded hosts. height: 'fill' no longer imposes a 480 px floor (minHeight now defaults to 0 and an explicit value is still honoured) and fills the host’s content box, so a padded or bordered panel no longer overflows. The loading placeholder is the same quiet light shell the Designer paints, sized to the embed box. A hosted checkout the organizer’s payment provider refuses now tells the buyer so, instead of a generic message. @seatlayer/react, @seatlayer/vue and @seatlayer/angular 0.93.0 pin this release.

2026-09-16

  • Browser SDK 0.92.5: the buyer page says why a sale is shut. An event that is not on sale yet says so (“Tickets for this event aren’t on sale yet”) instead of “sales have ended”; paused events say paused. An event whose sales really have finished is unchanged.
  • Browser SDK 0.92.1: Block mode marquee starts from anywhere inside a seating block. In Block mode a drag that begins anywhere inside a seating block draws a marquee, and a drag that begins on the floor moves the map.
  • Browser SDK 0.92.0: one seat-state language in the organizer control room. On the manage map a free seat now draws in its category colour, a sold seat in neutral grey, a held seat in gold with a clock once you zoom in far enough to read it, and a blocked seat with a cross. The same four states are used everywhere the organizer sees seats.
  • Dragging empty space moves the map, even with seats selected. A drag that starts on an empty floor, an aisle or the gap between rows now pans the chart. Marquee selection starts only from a press on a seat, so you no longer lose a selection by trying to move the view. Section shapes no longer swallow the wheel or the drag either, so zooming and panning work over a section the same way they work over empty floor.
  • A Clear button in the map toolbar drops the current selection in one click, and the notices that used to stack in different corners now share a single pill lane at the top centre of the map.
  • Channels follows your light or dark theme. The dialogs, the preview banner, the status flags and the staged-changes bar all read correctly in both themes. “+ New channel” stays pinned while the list scrolls, and the buyer link, once revealed, has a Copy button next to it.

2026-09-15

  • Browser SDK 0.91.1: multi-floor charts name every seat by its own floor. On charts with stacked floors, a seat on an upper floor now carries that floor’s section name on the confirm card, the tray chip and the 3D caption instead of the ground floor’s. Booths and table seats keep a tappable hit target at every zoom level, and the section overview chips show section names rather than ordinals. Charts with a single floor are unchanged.
  • Hidden and closed sections are consistent on multi-floor charts. Hiding or closing a section now removes the same seats from the map and from sale on every floor. Events materialized before this release keep their stored section labels in reports and section tools until the chart is republished.
  • Events carry their after-payment destination. checkoutReturn (seatlayer | page) is stored on the event and set from Setup → Checkout inside the payment-gateway card; a return to your own page still requires the website origin to be declared for the organization.
  • Embed origins are observed, not typed. The installation check records the origin of a published page that loads the widget, so the organizer can declare it with one click instead of pasting it.
  • Door list and orders export. The door list has one row per guest with the attendee name, phone and booking-form answers; orders.csv heads each booking-form question as its own Q: column (capped at 20).

2026-09-13

  • Browser SDK 0.88.1: the picker names a maintenance pause and how long it should last. When the API answers 503 maintenance_mode, the buyer picker now says “Booking is paused for maintenance. Please try again in about N minutes.” (or shows the operator’s own notice) instead of reporting that the seats were just taken. ApiError carries the new retryAfterS and notice fields on a 503, the mobile bridge forwards them, and the message is translated in all 37 locales.

2026-09-12

  • Publishing a chart returns before its events are rebuilt. POST /v1/charts/{id}/publish now answers as soon as the new version is live, and the events pinned to that chart are moved onto it in the background. Two additive fields carry that:

    • pendingEvents: events handed to the background update.
    • publishedSha: the publication those updates are about.

    refreshedEvents still reports events refreshed inside the request, so it is 0 while pendingEvents is non-zero. manualUpdates and eventsNeedingManualUpdate keep their meaning: events a background update may not touch (a bound Event configuration, for example). An event that turns out to need a reviewed manual update, such as one holding bookings or holds, is reported by the status endpoint rather than in the publish response, along with its pricing review, so the publish response stays fast.

  • New: GET /v1/charts/{id}/publications/{sha}/status. How far one publication has travelled onto that chart’s events:

    {
      "sha": "…",
      "complete": true,
      "events": [
        { "key": "ev_…", "name": "Opening night", "state": "done", "outcome": "refreshed", "at": 1757671234567 }
      ]
    }

    state is pending, done, skipped, failed, or unknown (this publication never touched that event). complete is false only while something is still pending, so a failure is a finished state that needs attention rather than more waiting. It is always answerable: a publication with nothing pending returns an empty list with complete: true, so a client can poll it unconditionally. Charts with more than 200 events answer truncated.

    The endpoint is reachable with a secret key, but it is deliberately not part of the generated server SDKs yet: the per-event state vocabulary may still change while the propagation work continues.

    Nothing was removed, and no existing field changed shape. A client that ignores the new fields behaves exactly as before.

2026-09-07

  • Buyer SDK 0.86.2 (@seatlayer/core, @seatlayer/js, CDN, React, Vue, and Angular). Row numbers keep to the seats they belong to. Rows outside the focused section wait for the seat numbers before they are drawn, a focused stand keeps its numbers at the row-band rung, and a focused section framed barely past the venue fit, a whole floor, waits for the seat numbers too.
  • Buyer SDK 0.86.1 (@seatlayer/core, @seatlayer/js, CDN, React, Vue, and Angular). Section names are drawn in one grey and set smaller, 6px on a phone and 8px on a desktop, and they grow by at most 1.15x as the map is zoomed. A vertical stage caption reads top to bottom. The phone fit keeps a 10px margin to the edge of the screen, row numbers appear only alongside the seat numbers, and a focused section can always be zoomed into. The minus button walks back out to the whole venue when the current fit already shows seats.
  • Buyer SDK 0.86.0 (@seatlayer/core, @seatlayer/js, CDN, React, Vue, and Angular). Section names are centred inside their section and drawn in the category hue, and sold-out sections read as pale blocks. Row-band lines are available on desktop and phone, with the hand-over to seats kept under the zoom ceiling, and the phone map keeps clearance above the zoom column. Picking the first ticket no longer moves the camera, while the beacon and count badge dive to the buyer’s own seats. Closed and sold-out blocks are inert to taps, a held seat offers a Remove card, the seat card drops its distance line, and best-available skips seats that are not for sale.
  • Buyer SDK 0.85.2 (@seatlayer/core, @seatlayer/js, CDN, React, Vue, and Angular). The phone zoom column keeps its + and − controls in fixed slots, and a disc that reaches its limit fades out in place instead of shifting the column. The map camera now stays over the venue: a venue smaller than the screen never leaves it, a larger one leaves at most a third of the screen blank, and the leash is a hard stop rather than a snap-back.
  • Buyer SDK 0.85.1 (@seatlayer/core, @seatlayer/js, CDN, React, Vue, and Angular). Focused category rows remain visible after narrow-screen map settling and panning, and tapping a selected-ticket card keeps the mobile cart sheet open so buyers can inspect several chosen seats in sequence.
  • Buyer SDK 0.85.0. Section selection can reveal category-coloured row bands before individual seats, with neighbouring sections remaining visible as the map moves. Chart authors can choose row detail or direct seat detail. Authored section label positions are respected and overview fills are darker.
  • Mobile cart actions. Opening a seat confirmation card no longer replaces the footer action with “Confirm or cancel this seat”. Adding or cancelling a candidate restores the normal cart action and selected-ticket total.
  • Chart editing and transfer. Section review tools support a repeatable review workflow. Portable chart exports preserve editable chart data while excluding private reference images and review metadata.

2026-09-06

  • Buyer SDK 0.84.1 (@seatlayer/core, @seatlayer/js, CDN seatlayer-js@0.84.1; wrappers at the same version). The phone round’s second pass, again validated on a real iPhone. Phone sheet. The sheet stacks above the loading skeleton, so the handle is whole while the chart loads, and the handle steps aside while a confirm card is up. Adding a seat now reads as one moment: the button sweeps, the seat’s chip flies to the cart total, the count and total swell as it lands, and only then does the map settle back. Tapping a ticket card takes the map to that seat and puts the sheet away. Map controls. The phone’s control column grows upward from the corner: at the whole-venue view only the accessibility and zoom-in discs show, and the back-out discs appear above them, so the disc under the thumb never moves. The tapped-section card is gone on every layout. Panels. The accessibility menu’s info button sits with its label and the free count stands clear of its switch; the find-seats-together card’s info button follows its title. Light-theme map discs are tinted rather than white.

  • Buyer SDK 0.84.0 (@seatlayer/core, @seatlayer/js, CDN seatlayer-js@0.84.0; wrappers at the same version). The phone round, validated on a real iPhone. Phone sheet. The bottom sheet has three resting heights (the footer alone, the cart, the whole panel), and its handle is a single disc straddling the one line the sheet draws, which is now the sheet’s top edge: the map runs up to it and nothing is painted above it. Adding a seat always leaves the sheet at the footer, so the chart is never pushed up mid-pick; a tap anywhere on the footer brings the cart back, and the count and total swell when a ticket lands. Cart lines are shortened by the fact rather than clipped mid-word the first time the cart is shown. Map controls. The four discs in the phone’s control column are one size, the back-out discs leave the column at the whole-venue view, and the zoom-in disc leaves it once seats are big enough to tap. Light-theme discs are tinted rather than white. Seat numbers. A seat that is tapped and then cancelled, or deselected from the cart, gets its number back at once instead of when the camera next moves.

  • Buyer SDK 0.83.0 (@seatlayer/core, @seatlayer/js, CDN seatlayer-js@0.83.0; wrappers at the same version). A buyer QA round across the picker’s map, panel and 3D view. Map. A seat nobody can take is inert: sold and other buyers’ held seats are one flat grey disc that no longer answers a press, shows a hover card, or wears an accommodation glyph or ring, and a press that lands on empty canvas does nothing at all (the zoom-in cursor now appears only over the chart). The selection tick is drawn inside the seat’s disc rather than over its markings, the focus ring comes down when the buyer steps the zoom back, and the hover card is larger and carries every per-seat attribute. Seat attributes and notes. Seat types ship a shared pictogram set, and a seat’s notes are drawn as full-bleed bands on every buyer popup; a cart line states its attributes once, in words. Thirteen new strings across all 37 locales. Phone. The bottom sheet is now one surface with the desktop panel: the same footer block, the same cards, a pill handle on the edge, a capped list that scrolls instead of clipping. The hold clock lives in the header only. The map gets three zoom controls (+, −, fit) with an honest disabled state at the whole-venue fit, kept clear of the open sheet, and the price rail runs out past its last chip instead of slicing it. Accessibility. The accessibility control moved into the buyer’s map control column, where it stays reachable in 3D; the menu it opens stays inside the screen, scrolls when it must, and gives each accommodation one readable line (icon, short name, count, toggle). Colourblind mode now remaps the accommodation ring ink. The “find seats together” card fits its title on one line. 3D. Orbit direction is fixed at the source, −/+ dolly symmetrically under a widen-only envelope, and the camera controls are named in the buyer’s language. Leaving the booked overlay hands back a working picker. Native hosts. The picker snapshot carries map.atVenueFit and map.canZoomIn (both optional) so a native shell can draw its own zoom chrome truthfully. Multi-level venues. The level selector is a compact rail that fits its labels, keeps its own chrome clear of the seating and of the narrow map controls, and holds a selection made on one floor while the buyer reads another. A venue whose floors are shown together lays out as one combined plan, and the minimap tints and frames the focused section from the same source as the map. Entering or leaving fullscreen no longer re-measures a layout that did not change. Optional section prices. A section summary may carry no price range at all; the card now states what it has instead of rendering a range built from missing numbers, and section codes survive the trip to the card.

2026-09-05 (night)

  • Buyer SDK 0.81.0 (@seatlayer/core, @seatlayer/js, CDN seatlayer-js@0.81.0; wrappers at the same version). A Season the organizer has made public can now be embedded with no backend. Omit buyerAccessToken and buyerAccessTokenProvider and the Season picker mints its own anonymous, origin-bound session; that session is public-sale only and can never reach a private channel or a renewal allocation, and an explicit token always takes precedence. publicKey is accepted for parity with the Event picker’s snippet shape. It is not sent and is not a credential, because a public Season session is authorized by the Season key plus the browser’s registered Origin. Three refusals reach onAccessUnavailable with their own reasons: audience_not_public, sales_not_open (retryable) and origin_not_allowed; the picker also states each one in plain language, so a host that handles none of them still shows the buyer something true. When the Season publishes per-category package prices, the server price wins: the hero prices each category for the whole package, the confirm card totals the selection at those prices, and host-authored display-only offer copy is not shown beside them. With no server prices the previous wording is unchanged. New checkout option: 'handoff' stays the default and downloads no payment code, while 'hosted' opens the same payment card the Event picker uses once the atomic hold is committed, one order with one ticket per performance, and confirms through onOrderConfirmed. onContinue still fires either way. A Season priced on the organizer’s own backend reports checkoutMode: 'server' and stays on 'handoff' rather than starting a payment SeatLayer cannot complete, and returnUrl is honoured only for the organizer’s declared embed domains.

2026-09-05 (evening)

  • Buyer SDK 0.80.3 (@seatlayer/core, @seatlayer/js, CDN seatlayer-js@0.80.3; wrappers at the same version). A second tap on a seat already under a hold now asks before releasing it on native shells that opt into seat.retap; it used to be released with no question. The overview beacon rings the buyer’s seat itself rather than a point lifted toward the section’s middle. Nothing changes for web hosts.

2026-09-05 (later)

  • Buyer SDK 0.80.2 (@seatlayer/core, @seatlayer/js, CDN seatlayer-js@0.80.2; wrappers at the same version). Three additive bridge commands for native shells that draw their own chrome over the map, each gated on its presence in the hello command table. picker.setSelectionFocus names the seat a native card is asking about, so it is painted as the candidate the way the web card paints it: thick double ring, halo, neighbours paled. picker.setBlockedRegions takes the rectangles of native chrome laid over the map and swallows any pointer sequence that starts inside one before the map’s gesture machine or canvas can see it; on iOS 26 a tap on a native control reaches the web view regardless of the platform-view gesture boundary. picker.frameSeat pans and never zooms, so a seat rests at a fraction of the band the viewport insets leave clear, answering with the pan it made and the buyer’s own gesture count so a later re-frame can be refused once the buyer has moved the map. Nothing changes for the web picker. The wide confirm card now clears the seat it names when it closes.

2026-09-05

  • Buyer SDK 0.80.1 (@seatlayer/core, @seatlayer/js, CDN seatlayer-js@0.80.1; wrappers at the same version). A live hold is told once, by the header countdown: the “held tickets restored” notice on returning from checkout and the “N secured · yours for m:ss” strip above the pay button are gone on every layout, and the ✕ on each held line remains the way to release one seat. The phone is no longer offered a hold extension in the final minute; the wide layout keeps the docked control. The seat-session recovery card now says “The seat map timed out”, that any seats being held stay held, and that Refresh brings the map back. The map’s zoom stack is “+” and “−” on every layout; the 3D view keeps its own Fit view. The price rail no longer narrates other buyers’ bookings, because the live “left” counts and the map already carry that. A second tap on a seat already in the order keeps the seat and opens its card, and a native shell can pin whether entering a section dims the rest of the venue. Nine locale keys are removed across all 37 languages; hosts that override picker.securedCount, picker.holdReassurance, picker.change, picker.heldTicketsRestored, picker.fitToScreen, picker.liveAvailability or picker.seatsJustTakenInCategory can drop those overrides.

2026-09-04 (late)

  • Buyer SDK 0.80.0 (@seatlayer/core, @seatlayer/js, CDN seatlayer-js@0.80.0; wrappers at the same version). The client’s testing round. The count beacon that marks a buyer’s seats from the venue overview stands on the buyer’s own section rather than the zone’s label, and flies there; it and the other controls inside the map answer a finger, not only a mouse. The seat card opens one per seat on click as well as hover, the locate ring travels with its seat, and a host that draws its own seat card can tell the picker to stand its card down.

2026-09-04 (night)

  • Buyer SDK 0.79.0 (@seatlayer/core, @seatlayer/js, CDN seatlayer-js@0.79.0; wrappers at the same version). When a buyer’s hold runs out while they are still on the map, the picker now shows one card over the live map that names the seats that were released and offers “Choose seats again”, which re-reads availability and returns the map to the venue. The seat-session recovery screen uses the same card: the map stays visible behind a light veil, every reason offers one action, and “Refresh” re-establishes the session in place. An open seat card, table dialog or standing-area prompt closes when either card appears. Opening the picker no longer fetches a seat snapshot the live connection already delivered. The test-mode chip is readable on dark maps, the widget no longer lets iOS resize its type, the full-screen frame follows the visible viewport height, and light mode reaches the picker’s rounded corners in every full-screen route. Internally the picker and controller are split into smaller modules; the public API is unchanged.

2026-09-04 (evening)

  • Buyer SDK 0.78.0 (@seatlayer/core, @seatlayer/js, CDN seatlayer-js@0.78.0; wrappers at the same version). A buyer’s own hold no longer reads as another buyer taking the seat: the live feed exempts seats whose hold request is still in flight, so the seats stay in the order and the “someone else took a seat” notice does not fire on the device that pressed Continue. On phones the seat card is a fixed bottom sheet; the map lifts a low seat into view above it and drops back when the card leaves, the map behind it blurs with the tapped seat kept clear, and a tap outside the card closes it. Entering a section no longer dims the rest of the venue on phones, the section bar under the map is gone there, and the venue overview paints each block’s number beside the zone names on every layout. The count beacon over a buyer’s seats is a tap target that flies to those seats. “All prices” restores every section and the previous framing. The full-screen control hides where the picker already fills the phone. Tapping a seat already in the order opens the card with a Remove action instead of dropping it silently. Opening the picker issues its availability and live-feed reads alongside the chart load and no longer fetches the seat snapshot separately.

2026-09-04

  • Buyer SDK 0.77.2 (@seatlayer/core, @seatlayer/js, CDN seatlayer-js@0.77.2; wrappers at the same version). The seat card’s category band no longer prints the remaining count; it is a touch taller with larger type and the price kept clear of the card’s edge. On the phone the collapsed cart bar shows the whole of its buttons again, the chevron leaves the collapsed bar, and Find seats and Continue are larger, right-aligned buttons. The count beacon that marks a buyer’s seats from the overview now sits over those seats rather than over the section’s name, which could land a block away.

2026-09-03 (night)

  • Buyer SDK 0.77.1 (@seatlayer/core, @seatlayer/js, CDN seatlayer-js@0.77.1; wrappers at the same version). On the phone the collapsed cart bar’s grab handle sits clear of its buttons. Native hosts get the accessibility experience the web menu already had: turning a filter on through picker.setAccessibilityFilter flies to the matching spaces or keeps the overview with a hint, picker.focusAccessibilityFilter re-runs that flight, picker.focusNextAccessibleSection steps from section to section, and each snapshot section reports its free accessible places under accessibleFree (capabilities accessibility-focus-v1, section-access-counts-v1). With a filter on, opening a section frames its matching spaces instead of the whole stand. picker.bestAvailable now lands the map on the seats it held, with their neighbours, on every surface.

2026-09-03 (evening)

  • Buyer SDK 0.77.0 (@seatlayer/core, @seatlayer/js, CDN seatlayer-js@0.77.0; wrappers @seatlayer/react, @seatlayer/vue, @seatlayer/angular at the same version). The phone seat card is louder and shorter: section, row and seat sit in three equal centred cells, the category band is the category colour itself with an ink chosen per colour, and a seat with no photograph drops the empty strip and keeps 3D as a square beside Cancel. Inside the 3D venue the passport, compare and view-from-here controls share one row. A seat tap in 3D steps the camera in before the card opens, and seat numbers print on readable plates. The accessibility filter keeps the sections holding free spaces lit with a count badge, offers a hint when they span the venue, and turns the free count into a way to jump between them. A best-seats pick frames the seats it found with their neighbours, also under reduced motion, and every automatic zoom stops at a thumb-sized seat. The empty cart bar prints the from-price large with a rounded Find seats button.
  • Fewer requests on open. The map opens faster with fewer requests: when nothing changed it makes one map read and one availability read, and live updates paint from the first message instead of reading again.
  • Bootstrap response. chartDelivery now carries bytes and cache only.

2026-09-03

  • Buyer SDK 0.76.0 (@seatlayer/core, @seatlayer/js, CDN seatlayer-js@0.76.0; wrappers @seatlayer/react, @seatlayer/vue, @seatlayer/angular at the same version). Focusing a seat dims only the seats outside its neighbourhood, so the row and its neighbours stay readable. A price or accessibility filter recedes the seats it excludes instead of hiding them, and sold seats draw hollow with a status cue whose ink is chosen against the surface behind it, so it reads on light and dark canvases alike. Tapping a price band dives to a readable, pickable depth when the band is one block in one section, and frames every block when it spans several; turning the band off leaves the camera where it was. The map fills its box on landing, reuses label nodes across pans, and survives a host that mounts it hidden. Switching theme at seat depth keeps every seat number and status cue. The buyer chrome now fits its own words in every locale: action buttons step down before “Cancel” becomes an icon, cart lines drop whole facts rather than cutting mid-word, and pills shrink before they wrap.
  • Selection. The “leaves a single seat stranded” advisory only appears when the host enforces the noOrphanSeats selection validator; without it buyers pick freely with no message.
  • Native hosts. Selection entries gain seat-view-thumbnail-v1: a real photo reference (seatViewThumb), the sightline distance (sightlineMetres) where a stage is authored, and the seat’s confidence disclosure (seatViewConfidence). The web picker shows “View from here” only for seats with a real uploaded photo.

2026-09-02

  • Buyer SDK 0.75.1 (@seatlayer/core, @seatlayer/js, CDN seatlayer-js@0.75.1; wrappers @seatlayer/react, @seatlayer/vue, @seatlayer/angular at the same version). The seat picker’s confirm card shows Section · Row · Seat only where a section is authored (category-only charts show Row · Seat), the ticket-type band is a tint of the category colour with the theme’s own ink, the primary action reads “Add seat” and invites the tap, and the cart lists one line per ticket in the price list’s language. On phones the card sits just above the tapped seat, every control meets a 44 px touch floor, the sheet respects the home-indicator inset, the overview minimap is gone, the empty bar offers “Find seats”, and the best-seats card stacks its controls. Seats reveal in one tap on charts without sections; selected seats keep a breathing halo and, at the section and zone levels, a tappable beacon that flies to them. Sold seats no longer invite a hover. The accessibility filter frames every matching seat, dims other buyers’ holds, and carries into 3D, whose section shells now recede when a filter empties them. In 3D the seat-eye view opens from the occupant’s eye height, aims at the stage from every block, narrows its lens on portrait phones, and its look-around drag works again; the caption, back control, area chips and fit-view icon no longer overlap. Zone pills are quieter and never wider than their zone. Charts may opt in to a derived restricted-view flag (derivedRestrictedView) that marks seats the house geometry obstructs, honouring any authored flag.
  • Fixes. A held-seat conflict during checkout can no longer render the success screen; the success view lists the seats and offers a way back to the map. Section-less charts no longer print the engine’s internal “Other seats” label. The renderer repaints only what changed on availability snapshots and focus changes, coalesces wheel zoom per frame, caches the pointer rectangle, and fetches inventory once per boot.
  • CDN. Every script now ships pre-compressed brotli and gzip variants served by content negotiation; non-English pickers no longer wait for the locale before fetching the chart. Native hosts gain additive bridge fields behind seat-screen-point-v1 (a seat’s screen point on selection entries) and category-availability-v1 (per-category free counts).

2026-08-31

  • All four native SDKs are aligned at 0.3.4. Flutter on pub.dev, React Native on npm, iOS through the v0.3.4 Swift tag, and Android’s aligned core and Compose artifacts on Maven Central now ship the complete native picker. Each supports a ready-made flow, themes/strings/styles/builders, a host-owned layout built from public components, and the preserved raw map. Booking stays on the trusted backend, and the native picker currently targets one Event, not a Performance Group or Fixed Renewable Season.
  • A new Fixed Renewable Seasons preview, not yet released. It permits multiple immutable Plans to remain published, binds each browser session to an explicit planActivationId, and requires one complete retained rehearsal journey per published Plan before sales can open. The JavaScript preview adds same-seat Season Best Available plus safe adoption when buyerAccessTokenProvider rotates to an exactly matching session. It builds on the released 0.72.1 baseline and remains unpublished. The REST and Node.js preview adds exact-replay return and reclaim for one booked occurrence. It remains unpublished; the other six server SDKs do not yet expose those two operations or webhook names. In the preview, Season booking and renewal also show up on each included Event: one usage unit per newly booked Event label, Event booking history, live seat updates, and standard seat.booked/event.soldout webhooks. Full Season cancellation produces the matching Event history, live release, and seat.released webhook. Exact replay does not repeat these effects, no extra Season usage unit is added, and Event configuration prices are not treated as package revenue. Season Event webhook items omit configured price and currency while trusted Event history keeps them.
  • No existing package or deployment is being renamed as that preview. The released 0.7.0 server-SDK and 0.72.1 browser/framework baselines remain the previous frozen surface. No new package version, CDN artifact, REST deployment, framework wrapper, or native wrapper is claimed here. This work remains inventory-only: hosted ticket selling, package pricing, checkout, payment, commercial orders, ticket/pass issuance, refunds, resale listings, and payouts stay outside SeatLayer’s Seasons scope.

2026-08-30

  • Fixed Renewable Seasons reached the frozen production SDK baseline. Node, Python, PHP, Java, Go, Ruby, and .NET 0.7.0 each expose the same 48 released Season operations. JavaScript, React, Vue, and Angular 0.72.1 expose the released browser picker. Later multi-Plan shapes and occurrence return/reclaim are a preview, not yet released, and are not part of those package versions.

2026-08-29

  • Historical candidate milestone, superseded by the 2026-08-30 release. The production-gated Fixed Renewable Seasons candidate could build a catalogue from 2–20 compatible Events, publish an immutable Plan, rehearse the buyer flow, coordinate same-seat holds and booking, import incumbent Seat Rights, issue time-bounded renewal offers, record occurrence amendments, and inspect operational reports. The host platform keeps identity, pricing, checkout, commercial Orders, tickets, refunds, and fulfilment. The public candidate initially covered the REST API, the Node.js server resource, JavaScript and React SeasonPicker, and organizer dashboard. The completed 2026-08-30 release expanded the server contract to all seven SDKs and the web picker to Vue and Angular as well. No native SeasonPicker is claimed. Start with the buyer journey or Seasons API.
  • Current AI and agent surfaces use one release vocabulary. Copilot Ask, Edit, multistep creation, reference input, and chart-scoped Designer MCP are released with review, revision, authorization, and publication boundaries. AI-led 3D improvement remains off.

2026-08-23

  • Partner access for sales channels. An organizer can hand one private channel to an external partner organisation. Each invited person accepts with their own SeatLayer account and sees the channel as a partner context in the workspace switcher: Overview, Allocations, Distribution, Reports, and Team. It is not membership of the organizer’s workspace. Roles are Viewer, Coordinator, and Partner manager; per-assignment permissions cover buyer links, free-seat returns, and inventory requests; a release date returns still-free seats to Public sale automatically; every action on both sides is audited. See Partner access.

2026-08-21

  • Performance Groups are available with Buyer SDK 0.64.0. A Platform integration can present one fixed run of two to eight compatible dated performances with PerformanceGroupPicker. Buyers choose the same assigned seats for every included date or an equal-size allocation per date; SeatLayer makes one recoverable all-or-nothing hold and the host retains checkout, payment, commercial order, and fulfilment ownership. This is not a season ticket, subscription, pass, or buyer-selectable date bundle. Start at Integrate a Performance Group.

2026-08-16

  • Sales channels can now carry authoritative sparse prices. Each channel exposes priceOverrides and an independent pricingVersion; PATCH writes use optimistic concurrency and reject unknown category/tier shapes. Scoped buyers see the channel price throughout SeatPicker, while the server resolves and freezes the same value on the hold. Existing holds and booked lines do not change after a price edit.
  • Pricing precedence is explicit. A channel override wins over an ordinary active ticket release and does not consume its quota. A Box Office operator’s deliberate named-release choice wins over the channel override and keeps the release attribution.
  • Control Room remains lightweight. Channel details now contain one compact price editor; blank fields inherit event pricing, and a concurrent save refreshes the latest values for review instead of silently overwriting them.

2026-08-13

  • Manage sessions now default to least privilege. Omitting capabilities when minting an mse_… token is still accepted, but the effective grant is now exactly event:view. Blocking, cancellation, reporting, channels, and Hosted Ticketing authority must be requested explicitly. Empty, malformed, and unknown capability lists remain invalid.
  • Manage-session revocation is exact-event scoped. A session ID can be revoked only under the event that minted it. Cross-event IDs are non-disclosing 404 responses, and live/test key mismatch returns the documented 403 mode_mismatch without revoking the session.
  • event:boxoffice browser grants are effective. A correctly scoped manage-session token can now use the Managed counter read and sale routes; the previous auth dispatcher incorrectly treated it as a secret key.

2026-08-10

  • The Platform/SDK booking boundary is inventory-only. A platform owns its event catalogue, buyer, checkout/payment, commercial Order, ticket/QR/PDF creation and delivery, email, refunds, scanning, and support. SeatLayer owns seating inventory, holds, idempotent inventory booking, audit/reporting, and webhooks. bookingRef links the systems; it is not a SeatLayer commerce Order.

    The short-lived behavior announced on 2026-08-06 created an internal external Order, tickets, PDF/email, attendance, and Door artifacts after POST /book. That behavior has been removed. Existing historical artifacts are retained for migration/audit, but new Platform bookings create inventory records only. SeatLayer-managed checkout and box-office fulfilment are unaffected.

  • Inventory cancellation and direct booking now enforce the same product boundary. Generic POST /v1/events/:key/unbook and legacy POST /v1/events/:key/box-book are available only for explicit Platform/SDK events. Hosted Ticketing cancellation stays coordinated through its Order/refund workflow, and Managed counter sales use /box-office/sale, so neither path can leave a live Order or ticket detached from its inventory. Organizer lifecycle, Control Room, object, report, and realtime-ticket routes also reject a live/test secret key used against the opposite event mode before reading or changing the event.

2026-08-06

  • The confirmation email and ticket PDF now wear the organizer’s brand. The logo and accent an organizer sets for their event pages now appear on the buyer’s confirmation email, with the logo in the header and accent on the card. The accent also colours the printed ticket’s rules. Sending stays under SeatLayer’s authenticated domain with the organizer’s name and reply-to, so deliverability is unaffected. Organizers who have set no branding see no change.

  • Historical implementation note, superseded: a server booking also created hosted fulfilment artifacts. For a short period, POST /v1/events/:eventKey/book with a holdId created a first-class order and issued real tickets: one QR per seat, the buyer’s ticket page, a printable PDF, and (when you pass the new optional buyer.email) the confirmation email. The response gains an order object carrying the order id, the human reference, and one scannable URL per seat so you can render your own tickets instead. The sale appears on the organizer’s Orders screen, the timeline, attendance, and the door list, exactly like a hosted-checkout sale. Retries with the same bookingRef return the original order and never email the buyer twice. Direct label bookings (no hold) get the same sale. They are priced through an internal hold. In the rare case the sale cannot be priced, the seats still book and the response states orderUnavailable instead of silently issuing nothing. SeatLayer still never touches your money on this route. Refunds stay in your own payment account, and the organizer’s refund button on such an order says so. See booking.

  • Every order now has a human reference: #7284 7528. Eight digits with a check digit that rejects a misheard or transposed digit rather than matching someone else’s order. It appears on the buyer’s confirmation, the tickets and PDF, the confirmation email, the organizer’s Orders screen and the door list, and the Orders search accepts #7284 7528, 72847528, and 7284-7528, alongside buyer name, email, and pasted order ids. It authorises nothing: ticket pages and PDFs are still addressed only by the long ord_… id. Orders that predate the change gain numbers automatically.

2026-08-01

  • Behavior change: a bare secret key can no longer touch private inventory. This affects you only if your server calls SeatLayer with an sk_… key to book seats and you start using sales channels on that event. An event with no channels behaves exactly as it did before.

    Once a seat is assigned to a private channel, a direct label booking without a holdId fails on that seat with 403 channel_access_denied unless the request says which channel it is acting for. A secret key proves which organization you are, not which allocation you may spend; without this rule the key that runs your public checkout could quietly drain a sponsor’s reserved block, and nothing but the audit log would say who did it.

    Three ways forward: send channelIds: ["chn_…"] and the sale is scoped and attributed to that channel; do nothing if the seats you book are all Public sale; or send ignoreChannelRestrictions: true with a reason for genuine back-office work, which reaches everything and writes every private seat it reaches to the channel audit log. Booking a hold is unaffected. A hold already captured its authorization when the seats were taken. See booking.

  • Sales channels. Split one event’s inventory into named allocations for partners, presales, sponsors, and box office, and decide who may select each one, without splitting the event, the chart, or the seat count. Assignment never changes whether a seat is free, held, booked or blocked; it only changes who may pick it before it sells. Every event you already have is entirely Public sale and stays that way; there is no migration. Start at sales channels.

  • New API: channels and buyer access sessions. Channel create, list, rename, versioned assignment, allocation paging, access preview, pause/unpause and archive-with-destination are on /server-api/channels. Buyer access sessions are short-lived, opaque, origin-bound bse_… bearers your backend mints for one buyer. They are documented at /server-api/buyer-access-sessions. Assignment is versioned and non-destructive: seats in someone’s checkout and seats already sold are never moved. New in the generated OpenAPI spec and the server SDKs.

  • Channel reporting separates allocation from attribution. GET /v1/events/:key/channels/report reports what each channel holds now beside what it sold, which are two different columns that move independently. Sell-through is attributed-sold over current-allocated, and the response says so in a methodology field rather than leaving you to guess. Revenue requires event:reports on top of event:channels:view; a caller without it sees every operational figure with revenue: null. See reports.

  • seat.booked webhooks carry sale attribution. Booked line items gain channelId (null = Public sale), channelExternalRef, accessSource, and partnerRef where the buyer’s grant carried one. Attribution is per item, not per delivery, and it is recorded at booking time and never rewritten, so it is safe to reconcile against. Payloads never contain a bearer token, session id, link capability, or secret key. See webhook events.

  • Two new least-privilege capabilities for event manage tokens: event:channels:view (names, allocations, counts) and event:channels:manage (create, assign, pause, archive). Neither implies the other, and event:block gains nothing. Tokens minted before this release keep exactly the capabilities they had. Channel access is opt-in by name.

2026-07-28

  • Template capacities changed for 17 of the 50 catalog templates. The published catalog had been serving a snapshot taken on 2026-07-17, and this is the first full reprint since, so the change carries eleven days of accumulated geometry work rather than a single fix. If you size events, price tiers or reconcile inventory against a template’s published seat count, re-read it. Existing charts you have already created are untouched. This affects the template you instantiate from, not anything you have saved.

    The largest movements, measured against the versions they replace:

    Template Before After Change
    esports-arena 864 3,666 +2,802
    amphitheatre 864 3,605 +2,741
    arena-round 2,364 3,684 +1,320
    west-end 1,584 922 −662
    small-theatre 198 788 +590
    concert-hall 663 1,119 +456
    uber-arena 14,142 13,784 −358

    Increases are mostly sections that the archetype compiler had already learned to build but that had never been printed. Decreases are corrections: rows that were being counted where the geometry could not actually seat them. A separate fix to arc-row placement accounts for the uber-arena reduction and several smaller ones. Rows had been deriving their radius from a rounded seat count and could land up to 30 chart units off their own circle.

  • Venue relief now renders in 3D across 34 of 50 templates. Sections carry real front-edge heights and rake, so raked stalls, stacked terraces and balcony tiers read as physical structure instead of flat plates at stepped heights. arena-section previously authored no sections at all and now builds three terraces rising to 4.92 m. The remaining 16 templates are flat because the rooms are flat, including banquet floors, booth halls, GA lawns, conference rooms, runways, and black-box studios. They are deliberately not badged 3D.

  • Web SDK 0.32.0. Seats render as chairs with backs at close range rather than dots, and label emphasis is reduced at seat level. The 3D renderer is still loaded only when a buyer opens 3D. @seatlayer/core, @seatlayer/js and @seatlayer/react are on npm; the CDN seatlayer-js@0 alias resolves to the new version.

  • GET /v1/charts/:id returns categorySeats. A map of category key to the number of seats that category actually sells, derived from the document on every read and never stored. It resolves per-seat category overrides, so it agrees with what the map sells rather than with what the row objects declare. Categories that sell nothing are present with 0, so “sells nothing” stays distinguishable from “does not exist”.

2026-07-26

  • Native Android SDK 0.1.0 first public release. The official Kotlin SDK provides SeatLayerView, coroutine commands, typed state and event flows, structured errors, a secure origin-restricted AndroidX WebKit bridge, and a runnable sample app. Install the exact JitPack tag or inspect source at seatlayer/seatlayer-android.
  • React Native SDK 0.1.0 first public release. The official @seatlayer/react-native package provides an Expo-compatible view, typed controller, versioned bridge, structured errors, and an independently vendored buyer runtime for iOS and Android. Source and the runnable example are available at seatlayer/seatlayer-react-native.
  • Web SDK 0.30.0. The public SDK now includes the current 3D venue structure, section rake, geometry, labels, and buyer-view renderer. The npm package pages also gain complete package-level guides, exact documentation routes, live demos, mobile SDKs, agent resources, and registry metadata.
  • Web SDK 0.29.0 published. @seatlayer/js and @seatlayer/react 0.29.0 are available from npm. The release includes the reconciled buyer widget and versioned mobile bridge behavior described below.
  • Flutter SDK 0.1.0 first public release. The official seatlayer package is available from pub.dev, with source in seatlayer/seatlayer-flutter.
  • iOS SDK source is public. The Swift package is available at seatlayer/seatlayer-ios for branch-pinned evaluation while its first semantic release is qualified.

2026-07-23

  • Native SDK release candidates. The iOS and Flutter 0.1.0 packages now share the versioned bridge protocol and pin their vendored buyer bundles independently. Their typed APIs cover holds, GA quantities, tiers, floors, accessibility color, best-available zone/premium/TTL controls, and flat/isometric/Perspective 2.5D view modes. They remain unpublished until the immutable web artifact, hosted/device smoke tests, and public-package checks pass.
  • Web SDK 0.29.0 release candidate. The app and public SDK widget sources are reconciled. The bridge adds initial and runtime view-mode control while retaining the hold-TTL and correlated command-error behavior. Existing public installation guidance remains pinned to the currently published 0.28.4 packages until the release gate completes.

2026-07-22

  • Reference and vector import boundaries. The Designer can use PNG/JPEG/WebP as a private trace reference or rasterize one selected page from a PDF source up to 15 MB and 100 pages. It can also sanitize a bounded SVG/DXF subset into ordinary editable Shape objects. PDF export, native PDF/vector fidelity, arbitrary SVG/full CAD support, and SVG export remain outside the contract. Private referenceImage bytes and provenance are removed from buyer documents; the optional URL-only backgroundImage is a separate buyer presentation layer.
  • Eight accessibility accommodations. CART live-caption view is now first-class alongside wheelchair, companion, semi-ambulatory, hearing, sign-language, plus-size, and lift-up armrest. Wheelchair inventory distinguishes an accessible physical seat from an empty selectable bay across the Designer, picker, event capacity, and JSON reporting.
  • Per-zone focal points. Venue zones can face distinct stages or field centres. Designer authors can place the point on the map or copy the active floor focal; generated seat views and best-available ranking consume the owning zone’s point. The buyer’s best-seats panel offers an accessible zone choice when applicable, and bestAvailable accepts an optional stable zoneId. Legacy charts still preview with floor/chart fallback, but used zones must be explicit before publication.

2026-07-21

  • SDK 0.23.0: “Best seats” premium quick-pick. In charts with premium-flagged seats, the picker’s find-best-seats panel gains a ★ toggle that biases the search to an all-premium block, with an honest fallback note when no premium block of the requested size exists. Charts without premium seats are unchanged, and the default best-available ordering is identical when the toggle is off. Localized in English, Spanish, German, and French.
  • Designer loading skeleton. Opening a chart now shows a ghost of the designer chrome and canvas instead of a text placeholder while the document loads.

2026-07-20

  • SDK 0.22.0: the embedded Designer fills the viewport. EmbeddedDesigner defaults to height: 'fill': the iframe always reaches the bottom of the browser window (recomputed on resize and scroll, floor of minHeight: 480), instead of the old content-height auto-grow that could leave the editor short inside a host page. Numeric height plus autoResize remains for hosts that manage sizing themselves, and the Designer’s new full-screen button asks the host to pin the iframe over the page via seatlayer.designer.fullscreen. See Embed the chart Designer.
  • SDK 0.22.0: buyers see seat flags. Seats marked in the Designer as restricted view, obstructed, or premium now surface in the picker: a caution note (with the organizer’s own wording) on the seat details card and hover tooltip, markers on cart chips, and a Hide limited-view seats filter that dims flagged seats, localized in English, Spanish, German, and French.
  • White-label enforcement. theme.hideBadge (“Hide Powered by SeatLayer”) is now honored only for accounts with the white-label add-on; the flag is ignored at buyer-serve time otherwise. Existing charts are unaffected in the dashboard. Contact support to enable the add-on.

2026-07-19

  • SDK 0.21.0: denser buyer panel and cross-floor category focus. Ticket-type rows now filter and frame their category, including categories on another floor; long section names wrap cleanly; low-value availability chrome stays quiet until there is real news; and all four sightline translations use the correct distance copy.
  • SDK 0.20.0: complete React option forwarding. <SeatPicker /> now forwards every typed core option, including pricing, hideBadge, and transport, instead of silently dropping newer options. React hosts can also import attachPickerFrame directly from @seatlayer/react.
  • SDK 0.19.0: embedded control room. @seatlayer/js now exports SeatManager and @seatlayer/react exports <SeatManager />, a live, origin-scoped seat-management board for organizers: realtime seat repaint, KPI + gross-revenue tallies, an activity feed, and bulk block/unblock, all inside your own admin UI. See Embed the control room.
  • Manage sessions: browser-safe, capability-gated tokens. A secret key or a dashboard session can mint a short-lived mse_… token via POST /v1/events/:key/manage-sessions, scoped to one event, one exact browser origin, and a chosen subset of capabilities (event:view, event:block, event:cancel, event:reports). Tokens are shown once, never retrievable, revocable (DELETE /v1/events/:key/manage-sessions/:id), and the account secret never ships to a browser. Each route is gated by the capability it needs.
  • Sections availability: the closed state. Availability rules (POST /v1/events/:key/availability) add a closed mode alongside hidden, timed, and threshold: a closed section stays visible to buyers but greyed and off sale, where a hidden section vanishes. Operators drive open / closed / hidden / timed / auto-reveal from the control room’s Sections tool. See Inventory control.
  • Iframe embed docs. The one-iframe /e/:key buyer embed, including responsive sizing, the seatlayer:height / seatlayer:fullscreen postMessage contract, and the attachPickerFrame host helper, is now documented in Iframe embedding & sizing.
  • Embedded Designer host options. Embed the chart Designer now documents the wrapper’s autoResize, showLoadingState, loadingTimeoutMs, onRequestRelaunch, and host-managed fullscreen behavior.
  • Usage-based pricing only. Monthly subscription plans were retired in favor of a single usage-based credit wallet: one credit per sold seat, a free grant of 100 sold seats/month, and prepaid packs from 8¢ down to a 5¢ floor. Every feature is included for every workspace. See Pricing.
  • hold.extended webhook. The extended-hold event is now subscribable, bringing the webhook catalog to eight events.
  • Docs restructured around personas. These docs are now organized by task: embed the picker, wire up booking, build venues in a CMS, run the control room, customize, or run a platform. The API reference covers the Management, Server, and Designer Embed surfaces. The manage-session token, control-room, availability, event-lifecycle, template-instantiate, and webhook-config operations are now documented.

2026-07-15

  • Build with AI: Designer MCP first public release. An external agent (Claude, ChatGPT, or your own bot) can connect to SeatLayer’s remote, chart-scoped MCP over OAuth 2.1 + PKCE and follow a deterministic reference → design → validate → preview → review loop. SeatLayer hosts no model; your agent supplies vision and semantics while SeatLayer supplies secure reference assets, geometry, validation, and publication gates. Charts stay unpublished drafts until authoritative seat data and human review exist. This release established the chart-scoped workflow and human-review gate. See Build with AI.

2026-07-10

  • Platform API 0.4.0: embedded chart Designer. Platform backends can mint short-lived dse_… sessions scoped to one active workspace, one chart, one exact parent origin, expiry, and optional publish permission. Organizers can draw new venue geometry, edit, autosave, upload assets and references, and publish inside the platform CMS without a SeatLayer login or account key in the browser. Sessions are shown once, never retrievable, revocable, and disabled automatically when their workspace is disabled. See Embed the chart Designer.

  • SDK 0.3.0: native Designer hosts. @seatlayer/js now exports EmbeddedDesigner, and @seatlayer/react exports <EmbeddedDesigner />. Both wrappers mount the scoped Designer iframe, validate message origin/source and optional chart/workspace IDs, and recreate the iframe when a new session URL is supplied.

  • Platform API 0.3.0: organizer workspaces. One SeatLayer account can create an isolated workspace per organizer through /v1/workspaces while retaining account-level billing, keys, and a single webhook subscription. Charts have an immutable workspaceId; events inherit it from the chart; list routes filter by it; and webhook payloads include it. Existing integrations continue in an automatically-created default workspace. externalRef remains optional routing metadata, not authorization.

  • SDK 0.2.0. Atomic cart/tier hold replacement, GA quantity APIs and pricing, per-hold TTL, authoritative hold items, expiry reconciliation, and React parity.

  • Fully key-drivable platform flow. POST /v1/charts/:id/publish and GET /v1/events (sold counts, externalRef filter, mode on every item) now accept secret-key auth: duplicate → publish → create event → embed without a dashboard visit.

  • externalRef tagging for platforms. Charts and events accept an optional externalRef (your own organiser/tenant id, up to 128 chars) on create and on POST /v1/charts/:id/duplicate (override wins, explicit null clears, absent inherits the source’s tag). It’s returned in chart/event meta, updatable via PUT /v1/charts/:id and PATCH /v1/events/:key, filterable on the list routes (?externalRef=…), and rides every webhook payload alongside livemode (additive: only present when set).

  • Chart provisioning with secret keys. The chart routes (list, create, get, update, duplicate, archive) now accept Authorization: Bearer sk_… in addition to a dashboard session, so a platform backend can provision per-organiser charts programmatically. Charts carry no live/test mode (a chart is a design; mode lives on events), so test keys can provision charts too. Delete, unarchive, thumbnail, and asset routes support the same scoped secret-key workflow.

  • New guide: Platform integration. The end-to-end recipe for running SeatLayer under a multi-organiser ticketing platform: roles mapping, per-organiser provisioning, webhook routing by externalRef, and how billing works for platforms.

  • Test-mode keys + sandbox events. API keys can now be created in test mode (pk_test_…/sk_test_…; rotation keeps the mode). An event created with a test key is a sandbox event: bookings are free, with no credits or usage reports, while holds, best-available, and realtime behave exactly like live. Buyers see an amber TEST MODE ribbon on the chart (localized), and every webhook payload now carries livemode: true|false so receivers can route sandbox traffic. Test and live are strictly isolated. A key used on an event of the other mode gets 403 mode_mismatch. See Test mode and the updated Quickstart.

  • SDK 0.1.4. New floor API for multi-floor charts: getFloors() and setFloor(floorId) let embedders build their own floor switcher (see Multi-floor venues); new colorblind-safe mode: the colorblindSafe option (and setColorblindSafe()) switches categories to an Okabe-Ito palette and renders booked seats as hollow rings, with a matching toggle on the hosted buyer page; new onHint callback delivers the non-blocking, localized orphan-seat hint (see Holding seats). @seatlayer/react exposes the new methods on its imperative handle.

  • Production launch on seatlayer.io. The API (api.seatlayer.io), hosted SDK (cdn.seatlayer.io/sdk/v1/seatmap.js), and dashboard are live on the production domain.

  • Per-event checkout window. The default hold TTL is now 15 minutes (was 5), configurable per event via GET/POST /v1/events/:key/hold-ttl or the dashboard’s “Checkout window” field. Precedence: explicit ttlMs on the hold → event setting → default, all clamped to 60 minutes. See Handling hold expiry.

  • SDK 0.1.3. HoldResult and BestAvailableResult gain seats (the held seats with the buyer’s chosen ticket tier per seat); new setSeatTier() method and tiers/tierId on SelectedSeat; new onDeckTap callback for multi-floor charts.

  • Best available respects hidden inventory. bestAvailable() never auto-picks a seat inside a hidden or not-yet-revealed section.

2026-07-09

  • Inventory control + auto-reveal. Set section/zone availability windows that hide inventory from buyers or reveal it on a schedule or automatically once the rest of the house sells past a threshold (GET/POST /v1/events/:key/availability). Cancel bookings with POST /v1/events/:key/unbook; schedule blocked seats to auto-release with releaseAt on block. Reveal changes reach embedded pickers live through the SDK. See Inventory control.
  • Ticket tiers. Categories can offer named price tiers (Adult / Child / Senior…); buyers choose per seat in the picker, and the chosen tier rides through the hold to your booking flow. See Ticket tiers.
  • Multi-floor venues. Charts can carry multiple floors; the designer authors them per floor, and buyers get a floor switcher plus a stacked 3D deck view. See Multi-floor venues.
  • Template library. 28 templates: 11 capacity-adjustable venue families (with a continuous capacity slider) plus 17 curated flagships, and an insertable seating-blocks library in the designer. See Templates.
  • Big-venue rendering. Section-block overview with level-of-detail: far zoom shows section blocks with availability tint, zooming in melts blocks into individual seats.
  • Buyer i18n + dynamic currency. The picker and embed SDK ship in en/es/de/fr (locale/messages options), and prices render in the organizer’s workspace currency. See Localization.
  • Subscription plans. Superseded 2026-07-19. Monthly paid tiers (Studio, Pro, Scale) shipped here were retired in favor of pure usage-based credits: one credit per sold seat, no subscriptions. See Pricing.

2026-07-08

1.0: Public API + embed SDK. Book, hold, best-available, and block seats; pull inventory reports and audit logs; embed a live seat map with the SDK; receive webhooks (seat.booked, seat.released, seat.blocked, hold.created, hold.expired, event.created, event.soldout); and keep the embedded picker in sync with live seat updates through the SDK.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close