Customer (end user)
Customers are end users who interact with tenant-branded sites. They are not
WorkOS users — they authenticate with a session token (stoken) issued by
scheduler-api.
Authentication
Section titled “Authentication”Customers do not have WorkOS accounts. Authentication is session-based:
- Customer provides their email (or phone) on the booking site.
scheduler-apiissues a stoken — a scoped bearer token tied to the customer record.- The stoken is sent in the
Authorization: Bearer <stoken>header on subsequent requests. - SSE streams (notifications, booking status) send the stoken as a query parameter
(
?stoken=…). This is required because the browserEventSourceAPI does not support custom headers. Mitigations in place: stokens are short-lived, scoped to a single customer record, and the SSE endpoint is served over HTTPS only.
See Glossary → stoken for the technical definition.
Surfaces
Section titled “Surfaces”Customers interact with whichever tenant site they landed on:
| App | Description |
|---|---|
site-main |
Main marketing site — generic storefront |
site-shop |
Multi-tenant e-commerce storefront (Vendure products) |
site-hypno |
Single-tenant booking + storefront reference implementation |
All three are TanStack Start apps sharing the same booking integration via
@nexus/business-client → @nexus/scheduler-sdk → scheduler-api.
Booking flow
Section titled “Booking flow”sequenceDiagram
actor C as Customer
participant Site as Tenant site
participant SDK as scheduler-sdk
participant API as scheduler-api
participant DB as Scheduler DB
participant Q as BullMQ
C->>Site: browse services + pick slot
Site->>SDK: book(request)
SDK->>API: POST /api/public/:slug/book
API->>API: validate (Zod contract)
API->>DB: insert booking (status=confirmed)
API->>Q: enqueue reminders (24h + 1h)
API-->>SDK: { data: booking }
SDK-->>Site: typed booking
Site-->>C: confirmation page
Note over Q,C: Later: worker sends reminder emails/SMS
See Booking flow for contract chain detail.
Capabilities
Section titled “Capabilities”| Feature | How |
|---|---|
| Browse services | Public GraphQL (Vendure) + public scheduler surface |
| Book appointment | POST /api/public/:slug/book |
| View bookings | GET /api/public/:slug/bookings + stoken |
| Reschedule / cancel | PATCH /api/public/:slug/bookings/:id |
| Receive reminders | Email/SMS via BullMQ scheduler-worker → Resend |
| Real-time updates | SSE stream (stoken-authenticated) |
Contract drift protection
Section titled “Contract drift protection”The public booking API is contract-first. If the client and server schemas
diverge, the server returns a 500 (drift) immediately — not a silent
type mismatch. The drift threshold is defined in @nexus/scheduler-contracts.
This means: if a customer-facing site sends a request that no longer matches the server’s Zod schema, the booking fails loudly rather than silently corrupting data. Update the contracts and regenerate the SDK to resolve.