⚠️ Error Codes

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

CodeHTTP StatusDescriptionSolution
UNAUTHORIZED401Missing or invalid authenticationCheck App Token or API key
TOKEN_EXPIRED401JWT token has expiredRe-authenticate
INVALID_TOKEN401Malformed or invalid tokenVerify token format
FORBIDDEN403Valid auth but insufficient permissionsCheck user role/permissions

Attestation Errors

CodeHTTP StatusDescriptionSolution
ATTESTATION_FAILED403Device attestation verification failedSee Troubleshooting
ATTESTATION_REQUIRED403Request missing attestation headerUpdate SDK to latest version
INVALID_ATTESTATION403Attestation data is malformedRe-initialize SDK
ATTESTATION_EXPIRED403Attestation has expiredSDK will auto-refresh
DEVICE_COMPROMISED403Device is jailbroken/rootedUse uncompromised device
EMULATOR_DETECTED403Running on simulator/emulatorUse real device
DEBUGGER_DETECTED403Debugger is attachedRun without debugger
APP_TAMPERED403App binary has been modifiedUse original app build

App & Endpoint Errors

CodeHTTP StatusDescriptionSolution
APP_NOT_FOUND404App ID doesn’t existVerify App Token
APP_DISABLED403App has been disabledContact admin
ENDPOINT_NOT_FOUND404Endpoint slug doesn’t existCheck endpoint configuration
ENDPOINT_DISABLED403Endpoint has been disabledEnable in dashboard
ENDPOINT_NOT_LINKED403Endpoint not linked to appLink endpoint to app
INVALID_METHOD405HTTP method not allowedUse correct HTTP method

Secret Errors

CodeHTTP StatusDescriptionSolution
SECRET_NOT_FOUND404Secret doesn’t existCreate secret in dashboard
SECRET_EXPIRED403Secret has expiredUpdate secret value
SECRET_DECRYPTION_FAILED500Unable to decrypt secretContact support

Rate Limiting Errors

CodeHTTP StatusDescriptionSolution
RATE_LIMITED429Too many requestsWait and retry
QUOTA_EXCEEDED429Monthly quota exceededUpgrade plan or wait
DEVICE_RATE_LIMITED429Too many requests from this deviceImplement client-side throttling

Rate limit headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1609459200
Retry-After: 60

Proxy Errors

CodeHTTP StatusDescriptionSolution
PROXY_ERROR502Error forwarding to target APICheck target API status
TARGET_TIMEOUT504Target API didn’t respond in timeIncrease timeout or retry
TARGET_UNAVAILABLE503Target API is unavailableCheck target API status
TARGET_ERROR502Target API returned an errorCheck target API response
INVALID_RESPONSE502Target API returned invalid responseCheck endpoint configuration

Validation Errors

CodeHTTP StatusDescriptionSolution
VALIDATION_ERROR400Request body validation failedCheck request format
INVALID_JSON400Request body is not valid JSONFix JSON syntax
MISSING_FIELD400Required field is missingInclude all required fields
INVALID_FIELD400Field has invalid valueCheck field requirements
PAYLOAD_TOO_LARGE413Request body exceeds size limitReduce payload size

Account Errors

CodeHTTP StatusDescriptionSolution
ACCOUNT_DISABLED403Account has been disabledContact support
ACCOUNT_PENDING_DELETION403Account scheduled for deletionCancel deletion in settings
EMAIL_NOT_VERIFIED403Email address not verifiedCheck email for verification link
IP_NOT_VERIFIED403Login from new IP requires verificationCheck email for verification link

Organization Errors

CodeHTTP StatusDescriptionSolution
ORG_NOT_FOUND404Organization doesn’t existCheck organization ID
ORG_ACCESS_DENIED403No access to this organizationRequest access from admin
ORG_LIMIT_REACHED403Organization limit reachedUpgrade plan
NOT_ORG_MEMBER403Not a member of organizationRequest invitation

Server Errors

CodeHTTP StatusDescriptionSolution
INTERNAL_ERROR500Unexpected server errorRetry or contact support
SERVICE_UNAVAILABLE503Service temporarily unavailableRetry after a moment
MAINTENANCE503Service under maintenanceCheck 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"
  }
}
FieldTypeDescription
successbooleanAlways false for errors
error.codestringMachine-readable error code
error.messagestringHuman-readable description

Need Help?

If you encounter an error not listed here:

  1. Check our Troubleshooting Guide
  2. Search our FAQ
  3. Join our Discord
  4. Contact [email protected]