The API
The API is Express 5 under /api. Everything returns JSON except the CSV exports,
the Stripe webhook, /sitemap.xml and /robots.txt. Money is integer cents in
every field, named *Cents.
Authentication
Section titled “Authentication”- Admin: a session cookie set by
POST /api/session, 24 hours,SameSite=Lax,Securein production.GET /api/sessionreturns{ isAdmin, csrfToken, isConfigured }. Every mutation sends the token asx-csrf-token. - Customer: a separate session on
/api/account/session, with the same CSRF rule. A customer session is refused by every admin route. - Storefront password: when visibility is
password, everything below the gate returns 401 untilPOST /api/storefront/unlocksucceeds. The admin’s own session always passes.
The login route answers identically for a known and an unknown email, and hashes a decoy password so the two branches cost the same.
Public
Section titled “Public”| Route | Returns |
|---|---|
GET /api/store |
The whole store snapshot: settings, theme, hero, collections, page summaries, live products. Capped at STORE_SNAPSHOT_LIMIT (200) products. 503 with needsSetup: true before setup; 401 when locked. |
GET /api/collections |
Collections with rendered introductions. |
GET /api/products?collection=&search=&limit=&offset= |
Paginated live products, for catalogues too large for the snapshot. |
GET /api/products/:slug |
One live product. |
GET /api/pages, GET /api/pages/:slug |
Published pages; bodies rendered from Markdown on the server. |
POST /api/shipping/quote |
Rates for a cart and a destination country. |
POST /api/checkout |
Creates a Stripe Checkout Session from { lines: [{ productId, variantId, quantity, options }], shipToCountry }. Returns the redirect URL. |
GET /api/checkout/:sessionId |
Order status for the confirmation page. |
POST /api/cart/sync, /recover, /unsubscribe |
Abandoned-cart machinery. |
POST /api/storefront/unlock |
Storefront password or share-link token. |
POST /api/webhooks/stripe |
Stripe’s inbound webhook. Raw body, signature-verified. |
GET /sitemap.xml, GET /robots.txt |
Live products and collections; empty when locked. |
Account
Section titled “Account”/api/account/register, /verify, /session (POST and DELETE),
/password/forgot, /password/reset, and under /api/account/me: the profile,
/orders, /orders/:id, /addresses with create, update and delete.
Session and setup
Section titled “Session and setup”GET | POST | DELETE /api/session, POST /api/invites/accept,
POST /api/session/forgot-password, POST /api/session/reset-password,
GET | POST /api/setup.
All under /api/admin, all behind the session and CSRF.
| Area | Routes |
|---|---|
| Environment | GET /environment, POST /email/test |
| Products | GET /products, GET /products/full, GET /products/:slug, POST /products, PUT /products/:id, DELETE /products/:id, POST /products/reorder, POST /products/:id/publish |
| Product images | POST /products/:id/images, PUT /products/:id/images (alt and variant), DELETE /products/:id/images, POST /products/:id/images/reorder |
| Catalogue CSV | GET /products.csv, POST /products/import/validate, POST /products/import/commit |
| Collections | GET, POST, PUT /:id, DELETE /:id, POST /:id/cover, POST /reorder |
| Pages | GET, POST, PUT /:id, DELETE /:id, POST /preview, POST /reorder |
| Settings | GET /settings, PUT /settings, POST /settings/logo, POST /settings/hero-image |
| Storefront | `GET |
| Shipping | `GET |
| Orders | GET /orders, GET /orders.csv, GET /orders/:id, PUT /orders/:id, POST /orders/:id/refund |
| Staff | GET /users, POST /users (invite), DELETE /users/:id, DELETE /users/invites/:id, PUT /users/me/password |
| Webhooks | GET, POST, PUT /:id, POST /:id/secret, DELETE /:id, GET /:id/deliveries, POST /deliveries/:id/redeliver |
Every one of these is listed in server/security.test.ts, which is what
guarantees the table above is complete and protected.
Shapes
Section titled “Shapes”Request and response shapes are the zod schemas in shared/schema.ts,
shared/api.ts, shared/orders.ts, shared/shipping.ts and shared/webhooks.ts.
They are the documentation; a shape that is not in shared/ is not part of the
contract.
Scripting it
Section titled “Scripting it”There is no API key. A script signs in with an administrator’s email and password, keeps the cookie, fetches the CSRF token, and sends it on every write. Scripting the admin API is a working example.