Error handling¶
This page describes the shared HTTP error model used by Open Delivery V2 API Specs.
Normative source: error responses and schemas in each API Spec. This summary guides implementers; on conflict, API Spec wins.
Principles¶
- Error responses are machine-readable (stable
code). - Classification preserves meaning for automation (retry, UX, audit).
- Producers do not emit business success when processing failed.
- Cancellation and state-transition failures are distinguishable by code.
Error envelope (common shape)¶
| field | type | required | description |
|---|---|---|---|
error.code |
string | YES | Stable machine-readable code |
error.message |
string | YES | Human-readable message |
error.details |
object | NO | Additional structured context |
error.retryable |
boolean | NO | Whether retry is safe |
error.timestamp |
string | NO | ISO 8601 instant |
Example¶
{
"error": {
"code": "ORDER_NOT_FOUND",
"message": "Unknown order identifier for this merchant scope",
"retryable": false
}
}
HTTP status codes (typical use)¶
| status | when |
|---|---|
400 Bad Request |
Malformed payload or invalid parameters |
401 Unauthorized |
Missing or invalid credentials |
403 Forbidden |
Valid credentials, insufficient scope |
404 Not Found |
Resource not found |
409 Conflict |
State or version conflict |
422 Unprocessable Entity |
Invalid transition or business rule |
429 Too Many Requests |
Rate limit |
500 Internal Server Error |
Unexpected internal failure |
202 Accepted |
Accepted for async processing (not an error) |
Many ODP V2 mutations are async-first (202). Confirm outcomes via events or GET, per capability.
Retries¶
When error.retryable is true, the client may retry after a delay.
Recommendation: exponential backoff with jitter (e.g. 1s → 2s → 4s; about 3 attempts max).
- On async mutations (
202), repeating an already applied operation (e.g. a secondconfirmwhile the order is alreadyCONFIRMED) is not an error — see duplicate lifecycle operations. - Do not confuse that with an invalid transition (incompatible state), which does return
4xx.
State transition errors¶
Return an error only when the transition is impossible in the current state (e.g. confirm an order that is already CANCELLED). An order already in the operation’s target state is not an error — return 202 (see conventions).
Example of an invalid transition:
{
"error": {
"code": "INVALID_STATE_TRANSITION",
"message": "Cannot confirm an order in CANCELLED status",
"retryable": false,
"details": {
"currentStatus": "CANCELLED",
"attemptedTransition": "confirm"
}
}
}
Exact codes and HTTP status: capability API Spec.