seatschart 0.3.0 → 0.5.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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +79 -11
  3. data/lib/seatschart/api/audit_api.rb +2 -2
  4. data/lib/seatschart/api/auth_api.rb +85 -8
  5. data/lib/seatschart/api/billing_api.rb +93 -8
  6. data/lib/seatschart/api/charts_api.rb +63 -63
  7. data/lib/seatschart/api/events_api.rb +130 -124
  8. data/lib/seatschart/api/public_api.rb +6 -6
  9. data/lib/seatschart/api/seasons_api.rb +88 -88
  10. data/lib/seatschart/api/seats_api.rb +6 -6
  11. data/lib/seatschart/api/usage_api.rb +4 -4
  12. data/lib/seatschart/api/workspace_api.rb +1229 -51
  13. data/lib/seatschart/models/{api_error.rb → api_error_body.rb} +7 -7
  14. data/lib/seatschart/models/delete_api_workspaces_by_workspace_id_keys_by_key_id200_response.rb +237 -0
  15. data/lib/seatschart/models/delete_api_workspaces_by_workspace_id_members_by_user_id200_response.rb +221 -0
  16. data/lib/seatschart/models/get_api_workspaces200_response_items_inner.rb +50 -4
  17. data/lib/seatschart/models/get_api_workspaces_by_workspace_id_invitations200_response.rb +239 -0
  18. data/lib/seatschart/models/get_api_workspaces_by_workspace_id_invitations200_response_invitations_inner.rb +286 -0
  19. data/lib/seatschart/models/get_api_workspaces_by_workspace_id_keys200_response.rb +239 -0
  20. data/lib/seatschart/models/get_api_workspaces_by_workspace_id_keys200_response_api_keys_inner.rb +321 -0
  21. data/lib/seatschart/models/get_api_workspaces_by_workspace_id_members200_response.rb +239 -0
  22. data/lib/seatschart/models/get_api_workspaces_by_workspace_id_members200_response_members_inner.rb +288 -0
  23. data/lib/seatschart/models/get_api_workspaces_overview200_response.rb +288 -0
  24. data/lib/seatschart/models/get_api_workspaces_overview200_response_account.rb +270 -0
  25. data/lib/seatschart/models/get_api_workspaces_overview200_response_account_charts.rb +233 -0
  26. data/lib/seatschart/models/get_api_workspaces_overview200_response_account_plan.rb +237 -0
  27. data/lib/seatschart/models/get_api_workspaces_overview200_response_items_inner.rb +439 -0
  28. data/lib/seatschart/models/get_api_workspaces_overview200_response_items_inner_revenue.rb +234 -0
  29. data/lib/seatschart/models/get_api_workspaces_overview200_response_items_inner_usage.rb +271 -0
  30. data/lib/seatschart/models/get_api_workspaces_overview200_response_seats.rb +431 -0
  31. data/lib/seatschart/models/get_api_workspaces_overview200_response_seats_overage.rb +233 -0
  32. data/lib/seatschart/models/get_api_workspaces_overview200_response_seats_projected.rb +237 -0
  33. data/lib/seatschart/models/get_api_workspaces_overview200_response_totals.rb +318 -0
  34. data/lib/seatschart/models/get_api_workspaces_overview200_response_totals_revenue.rb +238 -0
  35. data/lib/seatschart/models/get_api_workspaces_overview200_response_totals_seats.rb +253 -0
  36. data/lib/seatschart/models/patch_api_events_by_event_id_request.rb +15 -15
  37. data/lib/seatschart/models/patch_api_workspaces_by_workspace_id_keys_by_key_id200_response.rb +221 -0
  38. data/lib/seatschart/models/patch_api_workspaces_by_workspace_id_keys_by_key_id_request.rb +292 -0
  39. data/lib/seatschart/models/patch_api_workspaces_by_workspace_id_request.rb +288 -0
  40. data/lib/seatschart/models/post_api_auth_new_workspace_request.rb +294 -0
  41. data/lib/seatschart/models/post_api_billing_actions_change_plan_request.rb +256 -0
  42. data/lib/seatschart/models/post_api_events_by_event_id_actions_update_extra_data_request_objects_inner.rb +0 -2
  43. data/lib/seatschart/models/post_api_sandboxes201_response.rb +0 -4
  44. data/lib/seatschart/models/post_api_sandboxes_by_sandbox_id_actions_reset200_response.rb +0 -2
  45. data/lib/seatschart/models/post_api_workspaces200_response.rb +464 -0
  46. data/lib/seatschart/models/post_api_workspaces200_response_api_key.rb +332 -0
  47. data/lib/seatschart/models/post_api_workspaces200_response_template.rb +260 -0
  48. data/lib/seatschart/models/post_api_workspaces200_response_template_webhooks_inner.rb +284 -0
  49. data/lib/seatschart/models/post_api_workspaces_by_workspace_id_actions_delete200_response.rb +319 -0
  50. data/lib/seatschart/models/post_api_workspaces_by_workspace_id_actions_delete_request.rb +281 -0
  51. data/lib/seatschart/models/post_api_workspaces_by_workspace_id_invitations201_response.rb +238 -0
  52. data/lib/seatschart/models/post_api_workspaces_by_workspace_id_invitations201_response_invitation.rb +286 -0
  53. data/lib/seatschart/models/post_api_workspaces_by_workspace_id_invitations_request.rb +300 -0
  54. data/lib/seatschart/models/post_api_workspaces_by_workspace_id_keys201_response.rb +237 -0
  55. data/lib/seatschart/models/post_api_workspaces_by_workspace_id_keys201_response_api_key.rb +338 -0
  56. data/lib/seatschart/models/post_api_workspaces_by_workspace_id_keys_request.rb +299 -0
  57. data/lib/seatschart/models/post_api_workspaces_request.rb +100 -4
  58. data/lib/seatschart/models/post_api_workspaces_request_issue_key.rb +294 -0
  59. data/lib/seatschart/version.rb +1 -1
  60. data/lib/seatschart/workspaces.rb +172 -0
  61. data/lib/seatschart.rb +41 -2
  62. metadata +43 -4
  63. data/lib/seatschart/models/put_api_charts_by_chart_id_map_draft_request.rb +0 -349
