Use a Fixed Renewable Season when one buyer should receive the same assigned seats across an immutable programme of 2–20 Events and may keep a protected path to those seats in a successor Plan.
This page owns the end-to-end integration. Use the Season picker for buyer UI options and the Seasons API for exact operations, request fields, responses, lifecycle recovery, and support tooling.
Confirm that Season is the right model
| Requirement | Use |
|---|---|
| One dated occurrence | Event flow |
| One atomic purchase across a fixed 2–8 Event run, with no retained renewal right | Performance Group |
| Same assigned seats across an immutable 2–20 Event Plan, with durable rights and renewal | Fixed Renewable Season |
A Season is not a marketing name for several events. It adds four inventory concepts that a Performance Group deliberately does not have:
- a Plan fixes the complete Event membership and publication identity;
- a Contract records the holder’s relationship to that Plan;
- a Seat Right protects the holder’s assigned seats; and
- a Renewal Offer coordinates those rights into a successor Plan.
Read the full inventory model comparison before provisioning either multi-event product.
The complete Season journey
Your serverCreates compatible Events
Every occurrence uses the same published chart, venue, timezone, currency, environment, and Platform commerce boundary.
SeatLayerFreezes and publishes one Plan
Validation, activation, and publication establish the immutable occurrence set buyers will receive.
Your teamRehearses the complete path
A test buyer holds, books, cancels, and produces successfully delivered webhook evidence before sales open.
BuyerChooses one seat package
SeasonPicker holds the same labels atomically across every Event in the published Plan.
Your backendPrices, charges, and books
The host inspects the opaque operation, calculates the package amount, takes payment, and commits one retry-safe booking.
SeatLayerRetains rights for renewal
The completed inventory booking produces the Contract and Seat Rights used for later renewal offers.
1. Prepare compatible Events
Create one Event for every dated occurrence. Before creating the Season, confirm that all Events share:
- the same organization and workspace;
- the same test or live mode;
- the same published Chart snapshot and assigned-seat inventory model;
- the same venue, timezone, and currency;
- a start time; and
- Platform/integrator checkout ownership.
The currency is a compatibility guard. It does not make Event prices the Season package price. Your commerce system calculates the package amount.
Season v1 does not inherit private Sales Channel allocation. Use ordinary public Event inventory for the Plan; treat Sales Channels as a separate per-Event access model, not as a Season membership system.
2. Validate, create, activate, and publish
Preflight the intended Event set before a write. Validation reports the exact incompatible Event and field so an operator can correct the source rather than discovering the mismatch during publication.
POST /v1/seasons/validate HTTP/1.1
Authorization: Bearer sk_test_••••••••
Content-Type: application/json
{
"eventKeys": ["ev_opening", "ev_matinee", "ev_closing"]
}Create the draft with a retry-safe idempotency key:
POST /v1/seasons HTTP/1.1
Authorization: Bearer sk_test_••••••••
Idempotency-Key: membership-2027-draft
Content-Type: application/json
{
"name": "Main stage membership",
"edition": "2027",
"eventKeys": ["ev_opening", "ev_matinee", "ev_closing"]
}The draft contains a Plan. Activate the Season structure, then publish that exact Plan revision. These are separate transitions because structural review and buyer-facing publication are separate operational decisions.
POST /v1/seasons/sea_main_stage/activate HTTP/1.1
Authorization: Bearer sk_test_••••••••
Content-Type: application/json
{ "expectedRevision": 1 }POST /v1/seasons/sea_main_stage/plans/spl_2027/publish HTTP/1.1
Authorization: Bearer sk_test_••••••••
Content-Type: application/json
{ "expectedRevision": 2 }Lifecycle mutations may return 202 Accepted. Follow the returned Location,
honour Retry-After, and retain the original operation identity until it is
terminal. Do not create a replacement Season because one response was lost.
Activation does not publish a Plan, and publication does not open sales.
3. Rehearse before opening sales
The sales gate proves that the inventory and recovery path works as one system. In test mode, complete one coherent journey through the real public surfaces:
- mint a Season buyer session for the test origin;
- create a same-seat hold with
SeasonPicker; - inspect and book that hold from the trusted backend;
- cancel the test booking with an explicit Seat Right disposition; and
- receive successful webhook delivery for the required lifecycle events.
Then ask SeatLayer to validate the retained evidence:
POST /v1/seasons/sea_main_stage/buyer-rehearsals/validate HTTP/1.1
Authorization: Bearer sk_test_••••••••Once rehearsal succeeds, open sales against the revision you reviewed:
POST /v1/seasons/sea_main_stage/sales/open HTTP/1.1
Authorization: Bearer sk_test_••••••••
Content-Type: application/json
{ "expectedRevision": 3 }If the rehearsal is incomplete, fix the failed hold, booking, cancellation, or webhook-delivery boundary. Do not bypass the gate or paste operation ids into an operator screen.
4. Mint buyer access and render the picker
Authenticate and authorize the buyer in your application first. Your backend then mints one short-lived, exact-origin Season session and returns only the token and expiry to the browser.
POST /v1/seasons/sea_main_stage/buyer-access-sessions HTTP/1.1
Authorization: Bearer sk_live_••••••••
Content-Type: application/json
{
"allowedOrigin": "https://tickets.example.com",
"includePublic": true,
"maxQuantity": 4,
"buyerRef": "member_8372"
}Keep the secret key on the server and the returned bss_… token in browser
memory. Never place either credential in a URL, analytics property, exception
message, or persistent browser storage.
Render SeasonPicker with a token provider. The picker shows the complete Plan,
finds the availability intersection across every included Event, and creates
one all-or-nothing same-seat hold.
import { SeasonPicker } from "@seatlayer/js";
const picker = new SeasonPicker({
container: "#season-picker",
season: "sea_main_stage",
buyerAccessTokenProvider: () =>
fetch("/api/seatlayer/season-access", {
method: "POST",
credentials: "same-origin",
cache: "no-store",
}).then((response) => response.json()),
onContinue: (handoff) => {
startCheckout({
seasonKey: handoff.seasonKey,
operationId: handoff.operationId,
holdId: handoff.holdId,
});
},
});
await picker.render();Use the picker’s offer content only to explain the package. It is display
copy, not trusted pricing. Do not multiply an Event price in the browser and
call the result a Season total.
5. Inspect, price, pay, and book
Send the opaque operation identity to your backend. Inspect the retained hold there and verify that it is still committed to the expected Season and Plan. The inspection returns trusted Event and seat allocations but deliberately no authoritative commercial total.
Your backend should then:
- calculate the package amount, benefits, tax, and discounts from its own catalogue;
- create or recover one commercial order;
- authorize or capture payment according to its recovery policy; and
- book the same Season operation with one caller-stable action id and the
order’s immutable
bookingRef.
POST /v1/seasons/sea_main_stage/holds/sop_01/book HTTP/1.1
Authorization: Bearer sk_live_••••••••
Content-Type: application/json
{
"bookActionId": "season-book:order_1042",
"bookingRef": "order_1042"
}If booking returns 202 Accepted, poll the returned booking location. Reuse
the same bookActionId and bookingRef after a lost response. Never issue the
pass or per-occurrence tickets until the booking is terminally successful.
6. Store the commerce-to-inventory links
After booking, retain these relationships in your own order system:
| Host record | SeatLayer identity | Why retain it |
|---|---|---|
| Commercial order | bookingRef and booking action |
Retry, support, and reconciliation |
| Member or account | holderRef / buyer reference |
Find the correct Contract without treating it as payment identity |
| Membership edition | Season key and published Plan identity | Explain exactly which occurrence set was sold |
| Assigned package | Contract and Seat Right identities | Renewal, cancellation, and support |
| Fulfilment | Child Event allocations | Issue the correct passes or tickets for every occurrence |
SeatLayer’s Contract and Seat Rights prove inventory entitlement. Your order still proves the amount charged, tax, payment status, refund state, benefits, and fulfilment.
7. Renew, cancel, and operate deliberately
For an incumbent programme, import holders only through the Season import workflow and keep your own stable holder reference. For renewal:
- create and publish the successor Plan;
- generate time-bounded Renewal Offers for eligible Contracts;
- present the commercial renewal terms in your product;
- inspect the accepted renewal inventory on your server;
- take payment; and
- commit the offer with a stable action and order reference.
A buyer renewal intent is not a completed renewal and does not authorize a charge. Treat it as the start of your commerce workflow.
Cancellation requires an explicit Seat Right disposition:
- preserve keeps the future right while cancelling the current inventory booking according to your policy;
- release returns the right as well as the booked allocation.
Neither choice creates a refund. Payment compensation remains in your system. Use Season operations, reports, support lookups, and the retained outbox to reconcile uncertain or partially terminal outcomes; do not retry with new action ids or attempt independent child-Event rollback.
Go-live checklist
- The Event set is final, compatible, and uses one published Chart snapshot.
- The buyer uses exact seat choice on the released browser picker; the plan does not depend on native Season or Best Available support.
- Product owners chose Season instead of a single Event or Performance Group for a documented reason.
- Package price, benefits, tax, payment, refund, pass, and support ownership are implemented outside the inventory handoff.
- Test rehearsal proves hold, inspect, book, cancel, and webhook delivery.
- Browser credentials are exact-origin, short lived, kept in memory, and never carry a secret key.
- Lost responses reuse the same lifecycle and booking operation identities.
- The commercial order stores its Season, Plan, booking, Contract, and Seat Right relationships.
- Fulfilment covers every included Event and begins only after booking succeeds.
- Cancellation has an explicit payment policy and Seat Right disposition.
- Renewal terms and deadlines are owned by the host commerce system and tested against a successor Plan.
Continue by surface
| If you are implementing… | Continue with |
|---|---|
| Buyer selection and UI callbacks | Season picker |
| Catalogue, lifecycle, booking, import, renewal, and support operations | Seasons API |
| A shorter multi-performance purchase without renewal rights | Performance Group integration |
| A mobile Event picker | Native app SDKs |