@seatlayer/js 0.80.2 → 0.81.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -129,6 +129,72 @@ Supply `initialOperationId` to restore a lost create response. Pending operation
129
129
  are polled through their retained operation URL; `partial_terminal` stays visible
130
130
  and must be reconciled rather than replaced with a blind new action.
131
131
 
132
+ ### Selling a Season from a page with no backend
133
+
134
+ A Season the organizer has made public can be embedded without minting anything
135
+ first. Omit `buyerAccessToken` and `buyerAccessTokenProvider` and the picker
136
+ mints its own anonymous, origin-bound session against
137
+ `POST /pub/seasons/:key/sessions`. That session is **Public sale only**: it can
138
+ never reach a private channel or a renewal allocation, and an explicit
139
+ `buyerAccessToken` / `buyerAccessTokenProvider` always takes precedence over it.
140
+
141
+ `publicKey` is accepted for parity with `SeatPicker` so one snippet shape covers
142
+ both surfaces. It is not sent and is not a credential — a public Season session
143
+ is authorized by the Season key plus the browser's registered Origin.
144
+
145
+ ```js
146
+ const picker = new SeasonPicker({
147
+ container: '#season',
148
+ season: 'sea_2027',
149
+ publicKey: 'pk_live_…', // optional; never sent
150
+ checkout: 'hosted',
151
+ returnUrl: window.location.href,
152
+ onOrderConfirmed: (order) => showReceipt(order),
153
+ });
154
+ await picker.render();
155
+ ```
156
+
157
+ Three refusals reach `onAccessUnavailable` with their own reasons, because they
158
+ ask three different things of the organizer:
159
+
160
+ | `reason` | Means | `retryable` |
161
+ | --- | --- | --- |
162
+ | `audience_not_public` | The Season is embed-only; a tokenless embed cannot sell it. | `false` |
163
+ | `sales_not_open` | Public, but not on sale yet (or paused, or ended). | `true` |
164
+ | `origin_not_allowed` | This page's Origin is not a declared embed domain. | `false` |
165
+
166
+ The picker also says each one in plain language in its own status region, so a
167
+ host that handles none of them still shows the buyer something true.
168
+
169
+ ### Package prices and hosted Season checkout
170
+
171
+ `GET /pub/seasons/:key/prices` returns per-category package prices in minor
172
+ units. When it does, **the server price wins**: the hero prices each category
173
+ for the whole package ("Stalls · $480 for all 8 dates"), the confirm card totals
174
+ the selection at those prices, and the host-authored display-only `offer` copy
175
+ is not shown beside them. With no server prices, the existing "your ticketing
176
+ platform confirms the price" wording stays exactly as it was.
177
+
178
+ `checkout` chooses who takes the money:
179
+
180
+ - `'handoff'` (default) — unchanged. `onContinue` fires with the opaque,
181
+ price-free handoff and your server prices, charges and books it. No payment
182
+ code is downloaded.
183
+ - `'hosted'` — once the atomic hold is committed the primary action reads
184
+ *Continue to checkout*, and pressing it opens the same payment card the Event
185
+ picker uses. It collects an email, calls
186
+ `POST /pub/seasons/:key/checkout` with the hold's `operationId`, and follows
187
+ the gateway exactly as the Event path does — one order, one ticket per
188
+ performance. `onContinue` still fires, so a host that only observes the moment
189
+ keeps working.
190
+
191
+ A Season the organizer prices on their own backend reports
192
+ `checkoutMode: 'server'` on `GET /pub/seasons/:key`; asking for `'hosted'`
193
+ there stays on `'handoff'` rather than starting a payment SeatLayer cannot
194
+ complete. `returnUrl` follows the same rules as the Event picker's: the
195
+ organizer's declared embed domains decide whether it is honoured, so supplying
196
+ one cannot authorize it.
197
+
132
198
  The framework-agnostic JavaScript `SeasonPicker` is also wrapped by
133
199
  `@seatlayer/react`, `@seatlayer/vue`, and `@seatlayer/angular` `0.72.0` and
134
200
  newer. React Native, Flutter, iOS, and Android do not expose a Season bridge