@@ -374,7 +374,7 @@ module SeatsChart
374
374
  end
375
375
 
376
376
  # Hold GA area capacity (Redis)
377
- # Places a temporary hold on unnumbered GA capacity. **Idempotency-Key** is required; repeats within ~24h return the cached hold response. Optional `ticketBuyerId` is stored on the GA hold token and inherited by `POST /ga/confirm`. The organizer's booking limits cap `quantity` (designer *Max GA tickets per order*, else *Max seats per order*; strictest with the sales-channel default): 409 `booking_limit_exceeded` (`limit`, `current`, `requested`, `kind: \"ga\"`). GA tables sold as a whole (`shape.bookAs: \"whole\"`) take every place in one hold: any other `quantity` answers 409 `ga_table_whole` (`capacity`, `requested`). Areas sold as a whole (`areaType` `fixedOccupancy` / `variableOccupancy`) are held for one buyer in one piece: `quantity` is the number of people (fixed: exactly the capacity; variable: `minOccupancy`..capacity), every place of the area is held atomically and a second buyer can never hold part of it. Any other quantity answers 400 `ga_area_whole` (`areaType`, `capacity`, `minOccupancy`, `maxOccupancy`, `requested`); an area already held, sold or partly withheld answers 409 `conflict`. A whole area counts as one object against the booking limits (its capacity, at most 50, caps it); its people count against quotas, lots and per-buyer limits. The response adds `places`, `people` and `areaType`.
377
+ # Places a temporary hold on unnumbered GA capacity. **Idempotency-Key** is required; repeats within ~24h return the cached hold response. Optional `ticketBuyerId` is stored on the GA hold token and inherited by `POST /ga/confirm`. The organizer's booking limits cap `quantity` (designer *Max GA tickets per order*, else *Max seats per order*; strictest with the sales-channel default): 409 `booking_limit_exceeded` (`limit`, `current`, `requested`, `kind: \"ga\"`). **Free (test plan) out of seats:** once the workspace used its 50 seats of the month, new holds (appends included) answer 409 `holds_paused` with a neutral message until the next UTC month or an upgrade; holds already taken can still be confirmed. GA tables sold as a whole (`shape.bookAs: \"whole\"`) take every place in one hold: any other `quantity` answers 409 `ga_table_whole` (`capacity`, `requested`). Areas sold as a whole (`areaType` `fixedOccupancy` / `variableOccupancy`) are held for one buyer in one piece: `quantity` is the number of people (fixed: exactly the capacity; variable: `minOccupancy`..capacity), every place of the area is held atomically and a second buyer can never hold part of it. Any other quantity answers 400 `ga_area_whole` (`areaType`, `capacity`, `minOccupancy`, `maxOccupancy`, `requested`); an area already held, sold or partly withheld answers 409 `conflict`. A whole area counts as one object against the booking limits (its capacity, at most 50, caps it); its people count against quotas, lots and per-buyer limits. The response adds `places`, `people` and `areaType`.
378
378
  # @param idempotency_key [String] Required. Reuse with the same request on retry; a different payload conflicts. Seat confirmation binds this key durably in PostgreSQL; hold mutations use bounded Redis receipts.
379
379
  # @param post_api_ga_reserve_request [PostApiGaReserveRequest]
380
380
  # @param [Hash] opts the optional parameters
@@ -385,7 +385,7 @@ module SeatsChart
385
385
  end
386
386
 
387
387
  # Hold GA area capacity (Redis)
388
- # Places a temporary hold on unnumbered GA capacity. **Idempotency-Key** is required; repeats within ~24h return the cached hold response. Optional `ticketBuyerId` is stored on the GA hold token and inherited by `POST /ga/confirm`. The organizer's booking limits cap `quantity` (designer *Max GA tickets per order*, else *Max seats per order*; strictest with the sales-channel default): 409 `booking_limit_exceeded` (`limit`, `current`, `requested`, `kind: \"ga\"`). GA tables sold as a whole (`shape.bookAs: \"whole\"`) take every place in one hold: any other `quantity` answers 409 `ga_table_whole` (`capacity`, `requested`). Areas sold as a whole (`areaType` `fixedOccupancy` / `variableOccupancy`) are held for one buyer in one piece: `quantity` is the number of people (fixed: exactly the capacity; variable: `minOccupancy`..capacity), every place of the area is held atomically and a second buyer can never hold part of it. Any other quantity answers 400 `ga_area_whole` (`areaType`, `capacity`, `minOccupancy`, `maxOccupancy`, `requested`); an area already held, sold or partly withheld answers 409 `conflict`. A whole area counts as one object against the booking limits (its capacity, at most 50, caps it); its people count against quotas, lots and per-buyer limits. The response adds `places`, `people` and `areaType`.
388
+ # Places a temporary hold on unnumbered GA capacity. **Idempotency-Key** is required; repeats within ~24h return the cached hold response. Optional `ticketBuyerId` is stored on the GA hold token and inherited by `POST /ga/confirm`. The organizer's booking limits cap `quantity` (designer *Max GA tickets per order*, else *Max seats per order*; strictest with the sales-channel default): 409 `booking_limit_exceeded` (`limit`, `current`, `requested`, `kind: \"ga\"`). **Free (test plan) out of seats:** once the workspace used its 50 seats of the month, new holds (appends included) answer 409 `holds_paused` with a neutral message until the next UTC month or an upgrade; holds already taken can still be confirmed. GA tables sold as a whole (`shape.bookAs: \"whole\"`) take every place in one hold: any other `quantity` answers 409 `ga_table_whole` (`capacity`, `requested`). Areas sold as a whole (`areaType` `fixedOccupancy` / `variableOccupancy`) are held for one buyer in one piece: `quantity` is the number of people (fixed: exactly the capacity; variable: `minOccupancy`..capacity), every place of the area is held atomically and a second buyer can never hold part of it. Any other quantity answers 400 `ga_area_whole` (`areaType`, `capacity`, `minOccupancy`, `maxOccupancy`, `requested`); an area already held, sold or partly withheld answers 409 `conflict`. A whole area counts as one object against the booking limits (its capacity, at most 50, caps it); its people count against quotas, lots and per-buyer limits. The response adds `places`, `people` and `areaType`.
389
389
  # @param idempotency_key [String] Required. Reuse with the same request on retry; a different payload conflicts. Seat confirmation binds this key durably in PostgreSQL; hold mutations use bounded Redis receipts.
