Overview
All API errors follow a consistent JSON format:
{
"error": {
"code": "LICENSE_EXPIRED",
"message": "Your license has expired. Please renew to continue.",
"details": {}
}
}
License Verification Errors (POST /api/license/verify)
| HTTP | Code | Message | Action |
| 400 | INVALID_KEY | Invalid license key format | Prompt user for valid key |
| 404 | KEY_NOT_FOUND | License key not found | Prompt user for valid key |
| 403 | KEY_REVOKED | License has been revoked | Lock Pro features, show support link |
| 403 | LICENSE_EXPIRED | License expired on {date} | Prompt renewal |
| 403 | MACHINE_LIMIT_EXCEEDED | Maximum machines ({n}) reached | Show machine management UI |
| 403 | MACHINE_REVOKED | This machine has been revoked | Lock Pro features, show support link |
| 429 | RATE_LIMITED | Too many verification attempts | Exponential backoff, retry after Retry-After |
| 200 | VALID (valid:false) | Grace period active | Allow offline use, warn user |
Auth/Login Errors (POST /api/auth/login)
| HTTP | Code | Message | Action |
| 400 | INVALID_CREDENTIALS | Invalid email or password | Show login error |
| 401 | UNAUTHORIZED | Session invalid or expired | Clear token, force re-login |
| 402 | PAYMENT_REQUIRED | License expired or no active subscription | Redirect to billing |
| 403 | MACHINE_NOT_ACTIVATED | Machine not linked to license | Run license verification first |
| 429 | RATE_LIMITED | Too many login attempts | Exponential backoff |
Heartbeat Errors (POST /api/auth/heartbeat)
| HTTP | Code | Message | Action |
| 401 | SESSION_EXPIRED | Session token expired | Force re-login |
| 403 | LICENSE_REVOKED | License revoked since last heartbeat | Lock Pro features immediately |
| 403 | MACHINE_REVOKED | This machine revoked | Lock Pro features immediately |
| 403 | PLAN_DOWNGRADED | License downgraded to Free | Lock Pro features |
| 429 | RATE_LIMITED | Heartbeats too frequent | Respect Retry-After header |