Error Handling

Understanding error responses and implementing proper error handling in your VPT API integration.

Overview

The VPT API uses structured error responses for clear debugging. All errors follow a consistent format, making it easy to handle errors programmatically.

Error Response Format

JSON Error Format
{
  "success": false,
  "error": {
    "message": "Human-readable error description",
    "code": "ERROR_CODE",
    "status": 401
  }
}

Authentication Error Codes

These errors occur during login or when validating JWT tokens.

Code HTTP Status Description
AUTH_REQUIRED 401 No authentication token provided
AUTH_MISSING_CREDENTIALS 400 Email or password missing in login request
AUTH_MISSING_DEV_KEY 400 Developer key not provided in login request
AUTH_INVALID_CREDENTIALS 401 Invalid email or password
AUTH_TOKEN_EXPIRED 401 JWT token has expired
AUTH_TOKEN_REVOKED 401 Token was revoked (password changed)
AUTH_TOKEN_INVALID 401 Malformed or tampered JWT token

API Error Codes

These errors occur when making API requests after authentication.

Code HTTP Status Description
INVALID_REQUEST 400 Request body is malformed or missing required fields
INVALID_QUERY 400 The query parameter is invalid or unsupported
MISSING_PARAMETERS 400 Required parameters are missing from the request
RATE_LIMIT_EXCEEDED 429 Too many requests - rate limit exceeded
SERVER_ERROR 500 Internal server error - please try again later

OFP & Flight Data Error Codes

These errors are returned by the OFP storage endpoints (ofpImport, ofpList, ofpGet, ofpDelete, ofpAsset) and the Flight Data endpoints (flightDataList, flightDataGet, flightDataSave, flightDataDelete).

Code HTTP Status Description
OFP_NOT_FOUND 404 No OFP with that id belongs to the caller
OFP_PAYLOAD_MISSING 404 OFP row exists but the stored ofp.json is missing on disk
OFP_PAYLOAD_CORRUPT 500 Stored ofp.json could not be parsed
OFP_ASSET_NOT_FOUND 404 The requested asset kind does not exist for this OFP
OFP_PREVIEW_AIRPORT_RESTRICTED 403 Preview users can only import OFPs whose origin and destination are in the demo airports list
OFP_IMPORT_FAILED 400 Generic Simbrief import failure (network, quota, or upstream error)
INVALID_OFP_ID 400 OFP id missing or contains forbidden characters
INVALID_DATA_KEY 400 Flight Data dataKey missing or invalid (max 64 chars, A-Z a-z 0-9 . _ -)
FLIGHT_DATA_NOT_FOUND 404 No saved Flight Data row exists for (ofpId, dataKey)
MISSING_PAYLOAD 400 flightDataSave body had no payload field
INVALID_PAYLOAD 400 Payload is not an object, array or JSON string
INVALID_TIMESTAMP 400 lastDownloadedAt could not be parsed as ISO 8601
PAYLOAD_TOO_LARGE 413 Flight Data payload exceeds the 4 MB hard cap
VERSION_CONFLICT 409 The client's expectedVersion or lastDownloadedAt does not match the server. The response body's current field contains the server's up-to-date copy so the client can present a Cancel / Download latest / Override dialog.

OFP Sharing Error Codes

Returned by the cross-account sharing endpoints (ofpShare, ofpShareList, ofpShareAccept, ofpShareRevoke) and by any OFP / Flight Data endpoint when the caller is a shared user with insufficient permission.

Code HTTP Status Description
INVALID_PERMISSION 400 permission must be "view" or "edit"
INVALID_EMAIL 400 sharedWithEmail is not a valid email address
INVALID_EXPIRY 400 expiresInDays must be between 1 and 365
INVALID_SHARE_TARGET 400 You cannot share an OFP with yourself / accept your own share
SHARE_NOT_FOUND 404 No share matches the supplied token / code / id
SHARE_REVOKED 410 This share has been revoked and can no longer be redeemed
SHARE_EXPIRED 410 This share has passed its expiresAt
SHARE_FORBIDDEN 403 This share is bound to a different account, or the caller cannot revoke it
INSUFFICIENT_PERMISSION 403 Caller has view access to the OFP but tried a Flight Data write (flightDataSave, flightDataDelete).

Handling Errors

Here's how to properly handle errors in your application:

JavaScript
async function apiRequest(endpoint, data) {
    try {
        const response = await fetch(endpoint, {
            method: 'POST',
            headers: {
                'Authorization': `Bearer ${token}`,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(data)
        });

        const result = await response.json();

        if (!result.success) {
            // Handle specific error codes
            switch (result.error.code) {
                case 'AUTH_TOKEN_EXPIRED':
                case 'AUTH_TOKEN_REVOKED':
                    // Redirect to login
                    localStorage.removeItem('vpt_token');
                    window.location.href = '/login';
                    break;
                case 'RATE_LIMIT_EXCEEDED':
                    // Wait and retry
                    await delay(5000);
                    return apiRequest(endpoint, data);
                default:
                    // Display error message to user
                    showError(result.error.message);
            }
            return null;
        }

        return result;
    } catch (error) {
        console.error('Network error:', error);
        showError('Network error. Please check your connection.');
        return null;
    }
}
Best Practices
  • Always check the success field in responses
  • Use the error.code for programmatic handling
  • Display error.message for user-facing errors
  • Implement retry logic for transient errors (5xx, rate limits)

Next Steps