390
390
  # @param post_api_ga_reserve_request [PostApiGaReserveRequest]
391
391
  # @param [Hash] opts the optional parameters
@@ -621,7 +621,7 @@ module SeatsChart
621
621
  end
622
622
 
623
623
  # Suggest or atomically hold best available seats
624
- # Returns seat IDs for the requested quantity, preferring adjacent same-row groups near the map center. Filter the candidate pool by `category` (or ordered `categories`, max 10: windows of the first category are tried before the second, and so on), optional `sectionId` (layout section id or name) and optional `zone` (layout zone id or name; seats resolve explicit zone assignment, then their section zone, then the zone outline) before ranking. `tryToPreventOrphanSeats` (default **true**) skips adjacent windows that would leave a single empty seat at either end of the run, falling back to them only when nothing else fits. `ticketTypes` (`{ ticketTypeId: count }`) sets `quantity` to the sum, restricts the search to categories whose ticket catalog offers every requested type, and returns `ticketTypes` (seatId → ticketTypeId) ready to send as `seatTicketTypes` on confirm; events without ticket types reject it. `accessibleSeats` (N) only returns windows containing at least N seats flagged `accessibility.wheelchair` in the published seat structure (409 when no such window exists). `channel` is salesChannel order limits only. Pass **`x-channel-key`** for inventory partitions — do not send the secret in the body. **`hold: false` (default):** suggest only — does not lock. **`hold: true`:** ranks up to 32 candidate windows across the category preferences, locks the first fit in one Lua call each (all-or-nothing per window), then O(cart) PG gates (available/forSale/channel; seats that are not for sale are never picked, not even resale-listed ones of non-propagating season members: those are bought by holding the seats of the listing); on gate failure releases only the locks it added. Requires **Idempotency-Key**, and `userId` unless `holdToken` is given. `holdToken` appends the seats to that existing hold session (same expiry bound; 409 `hold_token_conflict` when the session is expired, foreign, confirming or full). `extraData` is stored on the held seats (requires hold). Returns `hold_token` for confirm. The organizer's booking limits (designer *Max seats per order*) cap `quantity` and, with `holdToken`, the seats already on the token: best-available never picks more than allowed (409 `booking_limit_exceeded` with `limit`, `current`, `requested`). `sections` (max 20 section ids or names, XOR with `sectionId`) ranks across the union of those sections. **API keys / dashboard sessions only:** `channelKeys` (channel secret keys or ids) restricts the pool to public seats plus those channels, `ignoreChannels: true` allows every channel (both replace `x-channel-key`; buyers get 403). `orderId` (with `hold`) is stored on the held seats as `extraData.orderId` and echoed in the response; pass it as `externalOrderId` on confirm. **`status: \"booked\"`** (API keys with the `bookings` scope, or dashboard sessions allowed to change object statuses; buyers get 403) books the best window directly instead of holding it: the same administrative booking as POST /events/{eventId}/actions/book (one SQL transaction under the seat row locks; a seat held by a buyer is never taken; when a ranked window was taken meanwhile the next one is tried). Requires **Idempotency-Key**: the booking order id is derived from it, so a retry returns the same booking. `ticketTypes` are recorded per seat, `extraData` and `orderId` (as `extraData.orderId`) are stored on the booked seats. Response: `status: \"booked\"`, `booked: true`, `bookingOrderId` (cancel with POST /orders/{orderId}/cancel) and `objects` (status, extraData, orderId, ticketType per seat). `status: \"reservedByToken\"` is the same as `hold: true`. **`keepExtraData: true`** (hold or booked) keeps the seats' stored extraData and merges `extraData` / `orderId` on top instead of replacing it.
624
+ # Returns seat IDs for the requested quantity, preferring adjacent same-row groups near the map center. **Free (test plan) out of seats:** once the workspace used its 50 seats of the month, new holds (appends included) answer 409 `holds_paused` with a neutral message until the next UTC month or an upgrade; holds already taken can still be confirmed. Filter the candidate pool by `category` (or ordered `categories`, max 10: windows of the first category are tried before the second, and so on), optional `sectionId` (layout section id or name) and optional `zone` (layout zone id or name; seats resolve explicit zone assignment, then their section zone, then the zone outline) before ranking. `tryToPreventOrphanSeats` (default **true**) skips adjacent windows that would leave a single empty seat at either end of the run, falling back to them only when nothing else fits. `ticketTypes` (`{ ticketTypeId: count }`) sets `quantity` to the sum, restricts the search to categories whose ticket catalog offers every requested type, and returns `ticketTypes` (seatId → ticketTypeId) ready to send as `seatTicketTypes` on confirm; events without ticket types reject it. `accessibleSeats` (N) only returns windows containing at least N seats flagged `accessibility.wheelchair` in the published seat structure (409 when no such window exists). `channel` is salesChannel order limits only. Pass **`x-channel-key`** for inventory partitions — do not send the secret in the body. **`hold: false` (default):** suggest only — does not lock. **`hold: true`:** ranks up to 32 candidate windows across the category preferences, locks the first fit in one Lua call each (all-or-nothing per window), then O(cart) PG gates (available/forSale/channel; seats that are not for sale are never picked, not even resale-listed ones of non-propagating season members: those are bought by holding the seats of the listing); on gate failure releases only the locks it added. Requires **Idempotency-Key**, and `userId` unless `holdToken` is given. `holdToken` appends the seats to that existing hold session (same expiry bound; 409 `hold_token_conflict` when the session is expired, foreign, confirming or full). `extraData` is stored on the held seats (requires hold). Returns `hold_token` for confirm. The organizer's booking limits (designer *Max seats per order*) cap `quantity` and, with `holdToken`, the seats already on the token: best-available never picks more than allowed (409 `booking_limit_exceeded` with `limit`, `current`, `requested`). `sections` (max 20 section ids or names, XOR with `sectionId`) ranks across the union of those sections. **API keys / dashboard sessions only:** `channelKeys` (channel secret keys or ids) restricts the pool to public seats plus those channels, `ignoreChannels: true` allows every channel (both replace `x-channel-key`; buyers get 403). `orderId` (with `hold`) is stored on the held seats as `extraData.orderId` and echoed in the response; pass it as `externalOrderId` on confirm. **`status: \"booked\"`** (API keys with the `bookings` scope, or dashboard sessions allowed to change object statuses; buyers get 403) books the best window directly instead of holding it: the same administrative booking as POST /events/{eventId}/actions/book (one SQL transaction under the seat row locks; a seat held by a buyer is never taken; when a ranked window was taken meanwhile the next one is tried). Requires **Idempotency-Key**: the booking order id is derived from it, so a retry returns the same booking. `ticketTypes` are recorded per seat, `extraData` and `orderId` (as `extraData.orderId`) are stored on the booked seats. Response: `status: \"booked\"`, `booked: true`, `bookingOrderId` (cancel with POST /orders/{orderId}/cancel) and `objects` (status, extraData, orderId, ticketType per seat). `status: \"reservedByToken\"` is the same as `hold: true`. **`keepExtraData: true`** (hold or booked) keeps the seats' stored extraData and merges `extraData` / `orderId` on top instead of replacing it.
625
625
  # @param post_api_seats_best_available_request [PostApiSeatsBestAvailableRequest]
