Error Codes Reference
Complete reference of all error codes returned by ProtectMyAPI.
📖
Error codes are returned in the response body as error.code. Use these to handle errors appropriately in your app.
Authentication Errors
| Code | HTTP Status | Description | Solution |
|---|---|---|---|
UNAUTHORIZED | 401 | Missing or invalid authentication | Check App Token or API key |
TOKEN_EXPIRED | 401 | JWT token has expired | Re-authenticate |
INVALID_TOKEN | 401 | Malformed or invalid token | Verify token format |
FORBIDDEN | 403 | Valid auth but insufficient permissions | Check user role/permissions |
Attestation Errors
| Code | HTTP Status | Description | Solution |
|---|---|---|---|
ATTESTATION_FAILED | 403 | Device attestation verification failed | See Troubleshooting |
ATTESTATION_REQUIRED | 403 | Request missing attestation header | Update SDK to latest version |
INVALID_ATTESTATION | 403 | Attestation data is malformed | Re-initialize SDK |
ATTESTATION_EXPIRED | 403 | Attestation has expired | SDK will auto-refresh |
DEVICE_COMPROMISED | 403 | Device is jailbroken/rooted | Use uncompromised device |
EMULATOR_DETECTED | 403 | Running on simulator/emulator | Use real device |
DEBUGGER_DETECTED | 403 | Debugger is attached | Run without debugger |
APP_TAMPERED | 403 | App binary has been modified | Use original app build |
App & Endpoint Errors
| Code | HTTP Status | Description | Solution |
|---|---|---|---|
APP_NOT_FOUND | 404 | App ID doesn’t exist | Verify App Token |
APP_DISABLED | 403 | App has been disabled | Contact admin |
ENDPOINT_NOT_FOUND | 404 | Endpoint slug doesn’t exist | Check endpoint configuration |
ENDPOINT_DISABLED | 403 | Endpoint has been disabled | Enable in dashboard |
ENDPOINT_NOT_LINKED | 403 | Endpoint not linked to app | Link endpoint to app |
INVALID_METHOD | 405 | HTTP method not allowed | Use correct HTTP method |
Secret Errors
| Code | HTTP Status | Description | Solution |
|---|---|---|---|
SECRET_NOT_FOUND | 404 | Secret doesn’t exist | Create secret in dashboard |
SECRET_EXPIRED | 403 | Secret has expired | Update secret value |
SECRET_DECRYPTION_FAILED | 500 | Unable to decrypt secret | Contact support |
Rate Limiting Errors
| Code | HTTP Status | Description | Solution |
|---|---|---|---|
RATE_LIMITED | 429 | Too many requests | Wait and retry |
QUOTA_EXCEEDED | 429 | Monthly quota exceeded | Upgrade plan or wait |
DEVICE_RATE_LIMITED | 429 | Too many requests from this device | Implement client-side throttling |
Rate limit headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1609459200
Retry-After: 60Proxy Errors
| Code | HTTP Status | Description | Solution |
|---|---|---|---|
PROXY_ERROR | 502 | Error forwarding to target API | Check target API status |
TARGET_TIMEOUT | 504 | Target API didn’t respond in time | Increase timeout or retry |
TARGET_UNAVAILABLE | 503 | Target API is unavailable | Check target API status |
TARGET_ERROR | 502 | Target API returned an error | Check target API response |
INVALID_RESPONSE | 502 | Target API returned invalid response | Check endpoint configuration |
Validation Errors
| Code | HTTP Status | Description | Solution |
|---|---|---|---|
VALIDATION_ERROR | 400 | Request body validation failed | Check request format |
INVALID_JSON | 400 | Request body is not valid JSON | Fix JSON syntax |
MISSING_FIELD | 400 | Required field is missing | Include all required fields |
INVALID_FIELD | 400 | Field has invalid value | Check field requirements |
PAYLOAD_TOO_LARGE | 413 | Request body exceeds size limit | Reduce payload size |
Account Errors
| Code | HTTP Status | Description | Solution |
|---|---|---|---|
ACCOUNT_DISABLED | 403 | Account has been disabled | Contact support |
ACCOUNT_PENDING_DELETION | 403 | Account scheduled for deletion | Cancel deletion in settings |
EMAIL_NOT_VERIFIED | 403 | Email address not verified | Check email for verification link |
IP_NOT_VERIFIED | 403 | Login from new IP requires verification | Check email for verification link |
Organization Errors
| Code | HTTP Status | Description | Solution |
|---|---|---|---|
ORG_NOT_FOUND | 404 | Organization doesn’t exist | Check organization ID |
ORG_ACCESS_DENIED | 403 | No access to this organization | Request access from admin |
ORG_LIMIT_REACHED | 403 | Organization limit reached | Upgrade plan |
NOT_ORG_MEMBER | 403 | Not a member of organization | Request invitation |
Server Errors
| Code | HTTP Status | Description | Solution |
|---|---|---|---|
INTERNAL_ERROR | 500 | Unexpected server error | Retry or contact support |
SERVICE_UNAVAILABLE | 503 | Service temporarily unavailable | Retry after a moment |
MAINTENANCE | 503 | Service under maintenance | Check status page |
SDK Error Handling
iOS (Swift)
do {
let response = try await ProtectMyAPI.shared.request(...)
} catch ProtectMyAPIError.attestationFailed(let reason) {
// Handle attestation failure
switch reason {
case .jailbreakDetected:
showAlert("Security violation detected")
case .simulatorDetected:
showAlert("Please use a real device")
default:
showAlert("Verification failed")
}
} catch ProtectMyAPIError.rateLimited(let retryAfter) {
// Wait and retry
try await Task.sleep(nanoseconds: UInt64(retryAfter) * 1_000_000_000)
} catch ProtectMyAPIError.networkError(let error) {
showAlert("Network error: \(error.localizedDescription)")
} catch ProtectMyAPIError.serverError(let code, let message) {
showAlert("Server error: \(message)")
} catch {
showAlert("Error: \(error.localizedDescription)")
}Android (Kotlin)
try {
val response = ProtectMyAPI.request(...)
} catch (e: ProtectMyAPIException.IntegrityCheckFailed) {
// Handle attestation failure
when (e.reason) {
IntegrityFailureReason.ROOTED -> showAlert("Rooted device detected")
IntegrityFailureReason.EMULATOR -> showAlert("Please use a real device")
else -> showAlert("Verification failed")
}
} catch (e: ProtectMyAPIException.RateLimited) {
// Wait and retry
delay(e.retryAfterSeconds * 1000L)
} catch (e: ProtectMyAPIException.NetworkError) {
showAlert("Network error: ${e.message}")
} catch (e: ProtectMyAPIException.ServerError) {
showAlert("Server error: ${e.message}")
} catch (e: Exception) {
showAlert("Error: ${e.message}")
}Flutter (Dart)
try {
final response = await ProtectMyAPI.instance.request(...);
} on ProtectMyAPIException catch (e) {
switch (e.type) {
case ProtectMyAPIExceptionType.attestationFailed:
showAlert("Verification failed");
break;
case ProtectMyAPIExceptionType.rateLimited:
await Future.delayed(Duration(seconds: e.retryAfter ?? 60));
// Retry
break;
case ProtectMyAPIExceptionType.networkError:
showAlert("Network error: ${e.message}");
break;
default:
showAlert("Error: ${e.message}");
}
} catch (e) {
showAlert("Unexpected error: $e");
}Error Response Format
All errors follow this format:
{
"success": false,
"error": {
"code": "ATTESTATION_FAILED",
"message": "Device attestation verification failed"
}
}| Field | Type | Description |
|---|---|---|
success | boolean | Always false for errors |
error.code | string | Machine-readable error code |
error.message | string | Human-readable description |
Need Help?
If you encounter an error not listed here:
- Check our Troubleshooting Guide
- Search our FAQ
- Join our Discord
- Contact [email protected]