Skip to main content

API overview

Express exposes a JSON API under /v1. Next.js calls it with an access token. The contract is OpenAPI 3.1. The source file in this documentation project is docs/api/openapi.yaml, and the site publishes that same file for download.

Conventions​

TopicRule
Base path/v1
Resource idsUUID strings.
MoneyIntegers in cents plus "currency": "USD".
TimesISO-8601 UTC.
AuthAuthorization: Bearer access token. Refresh tokens are posted only to /auth/refresh.
IdempotencyIdempotency-Key on booking creation and checkout.
Errors{ "error": { "code": "...", "message": "..." } }
Admin routesPrefix /admin. Role ADMIN and, in production, a completed MFA check.

The Stripe success and cancel URLs return the customer to Next.js. Those pages call GET /orders/{orderId} or the reconcile action. They do not post a client-side "payment succeeded" flag that the API trusts.

The webhook route is /v1/webhooks/stripe. It reads the raw body, verifies the Stripe signature, and uses the event id for deduplication. It does not accept an access token as proof of payment.

Response codes​

CodeWhen
200Read or a repeated idempotent request.
201A booking, gallery, or policy was created.
202A refund or thumbnail job was queued.
204Logout or a notification marked read.
400Validation failed, including a bad rating or an untrusted price.
401Missing or expired access token.
403Authenticated, but not allowed. Includes gallery access still pending.
404Missing, or hidden because it belongs to someone else.
409Duplicate referral, duplicate rating, consumed token, or idempotency key reused with a different body.
422The booking is in the wrong status for the decision.
429Rate limit.

Main resources​

AreaOperations
AuthLogin, refresh, logout, current user, account setup, password reset.
CatalogPublic list of active services. Admin create and update.
BookingsCreate, list, read. Admin decision.
OrdersRead. Create a Stripe checkout.
WebhooksStripe.
GalleriesAdmin upload, publish, and access decision. Customer list, signed URL, rating.
RewardsOwn code and balance. Admin reward policy.
NotificationsList and mark read.
AuditAdmin read.

Field names in JSON are camelCase. Database columns are snake_case. The generated Prisma Client maps between them. Every query uses DATABASE_URL.

Versioning​

This document is version 0.1.0 of the contract, matching the USD edition of the design. Additive fields are allowed. Removing a field or changing a cents calculation is a new version and a migration note.