626
626
  # @param [Hash] opts the optional parameters
627
627
  # @option opts [String] :idempotency_key Required on transactional routes. Reuse the same key for every retry of one logical operation; the API replays the stored outcome.
@@ -632,7 +632,7 @@ module SeatsChart
632
632
  end
633
633
 
634
634
  # Suggest or atomically hold best available seats
635
- # Returns seat IDs for the requested quantity, preferring adjacent same-row groups near the map center. Filter the candidate pool by `category` (or ordered `categories`, max 10: windows of the first category are tried before the second, and so on), optional `sectionId` (layout section id or name) and optional `zone` (layout zone id or name; seats resolve explicit zone assignment, then their section zone, then the zone outline) before ranking. `tryToPreventOrphanSeats` (default **true**) skips adjacent windows that would leave a single empty seat at either end of the run, falling back to them only when nothing else fits. `ticketTypes` (`{ ticketTypeId: count }`) sets `quantity` to the sum, restricts the search to categories whose ticket catalog offers every requested type, and returns `ticketTypes` (seatId → ticketTypeId) ready to send as `seatTicketTypes` on confirm; events without ticket types reject it. `accessibleSeats` (N) only returns windows containing at least N seats flagged `accessibility.wheelchair` in the published seat structure (409 when no such window exists). `channel` is salesChannel order limits only. Pass **`x-channel-key`** for inventory partitions — do not send the secret in the body. **`hold: false` (default):** suggest only — does not lock. **`hold: true`:** ranks up to 32 candidate windows across the category preferences, locks the first fit in one Lua call each (all-or-nothing per window), then O(cart) PG gates (available/forSale/channel; seats that are not for sale are never picked, not even resale-listed ones of non-propagating season members: those are bought by holding the seats of the listing); on gate failure releases only the locks it added. Requires **Idempotency-Key**, and `userId` unless `holdToken` is given. `holdToken` appends the seats to that existing hold session (same expiry bound; 409 `hold_token_conflict` when the session is expired, foreign, confirming or full). `extraData` is stored on the held seats (requires hold). Returns `hold_token` for confirm. The organizer's booking limits (designer *Max seats per order*) cap `quantity` and, with `holdToken`, the seats already on the token: best-available never picks more than allowed (409 `booking_limit_exceeded` with `limit`, `current`, `requested`). `sections` (max 20 section ids or names, XOR with `sectionId`) ranks across the union of those sections. **API keys / dashboard sessions only:** `channelKeys` (channel secret keys or ids) restricts the pool to public seats plus those channels, `ignoreChannels: true` allows every channel (both replace `x-channel-key`; buyers get 403). `orderId` (with `hold`) is stored on the held seats as `extraData.orderId` and echoed in the response; pass it as `externalOrderId` on confirm. **`status: \"booked\"`** (API keys with the `bookings` scope, or dashboard sessions allowed to change object statuses; buyers get 403) books the best window directly instead of holding it: the same administrative booking as POST /events/{eventId}/actions/book (one SQL transaction under the seat row locks; a seat held by a buyer is never taken; when a ranked window was taken meanwhile the next one is tried). Requires **Idempotency-Key**: the booking order id is derived from it, so a retry returns the same booking. `ticketTypes` are recorded per seat, `extraData` and `orderId` (as `extraData.orderId`) are stored on the booked seats. Response: `status: \"booked\"`, `booked: true`, `bookingOrderId` (cancel with POST /orders/{orderId}/cancel) and `objects` (status, extraData, orderId, ticketType per seat). `status: \"reservedByToken\"` is the same as `hold: true`. **`keepExtraData: true`** (hold or booked) keeps the seats' stored extraData and merges `extraData` / `orderId` on top instead of replacing it.
635
+ # Returns seat IDs for the requested quantity, preferring adjacent same-row groups near the map center. **Free (test plan) out of seats:** once the workspace used its 50 seats of the month, new holds (appends included) answer 409 `holds_paused` with a neutral message until the next UTC month or an upgrade; holds already taken can still be confirmed. Filter the candidate pool by `category` (or ordered `categories`, max 10: windows of the first category are tried before the second, and so on), optional `sectionId` (layout section id or name) and optional `zone` (layout zone id or name; seats resolve explicit zone assignment, then their section zone, then the zone outline) before ranking. `tryToPreventOrphanSeats` (default **true**) skips adjacent windows that would leave a single empty seat at either end of the run, falling back to them only when nothing else fits. `ticketTypes` (`{ ticketTypeId: count }`) sets `quantity` to the sum, restricts the search to categories whose ticket catalog offers every requested type, and returns `ticketTypes` (seatId → ticketTypeId) ready to send as `seatTicketTypes` on confirm; events without ticket types reject it. `accessibleSeats` (N) only returns windows containing at least N seats flagged `accessibility.wheelchair` in the published seat structure (409 when no such window exists). `channel` is salesChannel order limits only. Pass **`x-channel-key`** for inventory partitions — do not send the secret in the body. **`hold: false` (default):** suggest only — does not lock. **`hold: true`:** ranks up to 32 candidate windows across the category preferences, locks the first fit in one Lua call each (all-or-nothing per window), then O(cart) PG gates (available/forSale/channel; seats that are not for sale are never picked, not even resale-listed ones of non-propagating season members: those are bought by holding the seats of the listing); on gate failure releases only the locks it added. Requires **Idempotency-Key**, and `userId` unless `holdToken` is given. `holdToken` appends the seats to that existing hold session (same expiry bound; 409 `hold_token_conflict` when the session is expired, foreign, confirming or full). `extraData` is stored on the held seats (requires hold). Returns `hold_token` for confirm. The organizer's booking limits (designer *Max seats per order*) cap `quantity` and, with `holdToken`, the seats already on the token: best-available never picks more than allowed (409 `booking_limit_exceeded` with `limit`, `current`, `requested`). `sections` (max 20 section ids or names, XOR with `sectionId`) ranks across the union of those sections. **API keys / dashboard sessions only:** `channelKeys` (channel secret keys or ids) restricts the pool to public seats plus those channels, `ignoreChannels: true` allows every channel (both replace `x-channel-key`; buyers get 403). `orderId` (with `hold`) is stored on the held seats as `extraData.orderId` and echoed in the response; pass it as `externalOrderId` on confirm. **`status: \"booked\"`** (API keys with the `bookings` scope, or dashboard sessions allowed to change object statuses; buyers get 403) books the best window directly instead of holding it: the same administrative booking as POST /events/{eventId}/actions/book (one SQL transaction under the seat row locks; a seat held by a buyer is never taken; when a ranked window was taken meanwhile the next one is tried). Requires **Idempotency-Key**: the booking order id is derived from it, so a retry returns the same booking. `ticketTypes` are recorded per seat, `extraData` and `orderId` (as `extraData.orderId`) are stored on the booked seats. Response: `status: \"booked\"`, `booked: true`, `bookingOrderId` (cancel with POST /orders/{orderId}/cancel) and `objects` (status, extraData, orderId, ticketType per seat). `status: \"reservedByToken\"` is the same as `hold: true`. **`keepExtraData: true`** (hold or booked) keeps the seats' stored extraData and merges `extraData` / `orderId` on top instead of replacing it.
636
636
  # @param post_api_seats_best_available_request [PostApiSeatsBestAvailableRequest]
