Response envelope
Every action-style response follows a consistent shape. On success:businessRuleWarnings (when a rule warned but allowed the
action) and approvalRequested (when an approval policy intercepted a validation).
Always branch on errorCode, not on the error text — the text is for logs and may
change or be localized; the code is stable.
HTTP status mapping
Errors are categorized, and the category determines the HTTP status (with a few per-code overrides):| Category | HTTP | Examples |
|---|---|---|
| Validation | 400 | VALIDATION_ERROR, MISSING_REQUIRED_FIELD, VARIANT_REQUIRED |
| Auth | 401 | UNAUTHORIZED, FORBIDDEN |
| Not found | 404 | RECORD_NOT_FOUND, PLAN_NOT_FOUND |
| Business | 422 | BUSINESS_RULE_VIOLATION, INSUFFICIENT_STOCK |
| Rate limit | 429 | RATE_LIMIT_EXCEEDED |
| External | 502 | EXTERNAL_SERVICE_ERROR, EXTERNAL_SERVICE_TIMEOUT |
| Database / Config / Unknown | 500 | DATABASE_ERROR, UNKNOWN_ERROR |
PLAN_ALREADY_VALIDATED returns 409 Conflict rather than 422.
Common error codes
| Code | Meaning | What to do |
|---|---|---|
UNAUTHORIZED | Token missing, invalid, revoked, or expired | Re-authenticate / issue a new token |
FORBIDDEN | Token lacks the required permission | Grant the permission on the token; don’t retry as-is |
VALIDATION_ERROR | Input failed validation | Inspect fieldErrors; fix the payload |
RECORD_NOT_FOUND / PLAN_NOT_FOUND | Resource doesn’t exist (or not in your org) | Verify the id; don’t retry |
BUSINESS_RULE_VIOLATION | A business rule blocked the action | Read the message / warnings; adjust the request |
PLAN_ALREADY_VALIDATED | Plan is past the state you’re acting on | Re-fetch the plan’s current status |
RATE_LIMIT_EXCEEDED | Too many requests (if enforced upstream) | Back off and retry |
DATABASE_ERROR / UNKNOWN_ERROR | Unexpected server error | Retry once; escalate if persistent |

