Almost every route runs through a security wrapper (apiSecurity.* / withSecurity()) that enforces a rate limit, method/content-type validation, and a body-size cap. Tiers: public() 30/min no-auth · authenticated() 30/min · admin() 5/min + is_admin · ai() 10/min · webhook() 100/min + signature. State-changing requests (POST/PATCH/PUT/DELETE) additionally require CSRF (Origin/Referer + token). Errors return a typed envelope — { "error": "message", "code": "ERROR_CODE" } — with codes from core/*/error-codes.ts (never raw internals). Feature-gated domains (referrals, affiliates, error logs) return 404 when disabled, not 403.

Exceptions to the wrapper

Two endpoints intentionally bypass apiSecurity.*: /api/ai/stream uses raw POST + manual rateLimiters.ai(user.id:ip) + validateOrigin() so it can stream Server-Sent Events; /api/health is a public GET with no rate limit so a load balancer can probe it cheaply.

Authentication

Endpoint Method Description
/api/auth/magic-link POST Send magic-link email (link + 6-digit OTP code)
/api/auth/verify-otp POST Verify the 6-digit code from the magic-link email (alternate path to clicking the link)
/api/auth/me GET Return minimal sanitized auth/profile/workspace context for marketing-shell client hydration. Read-only, relaxed rate limit, Cache-Control: private, no-store.
/api/auth/logout POST Sign out user (logs activity)
/[locale]/callback GET OAuth/Magic link callback

Billing

Endpoint Method Description
/api/billing/checkout POST Create Stripe checkout
/api/billing/portal POST Stripe Customer Portal
/api/billing/license-checkout POST Create license one-shot checkout
/api/billing/subscribe-free POST Create free subscription (owner-only, all modes)
/api/billing/end-trial POST End a trialing subscription early and unlock full plan credits
/api/billing/current-plan GET Resolve the active plan for the current account (subscription preferred over license in hybrid mode)
/api/stripe/webhook POST Stripe webhook handler

AI

Endpoint Method Description
/api/ai/stream POST Streaming AI response (SSE)
/api/ai/config GET AI configuration

Chat

Endpoint Method Description
/api/chat/sessions GET List sessions
/api/chat/sessions POST Create session
/api/chat/sessions/[id] GET Get session with messages
/api/chat/sessions/[id] PATCH Update session
/api/chat/sessions/[id] DELETE Delete session

User

Endpoint Method Description
/api/user/export-data GET GDPR data export (multi-section CSV)
/api/user/sessions GET List recent login sessions
/api/user/sessions DELETE Revoke all other sessions
/api/user/log-activity POST Log user activity event
/api/user/onboarding POST Validate and store onboarding profile fields server-side

Invitations

Endpoint Method Description
/api/invitations/accept POST Accept workspace invitation
/api/invitations/resend POST Resend invitation email (owner/admin)
/api/invitations/revoke POST Revoke a pending workspace invitation (owner/admin)

Organization

Endpoint Method Description
/api/org/schedule-deletion POST Schedule org deletion (30-day grace)
/api/org/cancel-deletion POST Cancel pending org deletion
/api/org/settings PATCH Update workspace name/slug through a validated server boundary

CMS (Admin)

Endpoint Method Description
/api/admin/cms/pages GET List all CMS pages
/api/admin/cms/pages POST Create page
/api/admin/cms/pages PATCH Update page
/api/admin/cms/pages?id=xxx DELETE Delete page
/api/admin/cms/blocks GET List all blocks
/api/admin/cms/blocks POST Create block
/api/admin/cms/blocks PATCH Update block
/api/admin/cms/blocks?id=xxx DELETE Delete block (query param is id, the block's UUID)
/api/admin/cms/media GET List media files
/api/admin/cms/media POST Upload file
/api/admin/cms/media PATCH Rename file
/api/admin/cms/media?path=xxx DELETE Delete file
/api/admin/cms/categories GET List all blog categories (with usage counts)
/api/admin/cms/categories POST Create category
/api/admin/cms/categories/[id] PATCH Update category
/api/admin/cms/categories/[id] DELETE Delete category
/api/admin/cms/tags GET List all blog tags (with usage counts)
/api/admin/cms/tags POST Create tag
/api/admin/cms/tags/[id] PATCH Update tag
/api/admin/cms/tags/[id] DELETE Delete tag

Jobs

Endpoint Method Description
/api/jobs/run POST Execute a job (cron/manual/api). Dual auth: Authorization: Bearer JOBS_SECRET_KEY (constant-time compared, webhook rate limit) OR an admin user session with Origin/CSRF validation and strict rate limiting.
/api/admin/jobs GET List all jobs
/api/admin/jobs POST Create job
/api/admin/jobs/[jobId] PATCH Update job
/api/admin/jobs/[jobId] DELETE Delete job
/api/admin/jobs/handlers GET List all handlers (code + webhook)
/api/admin/jobs/handlers POST Create webhook handler
/api/admin/jobs/handlers/[handlerId] GET Read a single webhook handler
/api/admin/jobs/handlers/[handlerId] PATCH Update webhook handler
/api/admin/jobs/handlers/[handlerId] DELETE Delete webhook handler

Notifications

Endpoint Method Description
/api/notifications GET Fetch latest 50 notifications
/api/notifications PATCH Mark notifications as read

API Keys

Endpoint Method Description
/api/account/api-keys GET List API keys
/api/account/api-keys POST Create API key
/api/account/api-keys DELETE Revoke API key

Knowledge Base / Documents (RAG)

Endpoint Method Description
/api/documents GET List documents
/api/documents POST Upload document (multipart). Triggers async processing with credit deduction.
/api/documents DELETE Delete document + chunks + storage
/api/documents/[id] GET Document details + chunks

Changelog (Admin)

Endpoint Method Description
/api/admin/changelog GET List changelog entries
/api/admin/changelog POST Create changelog entry
/api/admin/changelog PATCH Update changelog entry
/api/admin/changelog DELETE Delete changelog entry

Referrals

Account-centric referral program. Every endpoint returns 404 when REFERRAL_ENABLED is off (surface invisibility).

EndpointMethodSecurityDescription
/api/referral/codeGETauthenticated · standardLazy-create the account's active referral code
/api/referral/statsGETauthenticated · standardDashboard counters
/api/referral/listGETauthenticated · standardCursor-paginated referrals
/api/referral/applyPOSTauthenticated + CSRF · strictManually apply a referral code
/api/referral/attributePOSTauthenticated + CSRF · strictCookie-based attribution (called from onboarding)
/[locale]/refer/[code]GETpublic · relaxedTracking redirect — sets the bsk_ref cookie
/api/admin/referralsGETadmin · strictFilterable list
/api/admin/referrals/statsGETadmin · strictAggregate KPIs
/api/admin/referrals/[id]GETadmin · strictDetail + audit trail
/api/admin/referrals/[id]/reversePOSTadmin + CSRF · strictClawback granted credits
/api/admin/referrals/[id]/rejectPOSTadmin + CSRF · strictReject a pending referral
/api/admin/referral-codesGETadmin · strictCodes + usage counts
/api/admin/referral-codes/[id]/deactivatePOSTadmin + CSRF · strictDeactivate a code

Affiliates

Cash-commission partner program (distinct from referrals). Every endpoint returns 404 when AFFILIATES_ENABLED is off.

EndpointMethodSecurityDescription
/api/affiliates/applyPOSTauthenticated + CSRF · strictSubmit affiliate application (Zod-validated pitch + URL)
/api/affiliates/attributePOSTauthenticated + CSRF · strictCookie-driven attribution (non-blocking)
/[locale]/affiliate/[code]GETpublic · relaxedTracking redirect — sets bsk_aff cookie + records click
/api/admin/affiliates/applications/[id]/approvePOSTadmin + CSRF · strictApprove at a tier (defaults to config defaultTierSlug)
/api/admin/affiliates/applications/[id]/rejectPOSTadmin + CSRF · strictReject with sanitized reason
/api/admin/affiliates/conversions/[id]/reversePOSTadmin + CSRF · strictManual conversion clawback (fraud / dispute)

Push Notifications

EndpointMethodSecurityDescription
/api/push/subscribePOSTauthenticatedRegister a push subscription (with device name)
/api/push/unsubscribePOSTauthenticatedRemove a push subscription
/api/push/vapid-keyGETpublicFetch the VAPID public key (browser subscription)
/api/push/preferencesGETauthenticatedGet notification preferences
/api/push/preferencesPATCHauthenticatedUpdate preferences / quiet hours
/api/push/trackPOSTauthenticatedTrack interaction (click / dismiss / view)

Error Logs (Admin)

EndpointMethodSecurityDescription
/api/admin/logsGETadmin · 5/minCursor-paginated error logs (Zod-validated filters). 404 when LOGS_ENABLED is off. Read-only — no write endpoints.

Public & Misc

EndpointMethodSecurityDescription
/api/contactPOSTpublic + Turnstile · contact (3/min)Contact form (queues on provider failure)
/api/newsletter/subscribePOSTpublic + Turnstile · standardNewsletter signup
/api/newsletter/unsubscribePOSTauthenticated + CSRF · strictUnsubscribe the current authenticated user from the newsletter. Public email links need a separate signed-token route.
/api/localePOSTpublicPersist locale preference cookie
/api/healthGETnoneHealth check (use for uptime monitoring / load-balancer probes)

Admin & Platform

Super-admin surface — all admin-gated (5/min, is_admin) with CSRF on state-changing calls. Sensitive actions that change access, billing, credits, retention, or destructive state also require recent auth and write immutable audit rows.

EndpointMethodSecurityDescription
/api/admin/usersPOST PATCH DELETEadminCreate / update (admin toggle, edit) / delete users
/api/admin/organizationsGET POST PATCH DELETEadmin + CSRF + recent-auth for writesWorkspace account CRUD — list, create, update, delete
/api/admin/subscriptionsGET PATCHadmin + CSRF + recent-auth for mutationsSubscription overview + admin updates (status, plan, credit grant)
/api/admin/licensesGET PATCHadmin + CSRFLicense list + admin revoke / extend (delegates to core/licenses/mutations.ts)
/api/admin/roles · /api/admin/roles/[roleId]GET POST PATCH DELETEadmin + CSRFDynamic role CRUD (is_system protected)
/api/admin/settingsGET PATCHadmin + CSRF + recent-auth for sensitive changesPlatform settings (app_settings) and log purges
/api/admin/jobs/stats · /api/admin/jobs/[jobId]/runsGETadminJob execution stats / run history
/api/admin/cron/[jobid]/togglePOSTadmin + CSRFEnable/disable a single pg_cron job
/api/admin/cron/[jobid]/unschedulePOSTadmin + CSRFUnschedule a single pg_cron job
/api/admin/cron/purge-orphansPOSTadmin + CSRFPurge orphaned pg_cron entries that no longer match any jobs row

Non-admin routes previously grouped here have moved to their correct sections: /api/billing/current-planBilling · /api/localePublic & Misc · /api/org/cancel-deletionOrganizations.