637
637
  # @param [Hash] opts the optional parameters
638
638
  # @option opts [String] :idempotency_key Required on transactional routes. Reuse the same key for every retry of one logical operation; the API replays the stored outcome.
@@ -1006,7 +1006,7 @@ module SeatsChart
1006
1006
  end
1007
1007
 
1008
1008
  # Place a temporary Redis hold (Lua TTL) before payment
1009
- # JSON body: `eventId`, `seatIds` (1–64 UUIDs, unique; up to the workspace `maxSeatsPerHoldToken` with large group holds), `userId`, optional `holdToken` capability to append seats to an existing session. `userId` is customer metadata, never ownership proof. Renew/append share a two-hour maximum session lifetime. Optional `ticketBuyerId` (opaque partner buyer id) is stored on a new hold token and inherited by its confirmation. `eventId` also accepts the event key. Headers: **x-api-key** (B2B) *or* **Authorization: Bearer** (HS256 JWT); optional **x-tenant-id**; **`Idempotency-Key` is required** (1–255 chars after trim; use a fresh UUID v4 per checkout attempt). Repeats with the same key within ~24h return the cached HTTP status and JSON without re-running the Lua lock. Applies Redis TTL locks (**default 600 s**, overridden by **`SEAT_HOLD_TTL_SEC`**, or by the workspace **hold period** setting — `PATCH /workspace/settings`) with SSE `seat` → **`locked`**; Postgres remains **`available`** until **`POST /api/seats/confirm`** persists **`sold`** via the reservation worker. A hold token holds at most the workspace `maxSeatsPerHoldToken` seats (409 `seat_limit`). **Large group holds (opt-in):** a workspace `maxSeatsPerHoldToken` above 64 (up to 1000, `PATCH /workspace/settings`) lets one request and one hold token hold that many seats of one event; the request is still one atomic lock — every seat of the group is held under the token, or none is (409 `SEAT_LOCKED` when any seat is taken, nothing locked). The sales-channel defaults (web 8, box office 20, partner 64) then step aside; the organizer's booking limits and the workspace cap still apply. Season and multi-event holds keep the 64-lock limit. **Booking limits:** the organizer's *Max seats per order* (designer → Booking limits, stored as `layoutMeta.bookingRules` of the published chart/event layout) caps the seats one hold token holds, appends included, checked in the same atomic call as the locks (parallel appends cannot exceed it); the strictest of the sales-channel default, this limit, the per-buyer limit and `maxSeatsPerHoldToken` wins. Refused with 409 `booking_limit_exceeded` (`limit`, `current` seats already on the token, `requested`, `kind: \"seats\"`). Holds placed before a lower limit was published keep their seats and stay confirmable; they only cannot grow. With ticket buyer validation on, buyer tokens must carry a bound ticket buyer id (403 `ticket_buyer_required` / `ticket_buyer_mismatch`). Seats that are not for sale are refused with 409 `SEAT_NOT_FOR_SALE`, except a seat with an active **resale** listing in a season member whose for-sale configuration does not propagate (`forSalePropagated: false`, e.g. a season-ticket seat its holder resells for one game); the confirmation and the order commit apply the same rule.
1009
+ # JSON body: `eventId`, `seatIds` (1–64 UUIDs, unique; up to the workspace `maxSeatsPerHoldToken` with large group holds), `userId`, optional `holdToken` capability to append seats to an existing session. `userId` is customer metadata, never ownership proof. Renew/append share a two-hour maximum session lifetime. Optional `ticketBuyerId` (opaque partner buyer id) is stored on a new hold token and inherited by its confirmation. `eventId` also accepts the event key. Headers: **x-api-key** (B2B) *or* **Authorization: Bearer** (HS256 JWT); optional **x-tenant-id**; **`Idempotency-Key` is required** (1–255 chars after trim; use a fresh UUID v4 per checkout attempt). Repeats with the same key within ~24h return the cached HTTP status and JSON without re-running the Lua lock. Applies Redis TTL locks (**default 600 s**, overridden by **`SEAT_HOLD_TTL_SEC`**, or by the workspace **hold period** setting — `PATCH /workspace/settings`) with SSE `seat` → **`locked`**; Postgres remains **`available`** until **`POST /api/seats/confirm`** persists **`sold`** via the reservation worker. A hold token holds at most the workspace `maxSeatsPerHoldToken` seats (409 `seat_limit`). **Free (test plan) out of seats:** once the workspace used its 50 seats of the month, new holds (appends included) answer 409 `holds_paused` with a neutral message until the next UTC month or an upgrade; holds already taken can still be confirmed. **Large group holds (opt-in):** a workspace `maxSeatsPerHoldToken` above 64 (up to 1000, `PATCH /workspace/settings`) lets one request and one hold token hold that many seats of one event; the request is still one atomic lock — every seat of the group is held under the token, or none is (409 `SEAT_LOCKED` when any seat is taken, nothing locked). The sales-channel defaults (web 8, box office 20, partner 64) then step aside; the organizer's booking limits and the workspace cap still apply. Season and multi-event holds keep the 64-lock limit. **Booking limits:** the organizer's *Max seats per order* (designer → Booking limits, stored as `layoutMeta.bookingRules` of the published chart/event layout) caps the seats one hold token holds, appends included, checked in the same atomic call as the locks (parallel appends cannot exceed it); the strictest of the sales-channel default, this limit, the per-buyer limit and `maxSeatsPerHoldToken` wins. Refused with 409 `booking_limit_exceeded` (`limit`, `current` seats already on the token, `requested`, `kind: \"seats\"`). Holds placed before a lower limit was published keep their seats and stay confirmable; they only cannot grow. With ticket buyer validation on, buyer tokens must carry a bound ticket buyer id (403 `ticket_buyer_required` / `ticket_buyer_mismatch`). Seats that are not for sale are refused with 409 `SEAT_NOT_FOR_SALE`, except a seat with an active **resale** listing in a season member whose for-sale configuration does not propagate (`forSalePropagated: false`, e.g. a season-ticket seat its holder resells for one game); the confirmation and the order commit apply the same rule.
1010
1010
  # @param idempotency_key [String] Required deduplication key (max 255 chars after trim; UUID v4 recommended). 24h idempotent cache replay in Redis per tenant.
