Specified error model
The platform’s normative error specification (docs/api/03-error-model.md) defines every error response as:
code as a stable, machine-readable identifier and message as a human-readable description, and a fixed set of canonical codes grouped by category:
| Category | Codes |
|---|---|
| Validation | INVALID_REQUEST, INVALID_METADATA, INVALID_POLICY, INVALID_SIGNALS, INVALID_SCHEMA |
| Authentication | UNAUTHENTICATED, INVALID_TOKEN, TOKEN_EXPIRED |
| Authorization | FORBIDDEN, INSUFFICIENT_PERMISSIONS |
| Resource | BUSINESS_TRANSACTION_NOT_FOUND, EXECUTION_NOT_FOUND, RECEIPT_NOT_FOUND, POLICY_NOT_FOUND, VERIFICATION_NOT_FOUND |
| Conflict | DUPLICATE_TRANSACTION, OVERRIDE_NOT_ALLOWED, IMMUTABLE_RESOURCE |
| Verification | VERIFICATION_FAILED, INVALID_SIGNATURE, TRUST_RECORD_CORRUPTED, POLICY_MISMATCH |
| Internal | INTERNAL_ERROR, STORAGE_FAILURE, UNEXPECTED_ERROR |
| HTTP Status | Category | Example |
|---|---|---|
| 400 | Validation | INVALID_REQUEST |
| 401 | Authentication | UNAUTHENTICATED |
| 403 | Authorization | FORBIDDEN |
| 404 | Resource | POLICY_NOT_FOUND |
| 409 | Conflict | DUPLICATE_TRANSACTION |
| 422 | Verification / Validation | VERIFICATION_FAILED |
| 500 | Internal | INTERNAL_ERROR |
What the implementation actually returns today
Practical status mapping (as implemented)
| Route | Failure condition | Status | Body shape |
|---|---|---|---|
POST /execute | Invalid or missing businessTransactionId | 400 | { "error": string } |
POST /policies/validate | Missing policyId / policyVersion | 400 | { "valid": false, "errors": string[] } |
POST /policies/validate | Policy not found | 404 | { "valid": false, "errors": string[] } |
GET /transactions/:id | Not found | 404 | { "error": string } |
GET /trust-records/:id | Not found | 404 | { "error": string } |
GET /verify/:id, GET /receipt/:id | Trust record or sub-resource not found | 404 | { "error": string } |
| Anything else | RuntimeError subclass | error.status | { "error": string, "code": string } |
| Anything else | Unhandled exception | 500 | { "error": "Internal Server Error" } |
Recommendation for integrators
Match on theerror string’s presence and HTTP status code rather than a code field, until the error handler is updated to conform to the specified nested model. If you need stable machine-readable codes today, they’re only reliably present for errors that subclass RuntimeError.