Error Handling
Error Handling
Three error shapes depending on which API you call. All are JSON;
always check the HTTP status and success/valid.
1. Panel API — https://<host>:3082/api/v1/*
success + code + error + message + status.
// 401 — bad credentials (verified live: POST /auth/login)
{ "success": false, "code": "UNAUTHORIZED",
"error": "Invalid credentials", "message": "Invalid credentials",
"status": 401 }
// 400 — missing fields (verified live)
{ "success": false, "code": "VALIDATION_ERROR",
"error": "Username and password are required",
"message": "Username and password are required", "status": 400 }
// 403 — verified live: POST /auth/sso/mint for an admin target
{ "success": false, "code": "FORBIDDEN",
"error": "Cannot mint SSO for admin accounts",
"message": "Cannot mint SSO for admin accounts", "status": 403 }
// 401 — no Authorization header (verified live)
{ "success": false, "code": "UNAUTHORIZED",
"error": "Missing authorization", "message": "Missing authorization",
"status": 401 }
2. Portal admin / CMS — https://wispanel.com/api/v1/admin/*
success + error + code (+ details on 422). No message/status.
// 422
{ "success": false, "error": "Validation failed",
"code": "VALIDATION_ERROR",
"details": { "version": ["The version field is required."] } }
// 404
{ "success": false, "error": "Version not found", "code": "NOT_FOUND" }
// 401
{ "success": false, "error": "Invalid or missing API key",
"code": "UNAUTHORIZED" }
3. Portal license / download — https://wispanel.com/api/v1/{license,download}/*
// license endpoints
{ "valid": false, "error": "Invalid request data",
"code": "VALIDATION_ERROR",
"details": { "hardware_id": ["The hardware id field must be 64 characters."] } }
// download/token, download/check-update — bare, no code, HTTP 401
{ "error": "Invalid license" }
HTTP status codes
| Status | Meaning |
|---|---|
| 200 / 201 | OK / created |
| 400 | Bad request / validation (VALIDATION_ERROR) |
| 401 | Missing/invalid auth (UNAUTHORIZED) |
| 403 | Authenticated but not allowed (FORBIDDEN) |
| 404 | Not found (NOT_FOUND) |
| 409 | Conflict — already exists (CONFLICT) |
| 422 | Portal validation (VALIDATION_ERROR + details) |
| 429 | Rate limited |
| 500 | Server error (INTERNAL_ERROR) |
Semantic codes (panel code field)
VALIDATION_ERROR · UNAUTHORIZED · FORBIDDEN · NOT_FOUND ·
CONFLICT · IDEMPOTENCY_KEY_CONFLICT · RATE_LIMITED ·
INTERNAL_ERROR. Portal-license also: INVALID_KEY, EXPIRED,
SUSPENDED, REVOKED, HARDWARE_MISMATCH, MAX_ACTIVATIONS,
UPDATES_EXPIRED, VERSION_TOO_LOW.
Rate limiting
/api/v1/auth/*: X-RateLimit-Limit: 20, X-RateLimit-Window: 60.
On 429: X-RateLimit-Remaining: 0, X-RateLimit-Reset: <unix>,
Retry-After: 60.
Auth & key management → Authentication. Pagination/Idempotency/ webhooks/OpenAPI → Webhooks & Conventions.