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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: abe617b9eff9a2dbeb571b81e16f8d41096b4cb4d49f35a3461f03b292316a87
4
- data.tar.gz: d901b82e10dd7194b726f7c3d4b8f2d642030a1458c42ae7a851b200a9b0ef9a
3
+ metadata.gz: 841def7560b63781babf931924a29204c724ba5b4513eff1de283a370cb22699
4
+ data.tar.gz: 7027c38a8aeeee9aa5c339d90d04b33c4d708e47362687951d30dc280402bef4
5
5
  SHA512:
6
- metadata.gz: d12c27e2f846f0aca0f95e8cc064723f9ad5ff37a83c64a854529db34a4b4651865011e3634a4eacd48bed9214e8ee64e1bccf162db24ca21d020f035cd6f091
7
- data.tar.gz: e764024fd33ae0ca89714490934a7bbac28a2527a0ccee40a1892b1d2292f6945deb575c28b69665f77fcb04dd2ba987b1ce80cdb0b512236a497386563ee9c3
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
  [![Ruby](https://img.shields.io/badge/Ruby-%E2%89%A53.0-CC342D.svg)](https://www.ruby-lang.org/)
6
6
  [![License: MIT](https://img.shields.io/badge/license-MIT-111827.svg)](LICENSE)
7
7
 
8
- The official SeatLayer Ruby server SDK the trusted side of a reserved-seating
9
- integration. Inspect what a hold really contains, price from server-owned seating-chart
10
- data, and book with a stable `booking_ref`, while managing charts, events, inventory,
11
- allocations, and webhooks through one typed ticketing API client.
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
- [SeatLayer server SDK documentation](https://docs.seatlayer.io/server-sdk/install/) ·
15
- [SeatLayer reserved-seating platform](https://seatlayer.io/) ·
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
- chart = client.templates.instantiate_template("arena-standard")["meta"]
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(chart_id: chart["id"], name: "Spring Gala")["meta"]
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
- ## The two selling flows
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
- total = hold["items"].sum { |item| item["unitPrice"] }
80
- # charge `total` in hold["currency"]
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` | Unbook paid seats and issue gateway refunds destructive, moves money |
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 a SeatLayer-managed order |
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. Automatic mutation retries are limited to the five
265
- operations backed by exact response replay: `charts.create`, `charts.copy`,
266
- `templates.instantiate_template`, `events.create`, and `workspaces.create`. Other 4xx responses
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 five replay-backed operations carry an `Idempotency-Key`, generated when you
270
- do not supply one and reused across attempts. Other mutations are single-attempt and receive no
271
- automatic key. A caller-supplied key is forwarded but does not enable retries. This includes
272
- inventory holds and bookings, show-once credential or secret creation, unsupported operations, and
273
- raw `request` mutations. Keep `booking_ref` in the booking body for reconciliation, but handle an
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: [docs.seatlayer.io/server-sdk](https://docs.seatlayer.io/server-sdk/install/)
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. SeatLayer never processes payment. Inspect the hold, compute the charge from
362
- the returned `items` and their authoritative `unitPrice` and `currency`, take the
363
- money through whichever provider you already use Stripe, Adyen, Razorpay, or your
364
- own and then book the hold with your order id as `booking_ref`. SeatLayer owns
365
- seating state, holds, booking concurrency, and the inventory ledger; your platform
366
- owns payments, commercial orders, tickets, delivery, and refunds.
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 SeatLayer server SDK guide](https://docs.seatlayer.io/server-sdk/install/)
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
@@ -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
@@ -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
- body = compact({ "chartId" => chart_id, "name" => name, "slug" => slug, "mode" => mode })
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SeatLayer
4
- VERSION = "0.6.1"
4
+ VERSION = "0.8.0"
5
5
  end
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.6.1
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