Skip to main content
The API returns errors in a single shape. Every response with a non-2xx status carries a JSON body with code, message, action, and retryable. Match the code field, not the message string. Messages are written for end users and may change without notice.

Response shape

Some legacy routes return { "error": "string" } only. Treat the HTTP status as authoritative when no code is present.

Retry posture

For 429 rate limit errors, see Rate Limits.

Code catalog

Where each code shows up

Most codes are not endpoint-specific. The list below covers the ones a developer can predict from the call site.
  • AUTH_REQUIRED / FORBIDDEN, every authenticated route returns these. Check before calling anything other than /api/health or /api/score/anonymous.
  • PLAN_LIMIT_REACHED / CREDIT_EXHAUSTED, /api/score, /api/chat, /api/agents/run, /api/teams (POST).
  • FEATURE_GATED, Business-and-up routes: /api/teams, /api/settings/byom, /api/intelligence/portfolio.
  • ONBOARDING_REQUIRED, /api/quarter-close, /api/board-report, /api/briefing.
  • SCORING_* / CRAWL_* / EMPTY_CRAWL, /api/score, /api/score/quick, /api/score/product.
  • INTEGRATION_DISCONNECT, /api/integrations/sync, any /api/integrations/* action route.
  • SIGNAL_*, /api/signal-card/[id], /api/signal-card/[id]/link.
  • TEAM_INVITE_EXPIRED, /api/teams/[id]/accept.
  • READ_ONLY_MODE_ACTIVE, every write route on Free accounts past day 14 with incomplete activation: /api/score, /api/score/product, /api/chat, /api/products (POST), /api/teams (POST). Cleared on rescue (both milestones complete) or on Pro upgrade.

Handling errors in code

Source of truth

The full code list lives in apps/web/src/lib/errors.ts. New codes added to that file ship to this page on the next docs build.