Skip to main content

Error shape

All error responses are JSON with Content-Type: application/json:
{ "error": "brief_not_found" }
Some endpoints include additional fields:
{
  "error": "invalid_request",
  "error_description": "iso2 must be a 2-letter uppercase country code",
  "field": "iso2"
}
OAuth endpoints follow RFC 6749 §5.2 error codes: invalid_request, invalid_client, invalid_grant, unsupported_grant_type, invalid_scope.

Status codes

CodeMeaningRetry?
200OK
202Accepted — job enqueued (e.g. scenario/v1/run). Poll statusUrl.
304Not Modified (conditional cache hit)
400Bad request — validation errorNo — fix input
401Missing / invalid authNo — fix auth
403Authenticated but not entitled (usually pro_required)No — upgrade
404Resource / tool / brief / entity not foundNo
405Method not allowedNo
409Conflict (duplicate webhook registration, etc.)No
413Payload too largeNo
429Rate limitedYes — honor Retry-After
500Server bugYes — with backoff, then report
502Upstream / Convex / Dodo failureYes — exponential backoff
503Service unavailable — missing env or dependency downYes — exponential backoff
504Upstream timeoutYes — with backoff

Common error strings

error valueMeaning
UNAUTHENTICATEDNo valid Clerk JWT or API key.
pro_requiredAuthenticated, but account is not PRO.
invalid_payloadBody failed schema validation.
invalid_date_shapeDate param not YYYY-MM-DD.
brief_not_foundNo composed brief for the requested {userId, issueDate}.
Rate limit exceeded429 fired; honor Retry-After.
Service temporarily unavailableUpstash or another hard dependency missing at request time.
service_unavailableSigning secret / required env not configured.
Failed to enqueue scenario jobRedis pipeline failure on /api/scenario/v1/run.

Retry strategy

Idempotent reads (GET): retry 429/5xx with exponential backoff (1s, 2s, 4s, cap 30s, 5 attempts). Most GET responses are cached at the edge, so the retry usually goes faster. Writes: never auto-retry 4xx. For 5xx on writes, inspect: POST /api/brief/share-url and POST /api/v2/shipping/webhooks are idempotent; POST /api/scenario/v1/run is not — it enqueues a new job on each call. Retrying a 5xx on run may double-charge the rate-limit counter. MCP: the server returns tool errors in the JSON-RPC result with isError: true and a text explanation — those are not HTTP errors. Handle them at the tool-call layer.

Debugging

  • Every edge response includes x-vercel-id and x-worldmonitor-deploy headers — include those when reporting issues.
  • Sentry alerts forward to status.worldmonitor.app.
  • GET /api/health and GET /api/seed-health show per-seed freshness; a stale seed is the most common root cause of unexpected empty payloads.