Skip to content

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.

Customers do not have WorkOS accounts. Authentication is session-based:

  1. Customer provides their email (or phone) on the booking site.
  2. scheduler-api issues a stoken — a scoped bearer token tied to the customer record.
  3. The stoken is sent in the Authorization: Bearer <stoken> header on subsequent requests.
  4. SSE streams (notifications, booking status) send the stoken as a query parameter (?stoken=…). This is required because the browser EventSource API 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.

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-sdkscheduler-api.

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.

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)

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.