1011
1011
  # @param post_api_seats_reserve_request [PostApiSeatsReserveRequest]
1012
1012
  # @param [Hash] opts the optional parameters
@@ -1018,7 +1018,7 @@ module SeatsChart
1018
1018
  end
1019
1019
 
1020
1020
  # Place a temporary Redis hold (Lua TTL) before payment
1021
- # JSON body: `eventId`, `seatIds` (1–64 UUIDs, unique; up to the workspace `maxSeatsPerHoldToken` with large group holds), `userId`, optional `holdToken` capability to append seats to an existing session. `userId` is customer metadata, never ownership proof. Renew/append share a two-hour maximum session lifetime. Optional `ticketBuyerId` (opaque partner buyer id) is stored on a new hold token and inherited by its confirmation. `eventId` also accepts the event key. Headers: **x-api-key** (B2B) *or* **Authorization: Bearer** (HS256 JWT); optional **x-tenant-id**; **`Idempotency-Key` is required** (1–255 chars after trim; use a fresh UUID v4 per checkout attempt). Repeats with the same key within ~24h return the cached HTTP status and JSON without re-running the Lua lock. Applies Redis TTL locks (**default 600 s**, overridden by **`SEAT_HOLD_TTL_SEC`**, or by the workspace **hold period** setting — `PATCH /workspace/settings`) with SSE `seat` → **`locked`**; Postgres remains **`available`** until **`POST /api/seats/confirm`** persists **`sold`** via the reservation worker. A hold token holds at most the workspace `maxSeatsPerHoldToken` seats (409 `seat_limit`). **Large group holds (opt-in):** a workspace `maxSeatsPerHoldToken` above 64 (up to 1000, `PATCH /workspace/settings`) lets one request and one hold token hold that many seats of one event; the request is still one atomic lock — every seat of the group is held under the token, or none is (409 `SEAT_LOCKED` when any seat is taken, nothing locked). The sales-channel defaults (web 8, box office 20, partner 64) then step aside; the organizer's booking limits and the workspace cap still apply. Season and multi-event holds keep the 64-lock limit. **Booking limits:** the organizer's *Max seats per order* (designer → Booking limits, stored as `layoutMeta.bookingRules` of the published chart/event layout) caps the seats one hold token holds, appends included, checked in the same atomic call as the locks (parallel appends cannot exceed it); the strictest of the sales-channel default, this limit, the per-buyer limit and `maxSeatsPerHoldToken` wins. Refused with 409 `booking_limit_exceeded` (`limit`, `current` seats already on the token, `requested`, `kind: \"seats\"`). Holds placed before a lower limit was published keep their seats and stay confirmable; they only cannot grow. With ticket buyer validation on, buyer tokens must carry a bound ticket buyer id (403 `ticket_buyer_required` / `ticket_buyer_mismatch`). Seats that are not for sale are refused with 409 `SEAT_NOT_FOR_SALE`, except a seat with an active **resale** listing in a season member whose for-sale configuration does not propagate (`forSalePropagated: false`, e.g. a season-ticket seat its holder resells for one game); the confirmation and the order commit apply the same rule.
1021
+ # JSON body: `eventId`, `seatIds` (1–64 UUIDs, unique; up to the workspace `maxSeatsPerHoldToken` with large group holds), `userId`, optional `holdToken` capability to append seats to an existing session. `userId` is customer metadata, never ownership proof. Renew/append share a two-hour maximum session lifetime. Optional `ticketBuyerId` (opaque partner buyer id) is stored on a new hold token and inherited by its confirmation. `eventId` also accepts the event key. Headers: **x-api-key** (B2B) *or* **Authorization: Bearer** (HS256 JWT); optional **x-tenant-id**; **`Idempotency-Key` is required** (1–255 chars after trim; use a fresh UUID v4 per checkout attempt). Repeats with the same key within ~24h return the cached HTTP status and JSON without re-running the Lua lock. Applies Redis TTL locks (**default 600 s**, overridden by **`SEAT_HOLD_TTL_SEC`**, or by the workspace **hold period** setting — `PATCH /workspace/settings`) with SSE `seat` → **`locked`**; Postgres remains **`available`** until **`POST /api/seats/confirm`** persists **`sold`** via the reservation worker. A hold token holds at most the workspace `maxSeatsPerHoldToken` seats (409 `seat_limit`). **Free (test plan) out of seats:** once the workspace used its 50 seats of the month, new holds (appends included) answer 409 `holds_paused` with a neutral message until the next UTC month or an upgrade; holds already taken can still be confirmed. **Large group holds (opt-in):** a workspace `maxSeatsPerHoldToken` above 64 (up to 1000, `PATCH /workspace/settings`) lets one request and one hold token hold that many seats of one event; the request is still one atomic lock — every seat of the group is held under the token, or none is (409 `SEAT_LOCKED` when any seat is taken, nothing locked). The sales-channel defaults (web 8, box office 20, partner 64) then step aside; the organizer's booking limits and the workspace cap still apply. Season and multi-event holds keep the 64-lock limit. **Booking limits:** the organizer's *Max seats per order* (designer → Booking limits, stored as `layoutMeta.bookingRules` of the published chart/event layout) caps the seats one hold token holds, appends included, checked in the same atomic call as the locks (parallel appends cannot exceed it); the strictest of the sales-channel default, this limit, the per-buyer limit and `maxSeatsPerHoldToken` wins. Refused with 409 `booking_limit_exceeded` (`limit`, `current` seats already on the token, `requested`, `kind: \"seats\"`). Holds placed before a lower limit was published keep their seats and stay confirmable; they only cannot grow. With ticket buyer validation on, buyer tokens must carry a bound ticket buyer id (403 `ticket_buyer_required` / `ticket_buyer_mismatch`). Seats that are not for sale are refused with 409 `SEAT_NOT_FOR_SALE`, except a seat with an active **resale** listing in a season member whose for-sale configuration does not propagate (`forSalePropagated: false`, e.g. a season-ticket seat its holder resells for one game); the confirmation and the order commit apply the same rule.
1022
1022
  # @param idempotency_key [String] Required deduplication key (max 255 chars after trim; UUID v4 recommended). 24h idempotent cache replay in Redis per tenant.
