Aller au contenu

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.

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.

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.

  • 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. Un PATCH qui les envoie est un 400.
  • guest et guest_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.
  • source et booking_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 un 400 qui nomme le champ.

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.
  • guest est toujours l’identifiant gst_…. Un webhook ne l’étend jamais et il n’existe aucun expand pour le demander.
  • events et modification_token ne 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.