Extend held seats
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`.
/api/v1/events/{eventKey}/seats/extendPath Parameters
Client-generated token identifying the hold session (≥ 8 chars; recommended: random UUID).
8 <= lengthSeat labels to extend. Omit to extend every seat currently held by this token.
1 <= items <= 200New hold lifetime in seconds (payment window). Defaults to 600 (10 min) when omitted; capped at 3600 (1 hour).
0 < value <= 3600Response Body
curl -X POST "https://seatbuilder.org/api/v1/events/string/seats/extend" \ -H "Content-Type: application/json" \ -d '{ "holdToken": "stringst" }'{
"holdExpiresAt": "2026-10-02T18:55:00.000Z",
"extended": [
{
"objectLabel": "A-12"
}
],
"failed": [
{
"objectLabel": "A-13",
"reason": "not_held_by_token"
}
]
}{
"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": 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"
]
}
}Release seats POST
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.
Reset a sandbox event POST
Sandbox events only, secret key only. Returns every seat and GA area of the event to `free`: deletes all holds, bookings and not-for-sale marks, so the event can be reused between test runs. Pending hold expiries become no-ops. No webhooks are sent and nothing is written to seat history. A production event returns `403 sandbox_only`; a public key returns `403 public_key_not_allowed`.