Stripe and Paid Bookings
This page is the developer-side companion to the organisation billing and paid booking user guides. Use it when you need to trace the billing stack, run the local payment loop, or update docs and screenshots safely.
Core Backend Modules
Organisation billing and public-booking payment code lives here:
backend-nestjs/src/organisations/organisation-stripe-connect.service.tsbackend-nestjs/src/organisations/stripe-connect.gateway.tsbackend-nestjs/src/payments/public-booking-payment.service.tsbackend-nestjs/src/payments/stripe-payments.gateway.tsbackend-nestjs/src/payments/stripe-webhook.service.tsbackend-nestjs/src/resources/public-booking.service.ts
Useful frontend surfaces:
frontend/src/components/reservation/OrganisationBillingSettingsPanel.tsxfrontend/src/components/ReservationsPanel.tsxfrontend/src/components/public-booking/PublicBookingExperience.tsxfrontend/src/services/organisationBillingApi.ts
Booking State Machine
Free booking
draft request -> confirmed reservation
Payment-required booking
draft request -> pending_payment reservation -> Stripe Checkout -> webhook success -> confirmed reservation
Key points:
- the reservation is created before Stripe succeeds
- the reservation is not fully confirmed until the webhook updates it
- the browser redirect is helpful UX, but not the payment source of truth
Local Environment
Use test credentials only in development.
Minimum environment:
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
FRONTEND_URL=http://127.0.0.1:4173
BACKEND_URL=http://127.0.0.1:8081
STRIPE_CONNECT_RETURN_PATH=/settings/billing/stripe
STRIPE_CONNECT_REFRESH_PATH=/settings/billing/stripe/refresh
PrimeCal also uses the configured public booking return paths when it builds Stripe Checkout return URLs.
Local Webhook Loop
Typical workflow:
- start backend
- start frontend
- seed docs-safe reservation data if needed
- connect the organisation in Stripe test mode
- create a payment-required public booking
- forward Stripe webhooks to
POST /api/payments/stripe/webhook - confirm the reservation moves from
pending_paymenttoconfirmed
Keep webhook signatures enabled. Do not short-circuit signature verification in normal local development.
API Surfaces To Watch
- organisation billing:
PATCH /api/organisations/:id/billingGET /api/organisations/:id/stripe/statusPOST /api/organisations/:id/stripe/onboarding-linkPOST /api/organisations/:id/stripe/dashboard-linkPOST /api/organisations/:id/stripe/disconnect
- public booking:
POST /api/public/booking/organisations/:slug/reserveGET /api/public/booking/organisations/:slug/checkout-statusPOST /api/payments/stripe/webhook
Screenshot Automation
For docs work, use the enterprise reservation screenshot runbook plus the local Playwright docs captures:
E2E_DOCS_SCREENSHOTS=true npm run test:e2e:web -- --grep "Docs screenshots"
This automation is meant for docs-safe states only:
- disconnected billing
- connected billing
- paid booking configuration
- public payment step before Stripe Checkout
When Playwright capture is not enough, finish the sequence with the Browser MCP manual workflow documented in the MCP section.
Safety Notes
- Never commit live Stripe keys.
- Never log webhook secrets, full Checkout URLs with sensitive query state, or raw customer payment data.
- Keep documentation screenshots free of real emails, phone numbers, and customer names.