Answer the venue's intake form
/api/book/{slug}/manage/{token}The guest fills in whatever questions the org defined for this booking (migration 0024). Serves both engines for the same reason PATCH does; the token is a link to a booking, and which engine that booking belongs to is resolved from the org's business_type inside loadByToken.
PUT rather than POST because there is exactly one response per booking, enforced by a partial unique index per subject id: a guest reopening their link EDITS their answers rather than stacking a second submission staff would have to reconcile.
The form is re-resolved server-side rather than taken from the body: the page may have been rendered days ago, and the org may have switched forms or deactivated one since. A service-specific form wins over the org-wide one, and only active forms are served. Answers are validated against that form; required questions present, dropdown answers within their options, lengths capped, and fields_snapshot is rewritten from it on every save, so staff always read these answers against the questions that were actually on screen.
Deliberately NOT gated on the org's guest-self-service policy, unlike PATCH and DELETE, and for the same reason POST is not: an org that switched off guest rescheduling still asked these questions, and a notice period is backwards here; the hour before a visit is exactly when someone remembers their allergy.
Path Parameters
The organization's public booking slug, i.e. the {slug} in /{slug}. Only orgs with status active resolve; anything else is a 404.
The booking's manage token.
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X PUT "https://example.com/api/book/string/manage/string" \ -H "Content-Type: application/json" \ -d '{ "answers": { "property1": "string", "property2": "string" } }'{ "ok": true}Cancel a booking DELETE
Sets status to `cancelled` rather than deleting, so the venue keeps the history and the slot or table is released by exactly the rules a staff cancellation uses. Compare-and-set on the current status.
Submit the private half of a booking's post-visit feedback POST
The other branch of the post-visit satisfaction gate a completed booking is emailed (see notifyBookingCompleted/notifyReservationCompleted): a guest who says a visit was NOT great lands here instead of the org's public Google review link, so the negative signal still reaches the business without ever becoming a public review. No slug, unlike the manage-link endpoint; the `manage_token` is unique across both engines by construction and is the whole credential, so it resolves a booking on its own. Guest name/email are read from the booking's own customer record rather than trusted from the request body, since the token already proves who this is. PUT-like replace semantics on a POST: a guest reopening the link edits their existing answer rather than stacking a second row, the same "one response per booking" convenience the intake form gives.