1023
1023
  # @param post_api_seats_reserve_request [PostApiSeatsReserveRequest]
1024
1024
  # @param [Hash] opts the optional parameters
@@ -87,7 +87,7 @@ module SeatsChart
87
87
  end
88
88
 
89
89
  # Monthly usage: used objects, charts and events
90
- # Sandboxes (`isTest: true`) are metered so their usage can be seen, but never billed and never held to plan limits (`limit: null`). `usedObjects.count` is the number of distinct objects booked in the UTC calendar month (seats.io-style billing unit): every seat that became booked counts once per month however often it is retried, released and re-booked; each sold general-admission place counts as one. Holds, test events and replays never count. Map-only renders (`bringYourOwnBackend`) count every object of the rendered chart once per chart and month (`byEvent` entry with the chart id and `mapOnly: true`). `history` has exactly 12 months ending at `month` (zero-filled); `byEvent` lists the top 100 events of the month. `charts`/`events` are current totals against the plan limits. Dashboard JWT (any role) or an API key with the `reports` scope.
90
+ # Sandboxes (`isTest: true`) are metered so their usage can be seen, but never billed and never held to plan limits (`limit: null`). `usedObjects.count` is the number of distinct objects booked in the UTC calendar month (seats.io-style billing unit): every seat that became booked counts once per month however often it is retried, released and re-booked; each sold general-admission place counts as one. Holds, test events and replays never count. Map-only renders (`bringYourOwnBackend`) count every object of the rendered chart once per chart and month (`byEvent` entry with the chart id and `mapOnly: true`). `history` has exactly 12 months ending at `month` (zero-filled); `byEvent` lists the top 100 events of the month. `charts`/`events` are this workspace's current totals; the plan limits count every production workspace of the billing account together (`account.charts` / `account.events`). `account`: the billing account the workspace belongs to (one plan for all its workspaces) with `ownerEmail`, `isOwner`, `workspaceCount` and the account totals `charts`, `events` and `usedSeats` of the month; `null` in a sandbox or without an account. `seats`: the used seats (the billing unit: one per event, object and month; the same seat sold in two events counts twice) of the billing account in the month — every production workspace of the account, an organizer workspace of a ticketing platform with the platform — with `includedSeats`, `mode` (`overage`: paid plan, extra seats billed per seat; `allowance`: Free, new events and putting events on sale pause above it; `on_demand`: Ultra On-Demand, every seat billed by the SeatsChart team), `overage` { seats, costCents } so far, `projected` (current month at the current pace) and `allowanceExceeded`; `null` in a test workspace. Dashboard JWT (any role) or an API key with the `reports` scope.
91
91
  # @param [Hash] opts the optional parameters
