seatlayer 0.6.1 → 0.8.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +93 -32
- data/lib/seatlayer/http_client.rb +6 -0
- data/lib/seatlayer/inventory.rb +13 -1
- data/lib/seatlayer/resources.rb +12 -2
- data/lib/seatlayer/seasons.rb +272 -0
- data/lib/seatlayer/version.rb +1 -1
- data/lib/seatlayer.rb +3 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 841def7560b63781babf931924a29204c724ba5b4513eff1de283a370cb22699
|
|
4
|
+
data.tar.gz: 7027c38a8aeeee9aa5c339d90d04b33c4d708e47362687951d30dc280402bef4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2ef313b0db74c36aef5d0f512264586448d99330e1257c8a28b835da54a7b539fd3f9ab7183a91ae912cf1e55ec2c5dcede861260d80b77a4ed0eaaa6d1faaba
|
|
7
|
+
data.tar.gz: e85e01d772d6639a36d7fa7154a062d60564fbbe750258c1080fa4f7cc17eba25277ebc0e7e31ad0f04589b9d716402c486c6c325b3d202e7c7fd2ed9e96c903
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.7.0 — 2026-08-30
|
|
4
|
+
|
|
5
|
+
- Added coverage for all 48 Fixed Renewable Season server
|
|
6
|
+
operations under `client.seasons`, with exact path encoding and
|
|
7
|
+
operation-specific retry/idempotency behavior.
|
|
8
|
+
- Season allocations are identity-only and the API response declares host
|
|
9
|
+
pricing authority. Buyer rehearsal validation sends no evidence body because
|
|
10
|
+
SeatLayer discovers the retained hold, booking, cancellation, and delivered
|
|
11
|
+
webhook chain automatically.
|
|
12
|
+
|
|
3
13
|
## 0.6.1
|
|
4
14
|
|
|
5
15
|
- Documentation only. Refreshes the README, adds frequently asked
|
data/README.md
CHANGED
|
@@ -5,21 +5,21 @@
|
|
|
5
5
|
[](https://www.ruby-lang.org/)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
SeatLayer's official Ruby server SDK is the trusted side of its reserved seating and seat booking
|
|
9
|
+
API. Inspect what a hold really contains, price from server-owned seating-chart data, and book
|
|
10
|
+
with a stable `booking_ref`, while managing charts, events, inventory, allocations, and webhooks
|
|
11
|
+
through one typed ticketing API client.
|
|
12
12
|
|
|
13
13
|
[`seatlayer` gem on RubyGems](https://rubygems.org/gems/seatlayer) ·
|
|
14
|
-
[
|
|
15
|
-
[SeatLayer
|
|
14
|
+
[Ruby server SDK guide](https://docs.seatlayer.io/server-sdk/ruby/) ·
|
|
15
|
+
[SeatLayer developer platform](https://seatlayer.io/developers/) ·
|
|
16
16
|
[SeatLayer JavaScript seat map SDK](https://www.npmjs.com/package/@seatlayer/js) ·
|
|
17
|
-
[Server API reference](https://docs.seatlayer.io/server-api/)
|
|
17
|
+
[Server API reference](https://docs.seatlayer.io/server-api/events/)
|
|
18
18
|
|
|
19
19
|
> **Server-side only.** This gem authenticates with your secret key. Never load it anywhere a
|
|
20
20
|
> ticket buyer can reach — browser surfaces get short-lived, origin-bound tokens that you mint here.
|
|
21
21
|
|
|
22
|
-
## Install
|
|
22
|
+
## Install the Ruby seat booking SDK
|
|
23
23
|
|
|
24
24
|
```ruby
|
|
25
25
|
gem "seatlayer"
|
|
@@ -40,11 +40,16 @@ require "seatlayer"
|
|
|
40
40
|
client = SeatLayer::Client.new(ENV.fetch("SEATLAYER_SECRET_KEY"))
|
|
41
41
|
|
|
42
42
|
# 1. Provision a venue for a new organiser from a public template.
|
|
43
|
-
|
|
43
|
+
# Replace this placeholder with a template id from your catalog.
|
|
44
|
+
chart = client.templates.instantiate_template("your-published-template")["meta"]
|
|
44
45
|
client.charts.publish(chart["id"])
|
|
45
46
|
|
|
46
47
|
# 2. Create an event on it.
|
|
47
|
-
event = client.events.create(
|
|
48
|
+
event = client.events.create(
|
|
49
|
+
chart_id: chart["id"], name: "Spring Gala",
|
|
50
|
+
currency: "EUR", # omit to inherit the workspace currency
|
|
51
|
+
region: "western-europe" # India: "asia-pacific"
|
|
52
|
+
)["meta"]
|
|
48
53
|
|
|
49
54
|
# 3. Sell four seats over the phone.
|
|
50
55
|
held = client.inventory.hold_best_available(event["key"], qty: 4)
|
|
@@ -52,9 +57,50 @@ held = client.inventory.hold_best_available(event["key"], qty: 4)
|
|
|
52
57
|
client.inventory.book(event["key"], hold_id: held["holdId"], booking_ref: "order-8842")
|
|
53
58
|
```
|
|
54
59
|
|
|
60
|
+
## Event hosting region
|
|
61
|
+
|
|
62
|
+
Pass `region:` to `events.create` based on the **event venue**, not your API server or office. It
|
|
63
|
+
controls the initial placement of the Event's live inventory; an existing Event
|
|
64
|
+
cannot be moved later. Omit it to inherit the workspace default (`western-europe` for new accounts).
|
|
65
|
+
Set that default with `workspaces.create(default_region: ...)` or
|
|
66
|
+
`workspaces.update(workspace_id, default_region: ...)`; changing it affects only future Events.
|
|
67
|
+
|
|
68
|
+
- `western-europe`, `eastern-europe`, `north-america-east`, `north-america-west`, `south-america`
|
|
69
|
+
- `asia-pacific`, `northeast-asia`, `southeast-asia`, `oceania`, `africa`, `middle-east`
|
|
70
|
+
|
|
71
|
+
The hint is best effort, not a data-residency guarantee. See the
|
|
72
|
+
[full Event region guide](https://docs.seatlayer.io/server-api/event-regions/).
|
|
73
|
+
|
|
55
74
|
Nullable event-create fields distinguish omission from an explicit reset: passing, for example,
|
|
56
75
|
`venue: nil` sends JSON `null`; leaving `venue` out sends no field.
|
|
57
76
|
|
|
77
|
+
## Fixed Renewable Seasons
|
|
78
|
+
|
|
79
|
+
Version `0.7.0` exposes all 48 trusted organizer operations through
|
|
80
|
+
`client.seasons`.
|
|
81
|
+
|
|
82
|
+
After the test hold/book/cancel journey and matching webhook deliveries,
|
|
83
|
+
`validate_season_buyer_rehearsal(season_key)` sends no evidence body; SeatLayer
|
|
84
|
+
discovers the retained chain automatically. Retrieved Season holds contain
|
|
85
|
+
inventory identity, not an authoritative amount—your platform owns package
|
|
86
|
+
price, payment, order, tax, refunds, benefits, and ticket or pass delivery.
|
|
87
|
+
|
|
88
|
+
```ruby
|
|
89
|
+
checked = client.seasons.validate_season(
|
|
90
|
+
source_performance_group_keys: ["pg_subscription_run"]
|
|
91
|
+
)
|
|
92
|
+
draft = client.seasons.create_season(
|
|
93
|
+
name: "2027 subscription",
|
|
94
|
+
source_performance_group_keys: ["pg_subscription_run"],
|
|
95
|
+
idempotency_key: "season-create-2027"
|
|
96
|
+
).fetch("season")
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Treat `202` as accepted work and poll `retrieve_season_lifecycle` with the
|
|
100
|
+
returned operation identity. Buyer-session minting and domain-exact booking,
|
|
101
|
+
cancellation, and renewal actions remain single-attempt; only declared
|
|
102
|
+
header-replay catalogue mutations retry automatically.
|
|
103
|
+
|
|
58
104
|
## Test vs live
|
|
59
105
|
|
|
60
106
|
Keys carry their own mode. `sk_test_…` keys can only touch test-mode events and `sk_live_…` only
|
|
@@ -69,15 +115,21 @@ raise "Refusing to boot production against test-mode seating data." if
|
|
|
69
115
|
A publishable `pk_` key is rejected at construction with a message naming the mistake, rather than
|
|
70
116
|
failing as a `401` three round-trips later.
|
|
71
117
|
|
|
72
|
-
##
|
|
118
|
+
## Book reserved seats from Ruby
|
|
73
119
|
|
|
74
120
|
**Buyer picks seats in the browser.** Your frontend holds them; your backend confirms the price and
|
|
75
121
|
books. Never price from what the browser sent you — `retrieve_hold` is authoritative.
|
|
76
122
|
|
|
77
123
|
```ruby
|
|
78
124
|
hold = client.inventory.retrieve_hold(event_key, hold_id)
|
|
79
|
-
|
|
80
|
-
|
|
125
|
+
currencies = hold["items"].map { |item| item.fetch("currency") }.uniq
|
|
126
|
+
raise "A hold must use one currency" unless currencies.one?
|
|
127
|
+
|
|
128
|
+
currency = currencies.first
|
|
129
|
+
total = hold["items"].sum do |item|
|
|
130
|
+
item.fetch("unitPrice") * item.fetch("quantity", 1)
|
|
131
|
+
end
|
|
132
|
+
# … charge `total` in `currency` …
|
|
81
133
|
client.inventory.book(event_key, hold_id: hold_id, booking_ref: charge.id)
|
|
82
134
|
```
|
|
83
135
|
|
|
@@ -177,12 +229,12 @@ The full set, all opt-in:
|
|
|
177
229
|
|---|---|
|
|
178
230
|
| `event:view` | Read the seat map and its live states |
|
|
179
231
|
| `event:block` | Block and unblock seats |
|
|
180
|
-
| `event:cancel` |
|
|
232
|
+
| `event:cancel` | Cancel a Platform/SDK booking by reference and return its inventory to sale; does not move gateway money |
|
|
181
233
|
| `event:reports` | Read sales and availability reports |
|
|
182
234
|
| `event:channels:view` | Read sales channels and their allocations |
|
|
183
235
|
| `event:channels:manage` | Create, pause and archive channels; rotate access links |
|
|
184
236
|
| `event:orders:read` | Read SeatLayer-managed orders |
|
|
185
|
-
| `event:refund` | Refund
|
|
237
|
+
| `event:refund` | Refund an eligible Managed Ticketing order through its connected gateway |
|
|
186
238
|
| `event:tickets:send` | Send SeatLayer-managed tickets |
|
|
187
239
|
| `event:door:view` | Read the door list |
|
|
188
240
|
| `event:door:checkin` | Check tickets in and out |
|
|
@@ -261,17 +313,20 @@ error carries `status`, `code`, `body` and `request_id` — quote the request id
|
|
|
261
313
|
## Reliability
|
|
262
314
|
|
|
263
315
|
**Retries.** Reads (`GET`/`HEAD`) retry 429, 408 and 5xx with exponential backoff and full jitter;
|
|
264
|
-
`Retry-After` wins when the server sends it.
|
|
265
|
-
|
|
266
|
-
`
|
|
316
|
+
`Retry-After` wins when the server sends it. Fourteen mutations use exact header replay:
|
|
317
|
+
`charts.create`, `charts.copy`, `templates.instantiate_template`, `events.create`,
|
|
318
|
+
`workspaces.create`, `performance_groups.create`, `seasons.create_season`,
|
|
319
|
+
`seasons.update_season`, `seasons.delete_season`, `seasons.create_season_plan`,
|
|
320
|
+
`seasons.duplicate_season_to_live`, `seasons.create_season_holder_import`,
|
|
321
|
+
`seasons.create_season_renewal_offers`, and `seasons.create_season_amendment`. Other 4xx responses
|
|
267
322
|
are never retried.
|
|
268
323
|
|
|
269
|
-
**Idempotency.** Those
|
|
270
|
-
do not supply one and reused across attempts.
|
|
271
|
-
|
|
272
|
-
inventory holds and bookings, show-once credential or secret creation, unsupported
|
|
273
|
-
raw `request` mutations. Keep `booking_ref` in the booking body for reconciliation,
|
|
274
|
-
unknown network outcome explicitly instead of automatically repeating the sale.
|
|
324
|
+
**Idempotency.** Those 14 replay-backed operations carry an `Idempotency-Key`, generated when you
|
|
325
|
+
do not supply one and reused across attempts. All remaining SDK mutations are single-attempt. Some
|
|
326
|
+
have a server-side domain idempotency contract, but the SDK does not retry them automatically. This
|
|
327
|
+
includes inventory holds and bookings, show-once credential or secret creation, unsupported
|
|
328
|
+
operations, and raw `request` mutations. Keep `booking_ref` in the booking body for reconciliation,
|
|
329
|
+
but handle an unknown network outcome explicitly instead of automatically repeating the sale.
|
|
275
330
|
|
|
276
331
|
```ruby
|
|
277
332
|
client.events.create(chart_id: chart_id, idempotency_key: "provision-event-#{event_id}")
|
|
@@ -296,6 +351,10 @@ client.request("POST", "/v1/events/ev_1/some-new-route", body: { "qty" => 2 })
|
|
|
296
351
|
|
|
297
352
|
## API surface
|
|
298
353
|
|
|
354
|
+
The client exposes these resources. Performance Groups cover runs, sessions, holds, and bookings;
|
|
355
|
+
Seasons cover catalogue, plan, sales, buyer-session, booking, renewal, occurrence, reporting,
|
|
356
|
+
outbox, and support operations.
|
|
357
|
+
|
|
299
358
|
| Resource | Methods |
|
|
300
359
|
| --- | --- |
|
|
301
360
|
| `charts` | `list` `list_all` `create` `retrieve` `update` `delete` `copy` `archive` `unarchive` `publish` |
|
|
@@ -306,8 +365,10 @@ client.request("POST", "/v1/events/ev_1/some-new-route", body: { "qty" => 2 })
|
|
|
306
365
|
| `sessions` | `create_manage_session` `revoke_manage_session` `create_designer_session` `revoke_designer_session` |
|
|
307
366
|
| `webhooks` | `list` `create` `update` `delete` `list_deliveries` |
|
|
308
367
|
| `workspaces` | `list` `create` `retrieve` `update` |
|
|
368
|
+
| `performance_groups` | `list` `create` `retrieve` `delete` `activate` `close` `retrieve_lifecycle` `create_buyer_access_session` `list_buyer_access_sessions` `revoke_buyer_access_session` `retrieve_hold` `book_hold` `retrieve_booking` |
|
|
369
|
+
| `seasons` | 48 operations for catalogue and Plan lifecycle, sales windows, buyer access and booking, holder imports, renewals, occurrence amendments, reports, audit, outbox, and support export |
|
|
309
370
|
|
|
310
|
-
Full reference: [
|
|
371
|
+
Full reference: [SeatLayer Ruby server SDK guide](https://docs.seatlayer.io/server-sdk/ruby/)
|
|
311
372
|
|
|
312
373
|
### Deliberately not in this SDK
|
|
313
374
|
|
|
@@ -358,16 +419,16 @@ outcome before trying again.
|
|
|
358
419
|
|
|
359
420
|
### Can I use my own payment provider?
|
|
360
421
|
|
|
361
|
-
Yes.
|
|
362
|
-
the
|
|
363
|
-
money through whichever provider you already use
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
422
|
+
Yes. This server SDK does not process payment in a Platform/SDK integration. Inspect the hold,
|
|
423
|
+
compute the charge from each returned item's authoritative `unitPrice`, `quantity`, and `currency`,
|
|
424
|
+
take the money through whichever provider you already use, and then book the hold with your order
|
|
425
|
+
id as `booking_ref`. SeatLayer owns seating state, holds, booking concurrency, and the inventory
|
|
426
|
+
ledger in this integration; your platform owns payments, commercial orders, tickets, delivery,
|
|
427
|
+
and refunds. Managed Ticketing is a separate product path with organizer-connected payments.
|
|
367
428
|
|
|
368
429
|
## Continue your Ruby integration
|
|
369
430
|
|
|
370
|
-
- [Follow the
|
|
431
|
+
- [Follow the Ruby server SDK guide](https://docs.seatlayer.io/server-sdk/ruby/)
|
|
371
432
|
for installation, authentication, and the full hold-to-booking flow.
|
|
372
433
|
- [Handle errors, retries, and safe booking repeats](https://docs.seatlayer.io/server-sdk/reliability/)
|
|
373
434
|
before connecting a production order flow.
|
|
@@ -101,6 +101,12 @@ module SeatLayer
|
|
|
101
101
|
request("POST", path, body: body, idempotency_key: idempotency_key, retry_policy: retry_policy)
|
|
102
102
|
end
|
|
103
103
|
|
|
104
|
+
# Internal path for non-POST mutations backed by exact response replay.
|
|
105
|
+
def mutation_with_header_replay(method, path, body = nil, idempotency_key: nil)
|
|
106
|
+
request(method, path, body: body, idempotency_key: idempotency_key,
|
|
107
|
+
retry_policy: :header_replay)
|
|
108
|
+
end
|
|
109
|
+
|
|
104
110
|
def put(path, body)
|
|
105
111
|
request("PUT", path, body: body)
|
|
106
112
|
end
|
data/lib/seatlayer/inventory.rb
CHANGED
|
@@ -252,9 +252,14 @@ module SeatLayer
|
|
|
252
252
|
@client.get("/v1/workspaces")
|
|
253
253
|
end
|
|
254
254
|
|
|
255
|
-
def create(name:, external_ref: UNSET, idempotency_key: nil)
|
|
255
|
+
def create(name:, external_ref: UNSET, default_region: nil, idempotency_key: nil)
|
|
256
|
+
unless default_region.nil? || EVENT_HOSTING_REGIONS.include?(default_region)
|
|
257
|
+
raise ArgumentError, "default_region must be a supported SeatLayer Event region"
|
|
258
|
+
end
|
|
259
|
+
|
|
256
260
|
body = { "name" => name }
|
|
257
261
|
body.merge!(supplied({ "externalRef" => external_ref }))
|
|
262
|
+
body["defaultRegion"] = default_region unless default_region.nil?
|
|
258
263
|
@client.post(
|
|
259
264
|
"/v1/workspaces", body, idempotency_key: idempotency_key, retry_policy: :header_replay
|
|
260
265
|
)
|
|
@@ -269,6 +274,13 @@ module SeatLayer
|
|
|
269
274
|
# The organisation's default workspace cannot be disabled — the API answers
|
|
270
275
|
# 409 +default_workspace_required+. Promote another one first.
|
|
271
276
|
def update(workspace_id, fields)
|
|
277
|
+
region = fields[:default_region] || fields["defaultRegion"]
|
|
278
|
+
unless region.nil? || EVENT_HOSTING_REGIONS.include?(region)
|
|
279
|
+
raise ArgumentError, "default_region must be a supported SeatLayer Event region"
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
fields = fields.dup
|
|
283
|
+
fields["defaultRegion"] = fields.delete(:default_region) if fields.key?(:default_region)
|
|
272
284
|
@client.patch("/v1/workspaces/#{encode(workspace_id)}", fields)
|
|
273
285
|
end
|
|
274
286
|
end
|
data/lib/seatlayer/resources.rb
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module SeatLayer
|
|
4
|
+
EVENT_HOSTING_REGIONS = %w[
|
|
5
|
+
western-europe eastern-europe north-america-east north-america-west
|
|
6
|
+
south-america asia-pacific northeast-asia southeast-asia oceania africa middle-east
|
|
7
|
+
].freeze
|
|
8
|
+
|
|
4
9
|
# Shared plumbing for the resource namespaces.
|
|
5
10
|
class Resource
|
|
6
11
|
UNSET = Object.new.freeze
|
|
@@ -179,8 +184,13 @@ module SeatLayer
|
|
|
179
184
|
def create(chart_id:, name: nil, slug: nil, starts_at: UNSET, venue: UNSET,
|
|
180
185
|
external_ref: UNSET, currency: UNSET, idempotency_key: nil,
|
|
181
186
|
description: UNSET, ends_at: UNSET, timezone: UNSET, locale: UNSET,
|
|
182
|
-
poster_asset_id: UNSET, mode: nil)
|
|
183
|
-
|
|
187
|
+
poster_asset_id: UNSET, mode: nil, region: nil)
|
|
188
|
+
unless region.nil? || EVENT_HOSTING_REGIONS.include?(region)
|
|
189
|
+
raise ArgumentError, "region must be a supported SeatLayer Event region"
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
body = compact({ "chartId" => chart_id, "name" => name, "slug" => slug,
|
|
193
|
+
"mode" => mode, "region" => region })
|
|
184
194
|
body.merge!(supplied({ "startsAt" => starts_at, "venue" => venue,
|
|
185
195
|
"externalRef" => external_ref, "currency" => currency,
|
|
186
196
|
"description" => description, "endsAt" => ends_at,
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SeatLayer
|
|
4
|
+
# Fixed Renewable Season organizer operations for trusted backends.
|
|
5
|
+
#
|
|
6
|
+
# Browser selection belongs in the distinct SeasonPicker. Give it only the
|
|
7
|
+
# show-once scoped token returned by +create_season_buyer_access_session+.
|
|
8
|
+
class Seasons < Resource
|
|
9
|
+
def list_seasons(workspace_id: nil, structure_state: nil, limit: nil, cursor: nil)
|
|
10
|
+
@client.get("/v1/seasons", compact({ "workspaceId" => workspace_id,
|
|
11
|
+
"structureState" => structure_state,
|
|
12
|
+
"limit" => limit, "cursor" => cursor }))
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Read-only compatibility preflight.
|
|
16
|
+
def validate_season(event_keys: nil, source_performance_group_keys: nil)
|
|
17
|
+
@client.post("/v1/seasons/validate",
|
|
18
|
+
selection(event_keys, source_performance_group_keys))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def create_season(name:, event_keys: nil, source_performance_group_keys: nil,
|
|
22
|
+
edition: UNSET, idempotency_key: nil)
|
|
23
|
+
body = selection(event_keys, source_performance_group_keys).merge("name" => name)
|
|
24
|
+
body.merge!(supplied({ "edition" => edition }))
|
|
25
|
+
@client.post("/v1/seasons", body, idempotency_key: idempotency_key,
|
|
26
|
+
retry_policy: :header_replay)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def retrieve_season(season_key)
|
|
30
|
+
@client.get(path(season_key))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def update_season(season_key, expected_revision:, name: nil, edition: UNSET,
|
|
34
|
+
idempotency_key: nil)
|
|
35
|
+
body = compact({ "expectedRevision" => expected_revision, "name" => name })
|
|
36
|
+
body.merge!(supplied({ "edition" => edition }))
|
|
37
|
+
@client.mutation_with_header_replay(
|
|
38
|
+
"PATCH", path(season_key), body, idempotency_key: idempotency_key
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def delete_season(season_key, idempotency_key: nil)
|
|
43
|
+
@client.mutation_with_header_replay(
|
|
44
|
+
"DELETE", path(season_key), idempotency_key: idempotency_key
|
|
45
|
+
)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def activate_season(season_key, expected_revision:)
|
|
49
|
+
lifecycle(season_key, "activate", expected_revision)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def close_season(season_key, expected_revision:)
|
|
53
|
+
lifecycle(season_key, "close", expected_revision)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def archive_season(season_key, expected_revision:)
|
|
57
|
+
lifecycle(season_key, "archive", expected_revision)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def retrieve_season_lifecycle(season_key, operation_id)
|
|
61
|
+
@client.get(path(season_key, "/lifecycle/#{encode(operation_id)}"))
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def create_season_plan(season_key, name:, event_keys: nil,
|
|
65
|
+
source_performance_group_keys: nil, idempotency_key: nil)
|
|
66
|
+
body = selection(event_keys, source_performance_group_keys).merge("name" => name)
|
|
67
|
+
@client.post(path(season_key, "/plans"), body, idempotency_key: idempotency_key,
|
|
68
|
+
retry_policy: :header_replay)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def retrieve_season_plan(season_key, plan_key)
|
|
72
|
+
@client.get(path(season_key, "/plans/#{encode(plan_key)}"))
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def publish_season_plan(season_key, plan_key, expected_revision:)
|
|
76
|
+
@client.post(path(season_key, "/plans/#{encode(plan_key)}/publish"),
|
|
77
|
+
{ "expectedRevision" => expected_revision })
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def supersede_season_plan(season_key, plan_key, expected_revision:)
|
|
81
|
+
@client.post(path(season_key, "/plans/#{encode(plan_key)}/supersede"),
|
|
82
|
+
{ "expectedRevision" => expected_revision })
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def open_season_sales(season_key, expected_revision:)
|
|
86
|
+
sales(season_key, "open", expected_revision)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def pause_season_sales(season_key, expected_revision:)
|
|
90
|
+
sales(season_key, "pause", expected_revision)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def resume_season_sales(season_key, expected_revision:)
|
|
94
|
+
sales(season_key, "resume", expected_revision)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def end_season_sales(season_key, expected_revision:)
|
|
98
|
+
sales(season_key, "end", expected_revision)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def duplicate_season_to_live(season_key, event_keys:, name: nil, idempotency_key: nil)
|
|
102
|
+
@client.post(path(season_key, "/duplicate-to-live"),
|
|
103
|
+
compact({ "eventKeys" => event_keys, "name" => name }),
|
|
104
|
+
idempotency_key: idempotency_key, retry_policy: :header_replay)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Reveal one show-once browser bearer. This call is deliberately single-attempt.
|
|
108
|
+
def create_season_buyer_access_session(season_key, allowed_origin:, include_public:,
|
|
109
|
+
expires_in_seconds: nil, max_quantity: UNSET,
|
|
110
|
+
buyer_ref: UNSET)
|
|
111
|
+
body = compact({ "allowedOrigin" => allowed_origin, "includePublic" => include_public,
|
|
112
|
+
"expiresInSeconds" => expires_in_seconds })
|
|
113
|
+
body.merge!(supplied({ "maxQuantity" => max_quantity, "buyerRef" => buyer_ref }))
|
|
114
|
+
@client.post(path(season_key, "/buyer-access-sessions"), body)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def list_season_buyer_access_sessions(season_key, limit: nil)
|
|
118
|
+
@client.get(path(season_key, "/buyer-access-sessions"), compact({ "limit" => limit }))
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def revoke_season_buyer_access_session(season_key, session_id)
|
|
122
|
+
@client.delete(path(season_key, "/buyer-access-sessions/#{encode(session_id)}"))
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def retrieve_season_hold(season_key, operation_id)
|
|
126
|
+
@client.get(path(season_key, "/holds/#{encode(operation_id)}"))
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def book_season_hold(season_key, operation_id, book_action_id:, booking_ref:)
|
|
130
|
+
@client.post(path(season_key, "/holds/#{encode(operation_id)}/book"),
|
|
131
|
+
{ "bookActionId" => book_action_id, "bookingRef" => booking_ref })
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def retrieve_season_booking(season_key, action_id)
|
|
135
|
+
@client.get(path(season_key, "/bookings/#{encode(action_id)}"))
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def cancel_season_booking(season_key, action_id, cancel_action_id:, booking_ref:,
|
|
139
|
+
plan_activation_id:, right_disposition:)
|
|
140
|
+
@client.post(path(season_key, "/bookings/#{encode(action_id)}/cancel"),
|
|
141
|
+
{ "cancelActionId" => cancel_action_id, "bookingRef" => booking_ref,
|
|
142
|
+
"planActivationId" => plan_activation_id,
|
|
143
|
+
"rightDisposition" => right_disposition })
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def validate_season_buyer_rehearsal(season_key)
|
|
147
|
+
@client.post(path(season_key, "/buyer-rehearsals/validate"))
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def create_season_holder_import(season_key, successor_plan_activation_id:, rows:,
|
|
151
|
+
dry_run: UNSET, idempotency_key: nil)
|
|
152
|
+
body = { "successorPlanActivationId" => successor_plan_activation_id, "rows" => rows }
|
|
153
|
+
body.merge!(supplied({ "dryRun" => dry_run }))
|
|
154
|
+
@client.post(path(season_key, "/imports"), body, idempotency_key: idempotency_key,
|
|
155
|
+
retry_policy: :header_replay)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def retrieve_season_holder_import(season_key, import_id)
|
|
159
|
+
@client.get(path(season_key, "/imports/#{encode(import_id)}"))
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def create_season_renewal_offers(season_key, deadline_at:,
|
|
163
|
+
successor_plan_activation_id: nil, contract_ids: nil,
|
|
164
|
+
idempotency_key: nil)
|
|
165
|
+
body = compact({ "successorPlanActivationId" => successor_plan_activation_id,
|
|
166
|
+
"deadlineAt" => deadline_at, "contractIds" => contract_ids })
|
|
167
|
+
@client.post(path(season_key, "/renewal-offers"), body,
|
|
168
|
+
idempotency_key: idempotency_key, retry_policy: :header_replay)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def list_season_renewal_offers(season_key)
|
|
172
|
+
@client.get(path(season_key, "/renewal-offers"))
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def retrieve_season_renewal_offer(season_key, offer_id)
|
|
176
|
+
@client.get(path(season_key, "/renewal-offers/#{encode(offer_id)}"))
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def extend_season_renewal_offer(season_key, offer_id, deadline_at:)
|
|
180
|
+
@client.post(path(season_key, "/renewal-offers/#{encode(offer_id)}/extend"),
|
|
181
|
+
{ "deadlineAt" => deadline_at })
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def inspect_season_renewal_offer(season_key, offer_id)
|
|
185
|
+
@client.get(path(season_key, "/renewal-offers/#{encode(offer_id)}/inspect"))
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def commit_season_renewal_offer(season_key, offer_id, commit_action_id:, order_ref:,
|
|
189
|
+
booking_ref:, plan_activation_id:)
|
|
190
|
+
@client.post(path(season_key, "/renewal-offers/#{encode(offer_id)}/commit"),
|
|
191
|
+
{ "commitActionId" => commit_action_id, "orderRef" => order_ref,
|
|
192
|
+
"bookingRef" => booking_ref, "planActivationId" => plan_activation_id })
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def decline_season_renewal_offer(season_key, offer_id)
|
|
196
|
+
@client.post(path(season_key, "/renewal-offers/#{encode(offer_id)}/decline"), {})
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def release_season_renewal_offer(season_key, offer_id)
|
|
200
|
+
@client.post(path(season_key, "/renewal-offers/#{encode(offer_id)}/release"), {})
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def list_season_occurrences(season_key)
|
|
204
|
+
@client.get(path(season_key, "/occurrences"))
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def create_season_amendment(season_key, event_key:, kind:, starts_at: nil, name: nil,
|
|
208
|
+
idempotency_key: nil)
|
|
209
|
+
@client.post(path(season_key, "/amendments"),
|
|
210
|
+
compact({ "eventKey" => event_key, "kind" => kind,
|
|
211
|
+
"startsAt" => starts_at, "name" => name }),
|
|
212
|
+
idempotency_key: idempotency_key, retry_policy: :header_replay)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def list_season_amendments(season_key)
|
|
216
|
+
@client.get(path(season_key, "/amendments"))
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def retrieve_season_amendment(season_key, amendment_id)
|
|
220
|
+
@client.get(path(season_key, "/amendments/#{encode(amendment_id)}"))
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def retrieve_season_report(season_key)
|
|
224
|
+
@client.get(path(season_key, "/reports"))
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def list_season_operations(season_key)
|
|
228
|
+
@client.get(path(season_key, "/operations"))
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def retrieve_season_support_lookup(season_key, booking_ref: nil, holder_ref: nil)
|
|
232
|
+
@client.get(path(season_key, "/support-lookups"),
|
|
233
|
+
compact({ "bookingRef" => booking_ref, "holderRef" => holder_ref }))
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def list_season_outbox(season_key)
|
|
237
|
+
@client.get(path(season_key, "/outbox"))
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def replay_season_outbox(season_key, occurrence_id)
|
|
241
|
+
@client.post(path(season_key, "/outbox/#{encode(occurrence_id)}/replay"), {})
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def list_season_audit(season_key)
|
|
245
|
+
@client.get(path(season_key, "/audit"))
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def export_season_support_snapshot(season_key)
|
|
249
|
+
@client.get(path(season_key, "/export"))
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
private
|
|
253
|
+
|
|
254
|
+
def path(season_key, suffix = "")
|
|
255
|
+
"/v1/seasons/#{encode(season_key)}#{suffix}"
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def selection(event_keys, source_performance_group_keys)
|
|
259
|
+
compact({ "eventKeys" => event_keys,
|
|
260
|
+
"sourcePerformanceGroupKeys" => source_performance_group_keys })
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def lifecycle(season_key, action, expected_revision)
|
|
264
|
+
@client.post(path(season_key, "/#{action}"), { "expectedRevision" => expected_revision })
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def sales(season_key, action, expected_revision)
|
|
268
|
+
@client.post(path(season_key, "/sales/#{action}"),
|
|
269
|
+
{ "expectedRevision" => expected_revision })
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
data/lib/seatlayer/version.rb
CHANGED
data/lib/seatlayer.rb
CHANGED
|
@@ -7,6 +7,7 @@ require_relative "seatlayer/resources"
|
|
|
7
7
|
require_relative "seatlayer/inventory"
|
|
8
8
|
require_relative "seatlayer/channels"
|
|
9
9
|
require_relative "seatlayer/performance_groups"
|
|
10
|
+
require_relative "seatlayer/seasons"
|
|
10
11
|
require_relative "seatlayer/webhook"
|
|
11
12
|
|
|
12
13
|
# Official Ruby server SDK for the SeatLayer reserved-seating API.
|
|
@@ -21,7 +22,7 @@ module SeatLayer
|
|
|
21
22
|
# The SeatLayer client.
|
|
22
23
|
class Client
|
|
23
24
|
attr_reader :charts, :events, :inventory, :channels, :performance_groups, :sessions,
|
|
24
|
-
:webhooks, :workspaces, :templates
|
|
25
|
+
:seasons, :webhooks, :workspaces, :templates
|
|
25
26
|
|
|
26
27
|
def initialize(secret_key, base_url: HTTPClient::DEFAULT_BASE_URL,
|
|
27
28
|
max_retries: HTTPClient::DEFAULT_MAX_RETRIES,
|
|
@@ -34,6 +35,7 @@ module SeatLayer
|
|
|
34
35
|
@inventory = Inventory.new(@http)
|
|
35
36
|
@channels = Channels.new(@http)
|
|
36
37
|
@performance_groups = PerformanceGroups.new(@http)
|
|
38
|
+
@seasons = Seasons.new(@http)
|
|
37
39
|
@sessions = Sessions.new(@http)
|
|
38
40
|
@templates = Templates.new(@http)
|
|
39
41
|
@webhooks = Webhooks.new(@http)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: seatlayer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- SeatLayer
|
|
@@ -28,6 +28,7 @@ files:
|
|
|
28
28
|
- lib/seatlayer/inventory.rb
|
|
29
29
|
- lib/seatlayer/performance_groups.rb
|
|
30
30
|
- lib/seatlayer/resources.rb
|
|
31
|
+
- lib/seatlayer/seasons.rb
|
|
31
32
|
- lib/seatlayer/version.rb
|
|
32
33
|
- lib/seatlayer/webhook.rb
|
|
33
34
|
homepage: https://seatlayer.io
|