Release seats
Returns seats to `free`. With `holdToken`, only rows under that token are released (secret key: held and booked; public key: held only — booked seats are never released by a public key). `objectLabels` may be omitted when `holdToken` is given = everything that token holds on the event. Without `holdToken` (secret key only) any held or booked individual seat is released (admin release); a general-admission area always requires `holdToken` (`400 hold_token_required`), and so does every public-key call. Idempotent: labels that are already free — including an expired hold, swept or not — come back in `alreadyFree[]` with `200`. If any label is held/booked by a different token (or booked and the caller is a public key) the whole request fails `409 not_held_by_token` with `failed[]` and nothing is released (all-or-nothing). GA entries in `released[]` carry the freed `quantity`. Emits one `seat.released` webhook per released row.
/api/v1/events/{eventKey}/seats/releasePath Parameters
Labels to release (single seat = array of one). Optional when holdToken is given: omitted = everything that token holds on the event (public key: held rows; secret key: held and booked rows). Labels that are already free are returned in alreadyFree[], not treated as failures.
1 <= items <= 200Hold token that reserved (or booked) the seats. When given, only rows under this token are released. REQUIRED for public keys (which can only release held rows) and for general-admission areas. A secret key may omit it for individual seats (admin release of any held/booked seat).
1 <= lengthResponse Body
curl -X POST "https://seatbuilder.org/api/v1/events/string/seats/release" \ -H "Content-Type: application/json" \ -d '{ "objectLabels": [ "A-12", "A-13" ], "holdToken": "7f6c3a91-b1ef-4d0a-9c84-3f12a8e0b5d2" }'{
"chartKey": "chart_8a2b1c",
"eventKey": "evt_q3-2026-jazz-night",
"status": "free",
"releasedAt": "2026-10-02T19:15:30.000Z",
"released": [
{
"objectLabel": "A-12"
},
{
"objectLabel": "GA-LAWN",
"quantity": 2
}
],
"alreadyFree": [
{
"objectLabel": "A-13"
}
]
}{
"statusCode": 0,
"error": "string",
"message": "string",
"code": "validation_failed",
"failed": [
{
"objectLabel": "string",
"reason": "string",
"eventKey": "string",
"environment": "string",
"booked": 0,
"held": 0
}
],
"errors": {
"property1": [
"string"
],
"property2": [
"string"
]
}
}{
"statusCode": 0,
"error": "string",
"message": "string",
"code": "validation_failed",
"failed": [
{
"objectLabel": "string",
"reason": "string",
"eventKey": "string",
"environment": "string",
"booked": 0,
"held": 0
}
],
"errors": {
"property1": [
"string"
],
"property2": [
"string"
]
}
}{
"statusCode": 0,
"error": "string",
"message": "string",
"code": "validation_failed",
"failed": [
{
"objectLabel": "string",
"reason": "string",
"eventKey": "string",
"environment": "string",
"booked": 0,
"held": 0
}
],
"errors": {
"property1": [
"string"
],
"property2": [
"string"
]
}
}{
"statusCode": 0,
"error": "string",
"message": "string",
"code": "validation_failed",
"failed": [
{
"objectLabel": "string",
"reason": "string",
"eventKey": "string",
"environment": "string",
"booked": 0,
"held": 0
}
],
"errors": {
"property1": [
"string"
],
"property2": [
"string"
]
}
}{
"statusCode": 409,
"error": "Conflict",
"message": "One or more seats could not be released",
"code": "not_held_by_token",
"failed": [
{
"objectLabel": "A-13",
"reason": "not_held_by_token"
}
]
}Book held seats POST
Secret key only (a public key gets `403 public_key_not_allowed`). Confirms one or more previously-held seats as booked in a single atomic, all-or-nothing batch. Booked rows keep the `holdToken` that booked them (so the same token can later release them); tokens are never included in responses or webhooks. 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. Safe to retry: seats already booked under this `holdToken` are returned unchanged (same `bookedAt`) without another webhook or usage count; a mix books the held ones and returns all.
Extend held seats POST
Secret key only (a public key gets `403 public_key_not_allowed`). Refresh the hold TTL (payment window) for one or more seats the caller already holds. Batch + partial-success: seats that cannot be extended are returned in failed[] without failing the request, with `reason` `already_booked` (booked under this token), `hold_expired` (this token's hold lapsed) or `not_held_by_token`. `objectLabels` omitted = every row the token has on the event. If the token has nothing on the event → `409 no_active_hold`.