Errors and Rate Limits
The Oris API uses standard HTTP status codes and returns structured error responses. The SDKs map these to typed exception classes for language-idiomatic error handling.
Error Response Format
Every error response follows a consistent JSON structure. The code field is a machine-readable identifier. The message field is a human-readable description. The details field provides additional context when available.
Error Codes
| HTTP | Code | Description |
|---|---|---|
| 400 | BAD_REQUEST | Malformed request body or missing required fields |
| 401 | UNAUTHORIZED | Invalid API key, HMAC signature, timestamp, or nonce |
| 402 | WALLET_INSUFFICIENT_BALANCE | Wallet balance too low for this transaction |
| 403 | FORBIDDEN | Developer KYB not verified or insufficient permissions |
| 403 | POLICY_VIOLATED | Payment rejected by one or more spending policies |
| 403 | PAYMENT_COMPLIANCE_BLOCKED | Payment blocked by Veris compliance pre-screen |
| 403 | PAYMENT_REJECTED | Payment rejected during processing |
| 404 | RESOURCE_NOT_FOUND | Requested agent, wallet, payment, or policy does not exist |
| 404 | WALLET_NOT_FOUND | No wallet found for the specified agent and chain |
| 409 | WALLET_FROZEN | Wallet is frozen pending compliance review |
| 422 | VALIDATION_ERROR | Request body fails schema validation |
| 429 | RATE_LIMITED | Too many requests. Respect the Retry-After header. |
| 202 | PAYMENT_ESCALATED | Payment requires human approval per escalation policy |
| 502 | UPSTREAM_ERROR | Blockchain RPC or external service failure |
| 503 | SERVICE_UNAVAILABLE | Service temporarily unavailable |
| 504 | GATEWAY_TIMEOUT | Upstream request timed out |
SDK Error Hierarchy
Both the Python and TypeScript SDKs map HTTP errors to a typed exception hierarchy. This lets you catch specific error categories without inspecting status codes.
Every error instance exposes these properties:
| Property | Type | Description |
|---|---|---|
message | string | Human-readable error description |
statusCode | number | HTTP status code |
errorCode | string | Machine-readable error code (e.g., POLICY_VIOLATED) |
requestId | string | Unique request identifier for support debugging |
details | object | Additional context (violated rules, amounts, etc.) |
TypeScript Error Handling
Python Error Handling
Rate Limits
Rate limits are enforced per developer using a Lua token bucket in Redis. The limit applies per second, derived from the per-minute allocation for your plan.
| Plan | Requests/min | Agents | Transactions/mo |
|---|---|---|---|
| Free | 60 | 3 | 500 |
| Growth | 300 | 25 | 10,000 |
| Scale | 1,000 | 200 | 100,000 |
| Enterprise | Custom | Unlimited | Unlimited |
Rate Limit Headers
Every response includes rate limit information in the headers.
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per window |
X-RateLimit-Remaining | Remaining requests in the current window |
X-RateLimit-Reset | Seconds until the window resets |
Retry-After | Seconds to wait before retrying (only on 429 responses) |
Retry Strategy
The SDKs implement automatic retries with exponential backoff and jitter for retryable errors (429, 502, 503, 504). The default configuration retries up to 3 times with a maximum backoff of 30 seconds.
| Parameter | Default | Description |
|---|---|---|
| Max retries | 3 | Maximum number of retry attempts |
| Base delay | 500ms | Initial backoff delay |
| Max backoff | 30,000ms | Maximum delay between retries |
| Jitter | 0-500ms | Random jitter added to each delay |
| 429 handling | Respect Retry-After | Uses the server-provided delay for rate limit errors |
Non-Retryable Errors
The following status codes are never retried because they indicate a problem with the request itself:
| Status | Reason |
|---|---|
| 400 | Request is malformed. Fix the payload before retrying. |
| 401 | Authentication failed. Check credentials. |
| 403 | Permission denied or policy violation. Will not change on retry. |
| 404 | Resource does not exist. |
| 409 | Conflict state (e.g., wallet frozen). Resolve the conflict first. |
| 422 | Validation error. Fix the request body. |
Idempotency-Key header. If a retry sends the same key, the server returns the original response instead of executing the operation again. This prevents duplicate payments on network failures.