Guest self-service links
How the one-time /b link works: what guests can do themselves, token expiry, recovery when the link is lost, calendar files and offline behaviour.
Every booking has a private self-service page at /b, reached through a
one-time link rather than a password. The link carries a secret that works
once, opens a one-hour session, and can always be replaced by a fresh one.
Guests use it to check their booking’s status, download a calendar file,
answer a reconfirmation request, or cancel. Staff use the same commands from
the other side. Nothing about the page is public: it is not indexed, not
cached, and scoped to exactly one booking.
How the link reaches the guest
The confirmation email does not carry the link — it carries only the
DG-XXXXXXXX confirmation code, and the code alone never grants access. A
link is created in one of two ways:
- Recovery: the guest enters the email they booked with and their
confirmation code on the
/blanding page. If the pair matches a booking, a fresh link is queued to the address already on the booking. - Staff issuance: a member of the venue’s team issues the link for a reservation and hands it over directly, which is the normal route in this pilot — see the pilot note below.
The link looks like /b# followed by a 43-character secret. The secret is
the raw credential, so the link is shown once per issuance and never logged.
Opening the link — what happens in the browser
The page reads the secret from the part of the address after the # sign,
strips it from the address bar, and exchanges it through a single one-time
request. A consumed, expired, revoked or unknown secret all return the same
generic denial, TOKEN_INVALID — the page says: “This link has already been
used, expired, or was replaced by a newer one. Request a fresh link below.”
No answer ever distinguishes which of those happened, so a link can never
become a way to probe bookings.
A successful exchange sets a one-hour capability cookie scoped to /b
(HttpOnly, SameSite Lax, secure on https) and opens the booking page. The
booking’s id in the address is a request, never the authority: a missing
cookie, an expired session or any mismatch answers the same plain 404 as an
unknown address. Opening the exchange is a browser step, so a link cannot
open a booking in a browser that blocks scripts; recovery by email and code
is the fallback.
Issuance always rotates: issuing a fresh link revokes the previous secret and every live session that secret had created. Handing someone “a fresh link” therefore also switches off the old one.
What a guest can do on the page
| Action | When it is offered | What happens |
|---|---|---|
| View the booking | always | status headline — “Waiting for the venue to confirm”, “Confirmed”, “Cancelled”, “Marked as a no-show”, “Declined by the venue” or “Expired” — plus when, party size, name and the “Cancellation terms” label (“Free cancellation” or “Late-cancellation terms apply”) |
| Add to your calendar (.ics) | always | downloads booking-{code}.ics with the event status mapped from the booking: confirmed, tentative for a pending request, or cancelled |
| Reconfirm | only while a venue request is outstanding | “Please reconfirm” with the button “Yes, I am coming” |
| Cancel | for CONFIRMED and REQUESTED bookings |
“Reason (optional)”, at most 500 characters; confirms with “Booking {code} cancelled (no charge).” or “Booking {code} cancelled (late terms applied).” |
What is deliberately not there: no rescheduling (guests cancel and rebook — see Changing & cancelling), no access to any other booking, and none of the venue’s internal data — staff notes, guest history and table allocations never reach this page. The page footer states it directly: “This page is private to your link. Need help? Use the link in your confirmation email — a fresh link reissue invalidates this one.”
If the link is lost or expired
The landing page’s “Lost your link?” section asks for the Email and the
Confirmation code (placeholder DG-XXXXXXXX) and answers the same line
no matter what: “If that email and code match a booking, a fresh link is on
its way.” A miss writes nothing, so guessing codes reveals nothing. Two
limits protect the flow: recovery is capped at 5 requests per email address
per hour (more answers RATE_LIMITED — “Too many attempts — please wait a
moment.”), and the exchange endpoint is capped at 60 attempts per hour per
source address.
Offline and privacy behaviour
Every /b response is sent with Cache-Control: no-store,
Referrer-Policy: no-referrer and X-Robots-Tag: noindex — the pages are
never cached by the browser or a search engine, and the secret never leaks
through a referrer. The installable app treats /b as network-only: no
capability response is ever stored on the device, and there is no offline
queue. If the device is offline, the app’s honest screen says so:
“Nothing you submitted was recorded, and nothing is waiting to be sent —
DineGlobe never stores bookings or arrivals on a device.” See
Offline & installable app.
Pilot note: no email provider is connected during the unpaid pilot, so a recovery email is composed and then recorded as a visible failed delivery rather than sent. Until a provider is connected, the practical route is staff issuance — the venue runs the issue command for your reservation and gives you the link directly. The same applies to every guest email described in Messages, confirmations & reminders.