Skip to content

The reservation object

A reservation is one party, on one service date, at one restaurant. The same object comes back from every call on Reservations, and it is what a reservation.* webhook delivers.

objectstring

Possible values: reservation

The object type: always reservation.

idstring

The booking’s id, resv_…. Opaque and permanent. A booking converted from a hold keeps that hold’s suffix: hold_AbC becomes resv_AbC.

statusstring

Possible values: awaiting_guarantee awaiting_guest held pending confirmed partially_seated seated completed cancelled no_show

Where the booking is in its lifecycle.

⚠️ held and awaiting_guest never appear on a reservation this API serves — a hold is its own object (GET /v1/holds) and a waitlist promotion awaiting its guest is not yet a booking — so no endpoint, and no reservation.* webhook, can carry either value. They are listed because the enum is the platform’s own and codegen reads it verbatim. awaiting_guarantee DOES appear: it is a booking waiting for the guest to save a card.

There is no late. The restaurant’s screens show a party as late from its start time, but that is worked out on the spot and never stored, so a late party keeps the status it had, usually confirmed.

sourcestring

Possible values: manual widget walk_in import waitlist api

The mechanism that created the booking. See booking_channel for the channel the demand arrived through — a waitlist booking promoted by staff still has the channel the guest joined through.

  • manual: entered by the restaurant’s staff.
  • widget: made by the guest in the restaurant’s booking widget, including a widget embedded on a partner’s page.
  • walk_in: a party seated without a booking.
  • import: brought over from the restaurant’s previous reservation system.
  • waitlist: came out of the waitlist.
  • api: created through this API (POST /v1/reservations).

booking_channelstring

Possible values: back_office website_widget phone walk_in google_reserve partner_platform api

The channel the demand arrived through, as opposed to source, the mechanism.

  • back_office: taken by the restaurant’s staff.
  • website_widget: the restaurant’s own booking widget.
  • phone: taken by telephone.
  • walk_in: a party that walked in.
  • google_reserve: booked through Google.
  • partner_platform: taken in the booking widget embedded on a partner’s own page.
  • api: created through this API (POST /v1/reservations), including a hold converted into a booking.

party_sizeinteger

How many guests the booking is for.

service_datestring (date)

The service day the booking belongs to, YYYY-MM-DD in the restaurant’s timezone. A seating after midnight in a service that began the evening before keeps that evening’s date, so it can differ from the date in starts_at.

starts_atstring (date-time)

When the party is due to sit down: ISO 8601 with the restaurant’s UTC offset, e.g. 2026-07-01T20:00:00+02:00.

ends_atstring (date-time)optionalnullable

When the table is expected back, in the same format as starts_at. null when no seating duration applies to the booking.

guest_notesstringoptionalnullable

What the guest asked for, in their own words. Guest data: present only when your key carries guests:read — on every booking alike, including the ones your key made. Otherwise the field is absent, not null. Every webhook delivery carries it.

guest_notificationsstring

Possible values: service_managed partner_managed

Who writes to the guest about this booking. partner_managed means we send none of the discretionary guest messages for it. Treat the list as open.

excluded_from_shift_limitsboolean

True when this booking does not count against the shift’s covers caps — a private event seated apart from the room those caps describe.

Those caps do not refuse it either, so a party larger than the covers left is booked rather than turned away. It still holds its table, and it still appears in every count of guests.

Setting it requires the reservations:write:override scope, except on a whole-section booking (entire_section_id), where it is the default.

contact_emailstringoptionalnullable

The e-mail address this booking’s messages go to, as given when it was made. null means the booking uses the guest profile’s address. Guest data: present only when your key carries guests:read — on every booking alike, including the ones your key made. Otherwise the field is absent, not null. Every webhook delivery carries it.

contact_phonestringoptionalnullable

The phone number this booking’s messages go to, as given when it was made. null means the booking uses the guest profile’s number. Present on the same terms as contact_email.

internal_notesstringoptionalnullable

The restaurant’s own note about this booking — what its staff would type into the reservation form. Not shown to the guest anywhere.

Guest data, and gated exactly like guest_notes: present only when your key carries guests:read — on every booking alike, including the ones your key made. Otherwise the field is absent, not null. Every webhook delivery carries it.

gueststring or Guestnullable

The guest the booking is for. By default their id, gst_…; the full Guest object when you pass ?expand=guest on GET /v1/reservations or GET /v1/reservations/{id}, which needs the guests:read scope — without it the request is refused with 403 insufficient_scope, never downgraded to the id. Writes and webhook deliveries always carry the id.

null when the booking is linked to no guest profile: a walk-in seated without details, or a booking whose guest was deleted.

companyobjectnullable

The company the booking is made for, when it was filed under one — by the restaurant’s staff, or by company_id on your own create or PATCH. null otherwise, which is the common case; the key is always present. Readable by every key with reservations:read, unlike the guest’s own details.

objectstring

Possible values: company

The object type: always company.

idstring

The company’s id, cmp_….

namestring

The company’s name, as the restaurant recorded it.

