Error Handling API
All Cryptid API errors follow a consistent format with standard HTTP status codes, machine-readable error codes, and optional retry guidance. This enables clients to implement robust error handling and recovery strategies.
Error Response Format
Section titled “Error Response Format”{ "error": "ERROR_CODE", "message": "Human readable error description", "code": 4001, "retry_after": 300}Fields:
-
error: Machine-readable error identifier (uppercase snake_case)- Used for string-based matching and logging
- Examples:
RATE_LIMIT_EXCEEDED,INVALID_SIGNATURE - Useful for discriminant matching and human-readable logs
-
message: Human-readable error description- For logging and development debugging only
- Should NOT be displayed directly to end users
- Provides context about what went wrong
-
code: Numeric error code (4-digit integer)- Used for switch/match statements in code
- First digit matches HTTP status (4xxx = client error, 5xxx = server error)
- Enables efficient error handling in strongly-typed languages
-
retry_after(optional): Seconds to wait before retrying- Present only for retryable errors (rate limits, temporary failures)
- Clients SHOULD respect this value to avoid further rate limiting
HTTP Status Codes
Section titled “HTTP Status Codes”| Status | Description | Retryable? |
|---|---|---|
| 200 | OK - Request successful | N/A |
| 202 | Accepted - Message queued | N/A |
| 400 | Bad Request - Invalid format | No |
| 401 | Unauthorized - Invalid token | No* |
| 404 | Not Found - Resource missing | No |
| 413 | Payload Too Large - Message too big | No |
| 429 | Too Many Requests - Rate limited | Yes |
| 500 | Internal Server Error | Yes |
| 502 | Bad Gateway - Federation failed | Yes |
| 503 | Service Unavailable | Yes |
Error Codes
Section titled “Error Codes”| Code | Error | HTTP Status | Description |
|---|---|---|---|
| 4001 | INVALID_SIGNATURE | 400 | Ed25519 signature verification failed |
| 4002 | DEVICE_NOT_ANNOUNCED | 401 | Device not registered for delivery |
| 4003 | MESSAGE_TOO_LARGE | 413 | Message exceeds server size limit |
| 4004 | RATE_LIMIT_EXCEEDED | 429 | Too many requests |
| 4005 | INVALID_ADDRESS | 400 | Malformed device address |
| 4006 | FEDERATION_FAILED | 502 | Cross-server delivery failed |
| 4007 | SERVER_UNREACHABLE | 502/404 | Target server unavailable or not found |
| 4008 | INVALID_REFRESH_TOKEN | 401 | Refresh token is invalid or expired |
| 4009 | INFOPACKAGE_RATE_LIMIT | 429 | InfoPackage upload rate limit exceeded |
| 4010 | INVALID_ADMIN | 401 | Device is not configured as admin |
| 4011 | CHALLENGE_EXPIRED | 410 | Admin auth challenge has expired |
| 4012 | INSUFFICIENT_PERMISSIONS | 403 | Admin lacks required permission |
| 4013 | INVALID_CONFIG | 400 | Configuration value invalid |
| 4014 | DEVICE_NOT_FOUND | 404 | Device not found on server |
| 4015 | INVALID_KEYPACKAGE | 404 | KeyPackage not found on server |
| 5003 | FEDERATION_DISABLED | 503 | Recipient’s server doesn’t support federation |
Error Handling Strategies
Section titled “Error Handling Strategies”Client Errors (4xx)
Section titled “Client Errors (4xx)”Client errors indicate problems with the request that cannot be resolved by retrying without modification.
Examples:
4001 (INVALID_SIGNATURE): Re-sign the request with the correct device key4002 (DEVICE_NOT_ANNOUNCED): Re-announce device before retrying4003 (MESSAGE_TOO_LARGE): Reduce message size or split into chunks4005 (INVALID_ADDRESS): Fix address format4008 (INVALID_REFRESH_TOKEN): Obtain new token via/v1/announce4009 (INFOPACKAGE_RATE_LIMIT): Wait for rate limit window to reset (checkretry_after)
Server Errors (5xx)
Section titled “Server Errors (5xx)”Server errors indicate temporary issues that may be resolved by retrying with exponential backoff.
Examples:
4006 (FEDERATION_FAILED): Retry with backoff, store locally if persistent4007 (SERVER_UNREACHABLE): Retry with backoff, notify user of delay5003 (FEDERATION_DISABLED): Cannot be resolved by retry - inform user
Rate Limiting
Section titled “Rate Limiting”Rate Limit Headers
Section titled “Rate Limit Headers”All responses (success or failure) include rate limiting information:
X-RateLimit-Limit: 60X-RateLimit-Remaining: 45X-RateLimit-Reset: 1759000000Retry-After: 60Headers:
-
X-RateLimit-Limit: Maximum requests allowed in the current window -
X-RateLimit-Remaining: Requests remaining in the current window -
X-RateLimit-Reset: Unix timestamp when the rate limit resets -
Retry-After: Time in seconds after which requests can be retried
Best Practices
Section titled “Best Practices”-
Exponential Backoff: For retryable errors (5xx, 429), use exponential backoff
-
Respect Retry-After: Always respect the
retry_afterfield -
User-Facing Error Messages: Don’t show API error messages directly to users. Show them useful information
-
Logging and Monitoring: Log all errors with context for debugging
-
Graceful Degradation: Handle errors gracefully without blocking user experience.
Important Notes
Section titled “Important Notes”Error Code Stability
Section titled “Error Code Stability”Error codes are stable across API versions. Clients can rely on specific codes for error handling logic.
Adding New Error Codes
Section titled “Adding New Error Codes”Future versions may add new error codes. Clients should handle unknown codes gracefully.
Security
Section titled “Security”Error responses never include stack traces, internal paths, database errors, or sensitive server details. This prevents information leakage while maintaining debuggability through server-side logs.