92
92
  # @option opts [String] :month UTC calendar month `YYYY-MM` (default: current month).
93
93
  # @return [nil]
@@ -97,7 +97,7 @@ module SeatsChart
97
97
  end
98
98
 
99
99
  # Monthly usage: used objects, charts and events
100
- # Sandboxes (`isTest: true`) are metered so their usage can be seen, but never billed and never held to plan limits (`limit: null`). `usedObjects.count` is the number of distinct objects booked in the UTC calendar month (seats.io-style billing unit): every seat that became booked counts once per month however often it is retried, released and re-booked; each sold general-admission place counts as one. Holds, test events and replays never count. Map-only renders (`bringYourOwnBackend`) count every object of the rendered chart once per chart and month (`byEvent` entry with the chart id and `mapOnly: true`). `history` has exactly 12 months ending at `month` (zero-filled); `byEvent` lists the top 100 events of the month. `charts`/`events` are current totals against the plan limits. Dashboard JWT (any role) or an API key with the `reports` scope.
100
+ # Sandboxes (`isTest: true`) are metered so their usage can be seen, but never billed and never held to plan limits (`limit: null`). `usedObjects.count` is the number of distinct objects booked in the UTC calendar month (seats.io-style billing unit): every seat that became booked counts once per month however often it is retried, released and re-booked; each sold general-admission place counts as one. Holds, test events and replays never count. Map-only renders (`bringYourOwnBackend`) count every object of the rendered chart once per chart and month (`byEvent` entry with the chart id and `mapOnly: true`). `history` has exactly 12 months ending at `month` (zero-filled); `byEvent` lists the top 100 events of the month. `charts`/`events` are this workspace's current totals; the plan limits count every production workspace of the billing account together (`account.charts` / `account.events`). `account`: the billing account the workspace belongs to (one plan for all its workspaces) with `ownerEmail`, `isOwner`, `workspaceCount` and the account totals `charts`, `events` and `usedSeats` of the month; `null` in a sandbox or without an account. `seats`: the used seats (the billing unit: one per event, object and month; the same seat sold in two events counts twice) of the billing account in the month — every production workspace of the account, an organizer workspace of a ticketing platform with the platform — with `includedSeats`, `mode` (`overage`: paid plan, extra seats billed per seat; `allowance`: Free, new events and putting events on sale pause above it; `on_demand`: Ultra On-Demand, every seat billed by the SeatsChart team), `overage` { seats, costCents } so far, `projected` (current month at the current pace) and `allowanceExceeded`; `null` in a test workspace. Dashboard JWT (any role) or an API key with the `reports` scope.
101
101
  # @param [Hash] opts the optional parameters
102
102
  # @option opts [String] :month UTC calendar month `YYYY-MM` (default: current month).
103
103
  # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers
@@ -478,7 +478,7 @@ module SeatsChart
478
478
  end
479
479
 
480
480
  # Monthly used objects across my workspaces (admin view)
481
- # Every workspace the caller administers (role admin), with its plan, status and used objects of the month against the plan limit (`null` for sandboxes, which are metered but never billed), plus the total of the production workspaces (`usedObjects`) and, separately, of the sandboxes (`sandboxUsedObjects`). Dashboard session, or a **workspace admin API key** (the admin it is bound to); other API keys: 403 `ERR_PARTNER_SCOPE`. One grouped read of the metering table.
481
+ # Every workspace the caller administers (role admin), with its plan, status and used objects of the month against the plan limit (`null` for sandboxes, which are metered but never billed), plus the total of the production workspaces (`usedObjects`) and, separately, of the sandboxes (`sandboxUsedObjects`). Each item names its billing account (`billingOwnerUserId`); `accounts` lists those accounts (the caller's own first) with the owner, the plan and the totals of every production workspace of the account (`workspaceCount`, `charts`, `events`, `usedObjects` against the plan's included seats), since one plan covers them all. Dashboard session, or a **workspace admin API key** (the admin it is bound to); other API keys: 403 `ERR_PARTNER_SCOPE`. One grouped read of the metering table.
482
482
  # @param [Hash] opts the optional parameters
483
483
  # @option opts [String] :month UTC calendar month &#x60;YYYY-MM&#x60; (default: current month).
484
484
  # @return [nil]
@@ -488,7 +488,7 @@ module SeatsChart
488
488
  end
489
489
 
490
490
  # Monthly used objects across my workspaces (admin view)
491
- # Every workspace the caller administers (role admin), with its plan, status and used objects of the month against the plan limit (&#x60;null&#x60; for sandboxes, which are metered but never billed), plus the total of the production workspaces (&#x60;usedObjects&#x60;) and, separately, of the sandboxes (&#x60;sandboxUsedObjects&#x60;). Dashboard session, or a **workspace admin API key** (the admin it is bound to); other API keys: 403 &#x60;ERR_PARTNER_SCOPE&#x60;. One grouped read of the metering table.
491
+ # Every workspace the caller administers (role admin), with its plan, status and used objects of the month against the plan limit (&#x60;null&#x60; for sandboxes, which are metered but never billed), plus the total of the production workspaces (&#x60;usedObjects&#x60;) and, separately, of the sandboxes (&#x60;sandboxUsedObjects&#x60;). Each item names its billing account (&#x60;billingOwnerUserId&#x60;); &#x60;accounts&#x60; lists those accounts (the caller&#39;s own first) with the owner, the plan and the totals of every production workspace of the account (&#x60;workspaceCount&#x60;, &#x60;charts&#x60;, &#x60;events&#x60;, &#x60;usedObjects&#x60; against the plan&#39;s included seats), since one plan covers them all. Dashboard session, or a **workspace admin API key** (the admin it is bound to); other API keys: 403 &#x60;ERR_PARTNER_SCOPE&#x60;. One grouped read of the metering table.
492
492
  # @param [Hash] opts the optional parameters
493
493
  # @option opts [String] :month UTC calendar month &#x60;YYYY-MM&#x60; (default: current month).
494
494
  # @return [Array<(nil, Integer, Hash)>] nil, response status code and response headers