Contract version and migration

Exact authentication, origin, status, and compatibility changes for first-party callers.

Independent version

The public contract is 2.0.0 for the current local deployment candidate. It is independent from package versions, commit SHAs, Railway deployment ids, and the values returned by /version or /api/version.

  • 1.0.0 was the breaking authentication cutover from Supabase sessions to Better Auth.
  • 1.1.0 adds the concrete first-party domain operations without removing the five legacy paths.
  • 1.4.0 adds published pass forms and aggregate form analytics, organiser event discovery, schedules, exhibition checkpoints and assignment replacement, and account push-subscription endpoints.
  • 2.0.0 removes the merchant storefront, stall, and customer-order contract. Paid ticket checkout, provider callbacks, refunds, and historical financial records remain supported. MATRADE exhibitor reporting retains its legacy backing data without restoring merchant operations.

Caller migration

  1. Discard old Supabase sb-…-auth-token cookies and sign in again through the first-party same-host Better Auth proxy under /api/auth. Browser clients must not switch authentication calls to a separate API hostname; same-host transport keeps host-only local and isolated-preview cookies usable.
  2. Browser calls send credentials so the current surface cookie is included.
  3. Server-side first-party domain callers forward the incoming Cookie, set Origin to their exact configured frontend origin, and set x-xperience-origin to the same value.
  4. Never construct a session cookie name. HTTPS adds __Secure-; the remaining name is vigor-<encoded project>-<encoded API host>.session_token, where each configured value uses a byte-length-prefixed lossless encoding. HTTP omits __Secure-.
  5. Treat 401 as missing/expired identity and 403 as an untrusted mutation origin or insufficient live organiser, platform, or scanner scope.
  6. Do not require every successful mutation to return 200: direct Nest POST operations return 201 by default. The preserved POST /api/scan compatibility operation returns 200; PATCH and DELETE return 200.

The API rejects request bodies over 256 KiB with 413. The single poster import operation, POST /api/discovery/studio/listings/import-poster, has a 12 MiB transport ceiling because its concrete schema carries bounded image bytes. Narrower schema limits still apply: notably /api/scan accepts at most 500 scans per request and the first-party client batches 200.

The API-wide limit is 100 requests per minute per limiter key. Exceeding it returns 429; callers should back off rather than retrying immediately.

Preserved paths

Legacy operationCanonical ownershipMigration
GET /api/scan, POST /api/scan, DELETE /api/scanScanner moduleKeep the path and payload. checkedIn is optional when no scans are processed.
GET /api/me/exportAccount moduleKeep the path and payload; the API itself now sets the attachment and private no-store headers.
GET /api/studio/stats/{id}Partner moduleKeep polling the same three integer fields directly from the API.
GET /api/versionAPI bootstrap compatibility routeKeep treating the string as opaque; use GET /version for structured build metadata.
GET /api/searchAPI proxy to the docs search handlerKeep query and `scope=guides

The new deployment topology and intended hosts are configuration, not evidence that a production cutover has occurred.

Unlimited exhibition registration (1.3.0)

Event capacity and ticket-type quantity accept and return null for unlimited registration. Positive integers retain their existing limits. Handle null explicitly when displaying availability; do not convert it to zero or a sold-out state. Workshop creation continues to require a finite capacity. Availability requires target migration 0006_unlimited_event_capacity.sql and a verified deployment.

Pass forms, schedules, and push (1.4.0 history)

GET /api/events/pass-form returns the published version and bounded questions for a selected public ticket. GET /api/exhibition/pass-configuration and POST /api/exhibition/pass-configuration manage organiser drafts, publication, and zoneIds; GET /api/exhibition/form-analytics returns aggregate answers. PATCH /api/partner/events/details carries optional ordered schedule slots. POST /api/exhibition/checkpoint resolves a checkpoint and POST /api/exhibition/assignments/replace replaces a member's assigned zoneIds.

GET, POST, and DELETE /api/account/push manage the current user's browser subscriptions. Saving requires all three VAPID settings and device permission; notifications are generic alerts and the inbox remains durable. iOS web push requires Home Screen installation. No external provider delivery has been verified for this local candidate.

These additions describe the undeployed local candidate. They do not establish production availability or a completed migration.

Merchant commerce retirement (2.0.0 candidate)

The current candidate removes merchant/stall API routes, navigation, order analytics, and customer stall-order export fields. This is a breaking API change, so callers must stop using the retired merchant and order paths before adopting 2.0.0. Existing paid ticket checkout remains registration-backed: provider callbacks still settle ticket payments, issue tickets, and preserve refund reconciliation. Historical order and payment records must be retained until their financial retention and any pending provider outcomes are closed; they are not evidence that merchant operations remain available.

MATRADE exhibitor rows continue to use the legacy event/exhibitor backing data for country, space, and report calculations. That reporting path is separate from retired vendor storefront and order operations. This is an undeployed local candidate and does not establish production availability.

On this page