/api, deployed once and shared by every site. It exists for two reasons: anything that needs a secret, and anything that must be enforced server-side regardless of what a client sends. Sites reach it through API_URL.
Authentication
Most routes need a member session: a bearer token from the site’s sign-in, verified server-side, then a check that the member can act on theorg_id in the request. Row ownership is never trusted from the client.
Public-by-design routes are hardened instead: campaign link resolution, form submits (token-gated), access requests (honeypot, origin check, cooldowns, per-org caps), the private-site mode lookup, and visit ingest (origin-verified, rate-limited, classification fields never trusted from the body).
Cron routes (scheduled publishing, social publishing, metrics polling) are protected by a shared secret.
Route groups
Publishing
POST /api/build dispatches on the org’s publish_mode:
Both outbound calls are guarded: HTTPS only, no redirects, public-only DNS resolution, a timeout. Errors back to the admin are terse (“No deploy hook”, “Can’t reach hook”). The route returns as soon as the hook accepts and stamps
last_build_at, which the editor uses to decide whether to highlight Publish.
Errors
Routes fail loudly rather than partially. A lookup that cannot complete is a500, not a partial count. A resource in another org answers exactly like a missing one, because existence is tenant data too.