Error Codes
All API errors follow a consistent format and include helpful information for debugging.
Error Response Format
{
"error": "ErrorType",
"message": "Human-readable error description",
"code": "ERROR_CODE",
"details": { ... }
}
HTTP Status Codes
| Status | Description |
|---|---|
| 200 | Success |
| 201 | Created |
| 204 | No Content |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 409 | Conflict |
| 422 | Unprocessable Entity |
| 429 | Too Many Requests |
| 500 | Internal Server Error |
| 503 | Service Unavailable |
Authentication Errors
401 Unauthorized
Missing Authentication:
{
"error": "Unauthorized",
"message": "Authentication required",
"code": "AUTH_REQUIRED"
}
Invalid Token:
{
"error": "Unauthorized",
"message": "Invalid or expired token",
"code": "INVALID_TOKEN"
}
Invalid API Key:
{
"error": "Unauthorized",
"message": "Invalid API key",
"code": "INVALID_API_KEY"
}
Expired Token:
{
"error": "Unauthorized",
"message": "Token has expired",
"code": "TOKEN_EXPIRED"
}
403 Forbidden
Insufficient Permissions:
{
"error": "Forbidden",
"message": "You don't have permission to perform this action",
"code": "INSUFFICIENT_PERMISSIONS",
"details": {
"required": "admin",
"current": "viewer"
}
}
Server Access Denied:
{
"error": "Forbidden",
"message": "You don't have access to this server",
"code": "SERVER_ACCESS_DENIED",
"details": {
"server_id": "550e8400-e29b-41d4-a716-446655440000"
}
}
Feature Not Available:
{
"error": "Forbidden",
"message": "This feature requires a Pro license",
"code": "FEATURE_NOT_AVAILABLE",
"details": {
"feature": "siem",
"required_tier": "pro",
"current_tier": "personal"
}
}
Validation Errors
400 Bad Request
Invalid JSON:
{
"error": "Bad Request",
"message": "Invalid JSON in request body",
"code": "INVALID_JSON"
}
Missing Required Field:
{
"error": "Bad Request",
"message": "Missing required field: ip",
"code": "MISSING_FIELD",
"details": {
"field": "ip"
}
}
422 Unprocessable Entity
Validation Failed:
{
"error": "Validation Error",
"message": "Request validation failed",
"code": "VALIDATION_FAILED",
"details": {
"errors": [
{
"field": "ip",
"message": "Invalid IP address format"
},
{
"field": "maxretry",
"message": "Must be a positive integer"
}
]
}
}
Invalid IP Address:
{
"error": "Validation Error",
"message": "Invalid IP address: 999.999.999.999",
"code": "INVALID_IP",
"details": {
"ip": "999.999.999.999"
}
}
Invalid CIDR:
{
"error": "Validation Error",
"message": "Invalid CIDR notation",
"code": "INVALID_CIDR",
"details": {
"value": "10.0.0.0/99"
}
}
Resource Errors
404 Not Found
Resource Not Found:
{
"error": "Not Found",
"message": "Server not found",
"code": "RESOURCE_NOT_FOUND",
"details": {
"resource": "server",
"id": "550e8400-e29b-41d4-a716-446655440000"
}
}
409 Conflict
Duplicate Entry:
{
"error": "Conflict",
"message": "IP already exists in whitelist",
"code": "DUPLICATE_ENTRY",
"details": {
"ip": "10.0.0.0/8",
"existing_id": 1
}
}
Username Taken:
{
"error": "Conflict",
"message": "Username already taken",
"code": "USERNAME_TAKEN",
"details": {
"username": "admin"
}
}
Rate Limiting
429 Too Many Requests
{
"error": "Too Many Requests",
"message": "Rate limit exceeded",
"code": "RATE_LIMITED",
"details": {
"limit": 100,
"remaining": 0,
"reset_at": "2024-01-15T10:31:00Z",
"retry_after": 60
}
}
Headers included:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705320660
Retry-After: 60
Server Errors
500 Internal Server Error
{
"error": "Internal Server Error",
"message": "An unexpected error occurred",
"code": "INTERNAL_ERROR",
"details": {
"request_id": "req-abc123"
}
}
503 Service Unavailable
{
"error": "Service Unavailable",
"message": "Database connection failed",
"code": "SERVICE_UNAVAILABLE",
"details": {
"retry_after": 30
}
}
License Errors
Server Limit Reached:
{
"error": "Forbidden",
"message": "Server limit reached for your license",
"code": "SERVER_LIMIT_REACHED",
"details": {
"limit": 3,
"current": 3,
"tier": "personal"
}
}
License Expired:
{
"error": "Forbidden",
"message": "Your license has expired",
"code": "LICENSE_EXPIRED",
"details": {
"expired_at": "2024-01-01T00:00:00Z"
}
}
Command Errors
Command Failed:
{
"error": "Command Error",
"message": "Command execution failed",
"code": "COMMAND_FAILED",
"details": {
"command_id": "cmd-abc123",
"exit_code": 1,
"output": "fail2ban-client: error: ..."
}
}
Command Timeout:
{
"error": "Command Error",
"message": "Command timed out",
"code": "COMMAND_TIMEOUT",
"details": {
"command_id": "cmd-abc123",
"timeout_seconds": 60
}
}
Integration Errors
AbuseIPDB Error:
{
"error": "Integration Error",
"message": "AbuseIPDB API error",
"code": "ABUSEIPDB_ERROR",
"details": {
"api_error": "Rate limit exceeded"
}
}
Discord Webhook Error:
{
"error": "Integration Error",
"message": "Failed to send Discord notification",
"code": "DISCORD_ERROR",
"details": {
"http_status": 401,
"message": "Invalid webhook URL"
}
}
Error Code Reference
| Code | Description |
|---|---|
AUTH_REQUIRED | Authentication is required |
INVALID_TOKEN | Token is invalid |
INVALID_API_KEY | API key is invalid |
TOKEN_EXPIRED | Token has expired |
INSUFFICIENT_PERMISSIONS | User lacks required permissions |
SERVER_ACCESS_DENIED | User cannot access this server |
FEATURE_NOT_AVAILABLE | Feature requires higher license tier |
INVALID_JSON | Request body is not valid JSON |
MISSING_FIELD | Required field is missing |
VALIDATION_FAILED | Request validation failed |
INVALID_IP | Invalid IP address format |
INVALID_CIDR | Invalid CIDR notation |
RESOURCE_NOT_FOUND | Requested resource not found |
DUPLICATE_ENTRY | Entry already exists |
USERNAME_TAKEN | Username is already in use |
RATE_LIMITED | Rate limit exceeded |
INTERNAL_ERROR | Internal server error |
SERVICE_UNAVAILABLE | Service temporarily unavailable |
SERVER_LIMIT_REACHED | License server limit reached |
LICENSE_EXPIRED | License has expired |
COMMAND_FAILED | Remote command failed |
COMMAND_TIMEOUT | Command execution timed out |
ABUSEIPDB_ERROR | AbuseIPDB integration error |
DISCORD_ERROR | Discord webhook error |
SMTP_ERROR | Email sending error |
SIEM_ERROR | SIEM integration error |
Handling Errors
Best Practices
- Check HTTP status code first - Determines error category
- Parse error response - Get detailed error information
- Use error codes - For programmatic error handling
- Log request_id - For debugging with support
- Implement retry logic - For transient errors (5xx, 429)
Example Error Handler
async function apiCall(url, options) {
const response = await fetch(url, options);
if (!response.ok) {
const error = await response.json();
switch (error.code) {
case 'AUTH_REQUIRED':
case 'INVALID_TOKEN':
case 'TOKEN_EXPIRED':
// Redirect to login
break;
case 'RATE_LIMITED':
// Wait and retry
const retryAfter = error.details.retry_after;
await sleep(retryAfter * 1000);
return apiCall(url, options);
case 'VALIDATION_FAILED':
// Show validation errors to user
break;
default:
// Log and show generic error
console.error('API Error:', error);
}
throw new Error(error.message);
}
return response.json();
}