Skip to content

The guest object

A guest is one profile in the restaurant’s guest book. It is what Guests returns, what ?expand=guest embeds on a reservation or a waitlist entry, and what every guest.* webhook delivers.

objectstring

Possible values: guest

The object type: always guest.

idstring

The guest’s id, gst_…. Opaque and permanent. When two profiles are merged, the one that disappears keeps resolving to the survivor in ?id= on GET /v1/guests.

first_namestringnullable

First name. A profile has a first name or a last name, possibly both; null when it has only the other.

last_namestringnullable

Last name. null when the profile has only a first name.

emailstringoptionalnullable

Primary e-mail address, trimmed and lower-cased. null when none is known.

phonestringoptionalnullable

Primary phone number: E.164 (+33612345678) when it could be parsed for the restaurant’s country, otherwise as entered with separators removed — so do not assume E.164. null when none is known.

notesstringoptionalnullable

The restaurant’s own notes on the guest profile: free text written by its staff, or carried over from its previous reservation system — the restaurant’s words about the guest, not the guest’s. A booking’s guest_notes are the guest’s own. null when there are none.

blacklistedboolean

Whether the restaurant has flagged this guest as unwelcome. A flag only: it does not by itself refuse a booking.

blacklist_reasonstringoptionalnullable

Why the guest was flagged — required by the restaurant when it sets blacklisted. null when the guest is not flagged.

dietary_preferencesarray of string

Dietary preferences the restaurant recorded, as free-form labels. [] when none.

allergiesarray of string

Allergies the restaurant recorded, as free-form labels. [] when none.

birthdaystring (date)optionalnullable

Date of birth, YYYY-MM-DD. null when not recorded.

anniversarystring (date)optionalnullable

An anniversary date the restaurant recorded, YYYY-MM-DD. null when not recorded.

vipboolean

Whether the restaurant marked the guest as a VIP.

languagestringoptionalnullable

Possible values: fr en de es it nl pt da sv no fi

The language the restaurant writes to this guest in, as an ISO 639-1 code. Set to the restaurant’s primary language when the profile is created unless one is given, so null only on a profile that never had one.

sourcestring

Possible values: manual widget import host_assertion api website_newsletter

How the restaurant first learned of this guest. Not the same vocabulary as a reservation’s source.

  • manual: entered by the restaurant’s staff.
  • widget: first seen booking in the restaurant’s booking widget.
  • import: brought over from the restaurant’s previous reservation system.
  • host_assertion: first seen booking through the widget embedded on a partner’s page, with the partner vouching for their identity.
  • api: first seen on a booking created through this API.
  • website_newsletter: first seen signing up to the newsletter on the restaurant’s website.

marketing_email_consentboolean

Whether the guest agreed to receive marketing e-mail from the restaurant.

marketing_email_consent_atstring (date-time)optionalnullable

When marketing_email_consent last became true, ISO 8601 with the restaurant’s UTC offset. null while consent is false.

marketing_sms_consentboolean

Whether the guest agreed to receive marketing text messages from the restaurant.

marketing_sms_consent_atstring (date-time)optionalnullable

When marketing_sms_consent last became true, ISO 8601 with the restaurant’s UTC offset. null while consent is false.

visit_countinteger

How many of the guest’s bookings ended with them seated (seated, partially_seated or completed). Recomputed hourly, so it can trail a visit by up to about two hours.

no_show_countinteger

How many of the guest’s bookings ended no_show. Recomputed like visit_count.

cancellation_countinteger

How many of the guest’s bookings were cancelled, counting only bookings whose time has passed — a cancelled booking for next month is not counted until then. Recomputed like visit_count.

first_visit_atstring (date-time)optionalnullable

When the guest’s earliest visit (a booking counted in visit_count) started: ISO 8601 with the restaurant’s UTC offset, on the calendar day it actually started — a seating after midnight carries the next day’s date. null until they have one. Recomputed like visit_count.

last_visit_atstring (date-time)optionalnullable

When the guest’s latest visit started, in the same format as first_visit_at. null until they have one. Recomputed like visit_count.

created_atstring (date-time)

When the profile was created: ISO 8601 with the restaurant’s UTC offset.

updated_atstring (date-time)

When the profile last changed, in the same format. The value updated_since compares against.

There is no partial view of a profile. Every route to it — GET /v1/guests, GET /v1/guests/{id}, ?expand=guest — needs the guests:read scope, and a key without it is refused with 403 insufficient_scope rather than handed a thinner object. That is the difference from a reservation, where the same scope gates four fields and the rest come back regardless. See Authentication.

The counters — visit_count, no_show_count, cancellation_count — and the restaurant’s own flags are the restaurant’s record of this guest, not yours. They move when its staff work the floor.

The restaurant merges duplicate profiles, and the absorbed gst_… keeps resolving afterwards: GET /v1/guests/{absorbed_id} returns the surviving profile, under the survivor’s own id. Compare the id you get back with the one you sent to notice it. A guest.merged webhook announces the merge as it happens, and an unmerge is announced the same way — both are in the event catalog.

Every guest.* delivery puts the whole profile in data.object, contact details and all, whatever scopes the key behind the endpoint holds. A profile also reaches you attached to a booking, and there the rule is the reservation’s — see The reservation object.