Errors
The AnySpend Platform API uses a consistent, structured error format across all endpoints. Errors follow the Stripe convention — a JSON object with anerror key containing the type, code, human-readable message, and (where applicable) the parameter that caused the error.
Error response format
Every error response has this shape:| Field | Type | Description |
|---|---|---|
type | string | The category of error. Use this for broad error handling logic. |
code | string | A machine-readable error code. Use this for specific error handling. |
message | string | A human-readable description of what went wrong. Safe to display to developers (but not end users). |
param | string or absent | The request parameter that caused the error, if applicable. |
Error types
Error types group errors into broad categories. Use these for top-level error handling.| Type | HTTP status | Description |
|---|---|---|
invalid_request_error | 400 | The request was malformed or contained invalid parameters. Check the param field for which field caused the issue. |
authentication_error | 401 | The API key is missing, invalid, expired, or revoked. |
permission_error | 403 | The API key is valid but lacks the required permission level for the requested operation. |
not_found_error | 404 | The requested resource does not exist, or does not belong to your organization. |
rate_limit_error | 429 | You have exceeded the rate limit for your authentication tier. |
idempotency_error | 409 | An idempotency key was reused with a different request body. |
api_error | 500 | An unexpected internal error occurred on our side. These are rare and are automatically reported. |
Error codes
Error codes provide specific, machine-readable identifiers for each error condition.Request validation errors
| Code | Type | HTTP | Description |
|---|---|---|---|
missing_required_field | invalid_request_error | 400 | A required field was not included in the request body. The param field indicates which field is missing. |
invalid_field_value | invalid_request_error | 400 | A field was included but its value is invalid (wrong type, format, or out of range). |
invalid_address | invalid_request_error | 400 | An Ethereum address field is not a valid 0x + 40 hex character address. |
no_updates_provided | invalid_request_error | 400 | A PATCH request was sent with no valid fields to update. |
invalid_status_transition | invalid_request_error | 400 | The requested status change is not allowed (e.g., completing an already-expired session). |
duplicate_resource | invalid_request_error | 409 | A resource with a conflicting unique field already exists. |
Authentication and authorization errors
| Code | Type | HTTP | Description |
|---|---|---|---|
key_missing | authentication_error | 401 | No API key was found in the Authorization or X-API-Key header. |
key_invalid | authentication_error | 401 | The provided API key does not match any key in the system. |
key_expired | authentication_error | 401 | The API key has passed its expires_at timestamp. Create a new key or extend the expiration. |
key_revoked | authentication_error | 401 | The API key was explicitly revoked. Create a new key. |
insufficient_permissions | permission_error | 403 | The API key does not have the permission level required for this operation (e.g., a read key attempting a POST). |
Resource errors
| Code | Type | HTTP | Description |
|---|---|---|---|
resource_not_found | not_found_error | 404 | The requested resource does not exist, or it belongs to a different organization. |
Rate limiting and idempotency errors
| Code | Type | HTTP | Description |
|---|---|---|---|
rate_limit_exceeded | rate_limit_error | 429 | Too many requests in the current time window. The error message includes the retry delay. |
idempotency_conflict | idempotency_error | 409 | An Idempotency-Key header was reused with a different request body than the original request. |
Server errors
| Code | Type | HTTP | Description |
|---|---|---|---|
internal_error | api_error | 500 | An unexpected server error. These are automatically tracked. If this persists, contact support. |
HTTP status codes
| Status | Meaning |
|---|---|
200 | Success — the resource was retrieved or updated |
201 | Created — a new resource was successfully created |
400 | Bad Request — the request was invalid |
401 | Unauthorized — authentication failed |
403 | Forbidden — the API key lacks the required permission |
404 | Not Found — the resource does not exist |
409 | Conflict — idempotency conflict or duplicate resource |
429 | Too Many Requests — rate limit exceeded |
500 | Internal Server Error — something went wrong on our end |
Example error responses
Missing required field
Invalid Ethereum address
Authentication failure
Insufficient permissions
Resource not found
Rate limit exceeded
Idempotency conflict
Handling errors in code
TypeScript / JavaScript
Python
Best practices
Always check the error type first
Always check the error type first
Use
error.type for broad control flow (e.g., retry on rate_limit_error, fail fast on authentication_error). Use error.code for specific handling within a type.Use the param field to build form validation
Use the param field to build form validation
When
error.param is present, you can map it directly to a form field to show inline validation errors in your UI.Implement retry logic for transient errors
Implement retry logic for transient errors
rate_limit_error and api_error (500) are transient. Use exponential backoff when retrying:Never retry 4xx errors (except 429)
Never retry 4xx errors (except 429)
Client errors like
400, 401, 403, and 404 will not resolve on retry. Fix the request or credentials before retrying.Log the full error object for debugging
Log the full error object for debugging
Always log
error.type, error.code, error.message, and error.param together. This gives you the full picture when debugging production issues.
HypeDuel