L'objet réservation
Une réservation, c’est une table, une date de service et un restaurant. Le même
objet revient de tous les appels de
Réservations et c’est lui qu’un webhook
reservation.* livre.
Le tableau ci-dessous est généré depuis la spécification OpenAPI et reste en anglais, comme la référence de l'API : noms de champs, valeurs d'énumération et descriptions viennent du backend. Une traduction serait une copie qui ment dès la première évolution du contrat.
objectstring
Valeurs possibles : 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
Valeurs possibles : 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
Valeurs possibles : 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
Valeurs possibles : 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)facultatifnullable
When the table is expected back, in the same format as starts_at. null when no seating duration applies to the booking.
guest_notesstringfacultatifnullable
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
Valeurs possibles : 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_emailstringfacultatifnullable
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_phonestringfacultatifnullable
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_notesstringfacultatifnullable
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
Valeurs possibles : 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.
guaranteeGuaranteefacultatifnullable
The card guarantee attached to the booking. null when it has none. Always included; no scope or expand needed.
metadataobjectfacultatif
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 ReservationEventfacultatif
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_tokenstringfacultatif
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.
Les statuts et qui les déplace
Section intitulée « Les statuts et qui les déplace »Le statut de naissance d’une réservation appartient au restaurant, pas à vous.
Sous validation manuelle elle arrive en pending. Sur un créneau qui demande une
garantie par carte elle arrive en awaiting_guarantee et le client reçoit un
lien de paiement par e-mail. Sinon elle arrive en confirmed, la seule valeur qui
veut dire que la table est réservée.
Votre clé déplace une réservation de deux façons. Un PATCH peut ramener une
réservation confirmed en pending quand le nouveau créneau ou le nouveau
nombre de couverts demande la validation du restaurant, et
POST /v1/reservations/{id}/cancel la passe en cancelled. Tous les autres
mouvements appartiennent au personnel du restaurant sur sa propre salle : placer
une table la fait passer par partially_seated puis seated, completed quand
la table est rendue et no_show quand personne ne vient. Vous les voyez sous
forme d’événements et de webhooks.
Trois statuts sont définitifs pour cette API. Un PATCH sur une réservation
completed, no_show ou cancelled est un 409 avec
reservation_finalized, et annuler une
réservation completed ou no_show aussi. Annuler une réservation déjà
cancelled renvoie 200 et le même objet : une reprise qui passe deux fois ne
demande aucun cas particulier.
Ce que votre clé peut lire
Section intitulée « Ce que votre clé peut lire »Quatre champs sont des données client — guest_notes, internal_notes,
contact_email et contact_phone. Une clé sans guests:read ne les reçoit sur
aucune réservation, et ils sont absents plutôt que nuls : un null que vous
lisez est donc bien la valeur vide du restaurant. La règle et la portée sont sur
Authentification.
Deux champs n’arrivent que si vous les demandez. ?expand=guest remplace
l’identifiant du client par l’objet client entier et
demande guests:read ; une clé qui ne l’a pas reçoit un 403 et jamais
l’identifiant en repli. ?expand=events attache l’historique et ne demande rien
de plus que reservations:read. Voir Étendre les
objets.
modification_token est plus étroit encore : il apparaît sur le 201 de
POST /v1/reservations et nulle part ailleurs. Capturez-le là ou vous le perdez.
Ce qui est figé une fois la réservation créée
Section intitulée « Ce qui est figé une fois la réservation créée »id— permanent. Une réservation convertie depuis une option garde le suffixe de cette option.metadata— écrites à la création, ou reprises de l’option, et jamais modifiées. UnPATCHqui les envoie est un400.guestetguest_id— la réservation reste attachée à la fiche pour laquelle elle a été faite.guest_notifications— figé pour la vie de la réservation. Une confirmation envoyée ne se reprend pas et une confirmation supprimée ne s’envoie pas après coup. Annulez et refaites la réservation s’il vous faut une autre réponse.sourceetbooking_channel— la trace de la façon dont la réservation est arrivée. Cette API n’en écrit aucun des deux et en envoyer un à la création est un400qui nomme le champ.
Ce que porte un webhook
Section intitulée « Ce que porte un webhook »Chaque livraison reservation.* met l’objet entier dans data.object, dans la
forme que renvoie un GET, avec trois différences qui surprennent :
- Les quatre champs de données client sont sur toutes les livraisons, quelles que soient les portées de la clé derrière le point de terminaison. Un point de terminaison que vous enregistrez est un endroit où vous avez demandé que ces données soient envoyées.
guestest toujours l’identifiantgst_…. Un webhook ne l’étend jamais et il n’existe aucunexpandpour le demander.eventsetmodification_tokenne voyagent jamais. Le premier n’existe que sur une lecture étendue, le second que sur la réponse de création.
Webhooks couvre l’enregistrement et la signature ; le catalogue d’événements dit quel changement déclenche quel type d’événement.