Skip to Content
📚 Documentation is in active development — pages marked TODO will fill out over the next few weeks.
API referenceCancel-by-token

Cancel by token

POST /api/public/bookings/cancel-by-token Content-Type: application/json { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }

The token is a JWT signed at booking-create time with claims:

  • bookingId
  • agencyId
  • exp — slot start + 60s (past that point the customer should call the business)

Verified server-side; mismatched signature / expired → 400.

Response

Success:

{ "ok": true, "alreadyCancelled": false, "startAt": "2026-06-01T03:30:00.000Z" }

Already cancelled (idempotent):

{ "ok": true, "alreadyCancelled": true, "startAt": "2026-06-01T03:30:00.000Z" }

Terminal status (NO_SHOW / COMPLETED): 409

Invalid / expired: 400 with code: "INVALID" | "EXPIRED".

Why POST not DELETE

Customer reaches this via a link they click in the confirmation screen. POST avoids the GET-link-prefetch problem where an over-eager mail client would auto-cancel the booking on link hover.

The token lives in the body (not URL query) for the same reason.

Idempotency

Calling cancel twice on the same booking returns success both times. The first one deletes the Google event + flips status; the second is a no-op.

Last updated on