Error shape
All error responses are JSON withContent-Type: application/json:
invalid_request, invalid_client, invalid_grant, unsupported_grant_type, invalid_scope.
Status codes
| Code | Meaning | Retry? |
|---|---|---|
200 | OK | — |
202 | Accepted — job enqueued (e.g. scenario/v1/run). Poll statusUrl. | — |
304 | Not Modified (conditional cache hit) | — |
400 | Bad request — validation error | No — fix input |
401 | Missing / invalid auth | No — fix auth |
403 | Authenticated but not entitled (usually pro_required) | No — upgrade |
404 | Resource / tool / brief / entity not found | No |
405 | Method not allowed | No |
409 | Conflict (duplicate webhook registration, etc.) | No |
413 | Payload too large | No |
429 | Rate limited | Yes — honor Retry-After |
500 | Server bug | Yes — with backoff, then report |
502 | Upstream / Convex / Dodo failure | Yes — exponential backoff |
503 | Service unavailable — missing env or dependency down | Yes — exponential backoff |
504 | Upstream timeout | Yes — with backoff |
Common error strings
error value | Meaning |
|---|---|
UNAUTHENTICATED | No valid Clerk JWT or API key. |
pro_required | Authenticated, but account is not PRO. |
invalid_payload | Body failed schema validation. |
invalid_date_shape | Date param not YYYY-MM-DD. |
brief_not_found | No composed brief for the requested {userId, issueDate}. |
Rate limit exceeded | 429 fired; honor Retry-After. |
Service temporarily unavailable | Upstash or another hard dependency missing at request time. |
service_unavailable | Signing secret / required env not configured. |
Failed to enqueue scenario job | Redis 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-idandx-worldmonitor-deployheaders — include those when reporting issues. - Sentry alerts forward to status.worldmonitor.app.
GET /api/healthandGET /api/seed-healthshow per-seed freshness; a stale seed is the most common root cause of unexpected empty payloads.