tablesarray of Table

The tables the booking is seated at, each with its seating area. [] while no table is assigned.

guaranteeGuaranteeoptionalnullable

The card guarantee attached to the booking. null when it has none. Always included; no scope or expand needed.

metadataobjectoptional

Your own reconciliation data, echoed verbatim on every read and webhook; {} when there is none.

Set once, when the booking is made, and never changed afterwards — PATCH refuses it. It comes from metadata on POST /v1/reservations, or from the hold the booking was converted from. A booking made in the restaurant’s own widget carries metadata only when the widget was embedded by a partner platform that signed it into its identity assertion; an unsigned widget booking never has any.

⚠️ Readable by every integration this restaurant has authorised, not only by the one that wrote it. Put reconciliation ids here, not commercial terms.

eventsarray of ReservationEventoptional

The booking’s lifecycle events, oldest first — the same list GET /v1/reservations/{id}/events returns. Present only when you pass ?expand=events on a read, which needs no scope beyond reservations:read; absent otherwise, never an empty stand-in.

modification_tokenstringoptional

The guest’s own credential for their booking page. That page is on the booking host that public_booking_url in GET /v1/configuration names, not on this API, and the link is {public_booking_url}/{modification_token}, the same link the confirmation e-mail sends the guest.

Whoever holds it can do on that page everything the guest can: read, change or cancel the booking and, while it is awaiting_guarantee, complete the card step. Pass it only to the guest, as the link to their own page; never log it, display it or keep it longer than you need it. The endpoints behind that page are the booking widget’s, not part of this API.

⚠️ Present ONLY on the POST /v1/reservations response, and only when you ask with ?expand=modification_token and your key carries guests:read (it reads the guest’s contact details, so it is gated like the guest book). Reads, lists and webhooks never carry it — capture it at create time. Never null when present.

How long it lasts. It is minted once, when the booking is created, and never rotates: the value you capture is the value that booking keeps. It carries no expiry of its own and stays usable for as long as the booking is live, which in practice means until the party has been and gone. Cancelling — by you, by the guest or by a card request lapsing — retires it, and so does the restaurant marking the booking a no-show: the page answers 404 from then on, exactly as it does for a token that was never issued. There is no way to revoke it while the booking stands, which is the other half of “never log it”: if it leaks, the remedy is to cancel and rebook.

created_atstring (date-time)

When the booking was recorded: ISO 8601 with the restaurant’s UTC offset.

updated_atstring (date-time)

When anything on the booking last changed, in the same format. The value updated_since compares against.

The status a booking is born in is the restaurant’s decision, not yours. Under manual approval it lands pending. On a slot that carries a card guarantee it lands awaiting_guarantee and the guest is emailed a payment link. Otherwise it lands confirmed, which is the only value that means the table is booked.

Your key moves a booking two ways. A PATCH can push a confirmed booking back to pending when the new slot or party size needs the restaurant’s approval, and POST /v1/reservations/{id}/cancel makes it cancelled. Every other move is the restaurant’s staff working its own floor: seating a party takes the booking through partially_seated to seated, completed when the table is given back, and no_show when nobody arrives. You see those as events and as webhooks.

Three statuses are final for this API. PATCH on a completed, no_show or cancelled booking is a 409 with reservation_finalized, and so is cancelling one that is completed or no_show. Cancelling a booking that is already cancelled returns 200 and the same object, so a retry that lands twice needs no special case.

Four fields are guest data — guest_notes, internal_notes, contact_email and contact_phone. A key without guests:read does not receive them on any booking, and they are absent rather than null, so a null you do read is the restaurant’s own empty value. The rule and the scope are on Authentication.

Two fields arrive only when you ask for them. ?expand=guest replaces the guest id with the whole guest object and needs guests:read; a key without it is refused with 403, never quietly handed the id instead. ?expand=events attaches the lifecycle history and needs nothing beyond reservations:read. See Expanding objects.

modification_token is narrower still: it appears on the 201 of POST /v1/reservations, and nowhere else. Capture it there or lose it.

  • id — permanent. A booking converted from a hold keeps that hold’s suffix.
  • metadata — written at create, or carried over from the hold, and never changed. A PATCH that sends it is a 400.
  • guest and guest_id — the booking stays with the profile it was made for.
  • guest_notifications — fixed for the life of the booking. A confirmation that has been sent cannot be unsent, and one that was suppressed cannot be sent late. Cancel and rebook for a different answer.
  • source and booking_channel — a record of how the booking arrived. This API never writes either, and sending one on a create is a 400 naming the field.

Every reservation.* delivery puts the whole object in data.object, in the same shape a GET returns — with three differences that catch people out:

  • The four guest-data fields are on every delivery, whatever scopes the key behind the endpoint holds. An endpoint you register is a place you asked for guest data to be sent.
  • guest is always the gst_… id. A webhook never expands it, and there is no expand to ask with.
  • events and modification_token never travel. Both exist only on a read you asked to expand, and on the create response respectively.

Webhooks covers registration and signing; the event catalog says which change fires which event type.