Book held seats
Confirms one or more previously-held seats as booked in a single atomic, all-or-nothing batch. Pass every seat label in `objectLabels[]`; all must currently be held under the same `holdToken` returned from `/hold`. If any one seat is no longer held by that token, the whole request fails with `409` and nothing is booked. Booked seats remain in `booked` status until explicitly released via `/release`. Emits one `seat.booked` webhook per booked seat if a subscription exists.
/api/v1/events/{eventKey}/seats/bookPath Parameters
Seat labels to book in one atomic request. Single seat = array of one. All must be held by the supplied holdToken or the whole request fails.
1 <= items <= 200The holdToken returned from the preceding /hold call(s). All listed labels must be held under this token.
1 <= lengthArbitrary JSON metadata merged onto EVERY booked seat (e.g. one { orderId } for the whole order).
Empty Object
Response Body
curl -X POST "http://localhost:3000/api/v1/events/string/seats/book" \ -H "Content-Type: application/json" \ -d '{ "objectLabels": [ "string" ], "holdToken": "string" }'{
"booked": [
{
"chartKey": "chart_8a2b1c",
"eventKey": "evt_q3-2026-jazz-night",
"objectLabel": "A-12",
"status": "booked",
"bookedAt": "2026-10-02T18:46:00.000Z",
"extraData": {
"orderId": "ord_98a2"
}
},
{
"chartKey": "chart_8a2b1c",
"eventKey": "evt_q3-2026-jazz-night",
"objectLabel": "A-13",
"status": "booked",
"bookedAt": "2026-10-02T18:46:00.000Z",
"extraData": {
"orderId": "ord_98a2"
}
}
]
}{
"statusCode": 0,
"message": "string",
"errors": {
"property1": [
"string"
],
"property2": [
"string"
]
}
}{
"statusCode": 0,
"message": "string",
"errors": {
"property1": [
"string"
],
"property2": [
"string"
]
}
}{
"statusCode": 0,
"message": "string",
"errors": {
"property1": [
"string"
],
"property2": [
"string"
]
}
}{
"statusCode": 0,
"message": "string",
"errors": {
"property1": [
"string"
],
"property2": [
"string"
]
}
}{
"error": "One or more seats are no longer held by this token",
"failed": [
{
"objectLabel": "A-13",
"reason": "not_held_by_token"
}
]
}{
"statusCode": 0,
"message": "string",
"errors": {
"property1": [
"string"
],
"property2": [
"string"
]
}
}Hold seats POST
Places a hold on the requested seat label for the calling workspace. The hold lasts `ttlSeconds` (default 900). Pass the returned `holdToken` to `/book` to confirm purchase or `/release` to cancel. Holds expire automatically; subscribers to `seat.hold_expired` receive a webhook on expiry. Atomic via Redis SET NX EX — concurrent hold attempts on the same seat never double-book.
Release seats POST
Returns one or more seats to `free` status in a single atomic, all-or-nothing batch. Works on both held and booked seats. Use this when a purchase is cancelled, a hold needs to be voluntarily released before TTL expiry, or a booking is refunded. If any one requested label is not currently held or booked, the whole request fails with `409` and nothing is released. Emits one `seat.released` webhook per released seat if a subscription exists.