Overview
This page hosts the interactive OpenAPI reference for the JSON API under /api/*. Endpoints still require authentication (session cookie,
portal session, API key where supported) and team-scoped authorization as documented per
operation.
The machine-readable spec is served at /openapi.json (redirects to the static build artifact). Use the sidebar links to jump to rate limits or the Swagger UI below.
Most JSON API routes under /api/* are throttled. When a limit is
hit, the server responds with 429 Too Many Requests, a JSON body that
includes retryAfter (seconds), and headers such as Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. Retry after the indicated delay. Counters use
a rolling window (not fixed clock minutes).
How it is counted: most APIs use a per-IP bucket. For
signed-in staff on /api/* outside /api/portal/ and /api/auth/, a second per-user bucket applies (same numeric policies as below). Platform βview
asβ uses the operatorβs user id on /platform and /api/platform/*. Staff session requests to /api/portal/* use the IP bucket only (no per-staff-user bucket
on those routes). Client portal traffic on /api/portal/* is limited by IP in the hook, plus stricter per-portal-user caps on some writes (see below).
API keys: Bearer API key requests use the same route-class IP and per-user buckets as cookie sessions; there is no separate API-key quota tier.
Not throttled by these rules: webhooks and similar callbacks, including /api/twilio/voice/*, /api/twilio/sms/*, /api/stripe/webhook, /api/webhooks/resend, /api/cron/*, and ONLYOFFICE document callback URLs.
Enforcement: when limits are on, counters are stored in Redis if both KV_REST_API_URL and KV_REST_API_TOKEN are set (recommended for production so all
instances share state). If Redis is unavailable or misconfigured, the server falls back to
an in-memory store for that process only. Local vite dev disables throttling unless RATE_LIMIT_ENABLED=true. Setting RATE_LIMIT_ENABLED=false turns limits off everywhere.
Per-route API buckets (IP / authenticated user)
| Area | Per IP | Per user (when logged in) |
|---|---|---|
Default /api/* (except auth) | 500 / minute | 10,000 / hour |
/api/twilio/* (REST, not webhooks) | 1,200 / minute | 12,000 / hour |
POST /api/templates/{id}/generate | 300 / minute | 3,000 / hour |
Document downloads (GET /api/documents/{id}/download, GET /api/documents/temp/β¦), invoice PDF download | 1,500 / minute | 15,000 / hour |
/api/knowledge/* | 2,000 / minute | 20,000 / hour |
POST /api/assistant/chat | 60 / minute | 30 / minute |
Auth and portal (additional caps)
- Auth endpoints (sign-in, forgot password, reset password, portal
equivalents):
20 / 15 minutes / IP (shared
AUTHbucket). - Sign up: 20 / hour / IP.
- Portal magic link: 30 / 15 minutes / IP.
- Failed staff sign-in lockout: after repeated failures, the account can be temporarily locked (5 / 30 minutes, per identifier policy on the sign-in route).
- Portal writes: document uploads β 40 / 15 minutes / portal user; portal messages β 120 / 15 minutes / portal user.
/api/auth/* handlers apply their own IP-based policies (not the global
API hook). Team-switch routes are not throttled.