Skip to content

The hold object

A hold is a claim on a slot that occupies a real table without being a booking. It comes back from every call on Holds and from every hold.* webhook.

objectstring

Possible values: hold

The object type: always hold.

idstring

Opaque hold id (hold_…). A hold and the reservation it becomes are the same row and share this id’s suffix, so hold_AbC converts into resv_AbC.

kindstring

Possible values: basket commitment

basket releases the table the instant expires_at passes; commitment keeps it until the sweep that runs every five minutes picks the hold up. Both lapse on their own; only the minutes between the deadline and the table reopening differ.

statusstring

Possible values: held expired released converted

Lifecycle of the hold itself, not of a reservation.

  • held: live and occupying a table. The only state a conversion works from.
  • expired: the deadline passed and the table is back on sale. On a basket hold this is reported from the moment expires_at passes, because that kind reopens its table at read time. On a commitment hold the table is held past the deadline until the five-minute sweep resolves it, so the hold reads held for up to five minutes after expires_at and expired from then on. Either way it is the same lapse, and hold.expired announces it.
  • released: handed back deliberately — you called DELETE /v1/holds/{id}, or the restaurant released it from its own board.
  • converted: it became the booking named in reservation.

party_sizeinteger

How many guests the held seating is for.

service_datestring (date)

The service day of the held seating, YYYY-MM-DD in the restaurant’s timezone. A seating after midnight keeps the date its service began on.

starts_atstring (date-time)

Start of the SEATING the hold covers — not the hold deadline. ISO 8601 with the restaurant’s UTC offset.

ends_atstring (date-time)optionalnullable

End of the seating the hold covers, in the same format. null when no seating duration applies.

expires_atstring (date-time)nullable

When the hold lapses. Authoritative: the server sets it, clamping whatever was requested. Null once the hold is over.

ended_atstring (date-time)nullable

When the hold was released or lapsed. Null while it is live, and null once it has converted — a converted hold did not end, it became the booking named in reservation.

reservationstringnullable

The booking this hold became (resv_…), or null.

tablesarray of Table

The tables the hold occupies, each with its seating area.

excluded_from_shift_limitsboolean

True when this hold does not count against the shift’s covers caps, with the same meaning as on a reservation: they neither charge it nor refuse it. It is carried onto the booking when the hold converts, so converting an exempt hold needs the reservations:write:override scope.

metadataobject

Your own reconciliation data, echoed verbatim. Carried onto the reservation when the hold converts. ⚠️ Readable by every integration this restaurant has authorised, not only by the one that wrote it: holds are scoped to the restaurant, so another of its API keys can read this hold and this object. Put reconciliation ids here, not commercial terms or anything you would not show a competitor.

created_atstring (date-time)

When the hold was taken: ISO 8601 with the restaurant’s UTC offset.

updated_atstring (date-time)

When the hold last changed, in the same format.

A hold is born held and leaves that state exactly once. You release it (released), it lapses on its own (expired), or it becomes the booking named in reservation (converted). All three are terminal, and held is the only state a conversion works from.

kind decides how fast a lapse shows up rather than whether one happens. Both kinds lapse on their own; the minutes between the deadline and the table reopening are what differ, and the field’s own description says by how much.

Three things travel from the hold to the booking it becomes, which is why they are worth setting on the hold rather than on the create:

  • The id’s suffix. hold_AbC converts into resv_AbC, so a reference you stored against the hold still points at the booking.
  • metadata, verbatim.
  • excluded_from_shift_limits. Converting an exempt hold therefore needs the reservations:write:override scope, the same as setting it on a booking.

A hold has no guest, no contact details and no guest_notes. Those arrive at conversion, on the POST /v1/reservations that carries the hold_id.

hold.created, hold.converted, hold.released and hold.expired deliver the whole object in data.object. Which change fires which one is in the event catalog.