|
| 1 | +# API Reference Implementation |
| 2 | + |
| 3 | +This project's API integration was developed by reverse-engineering ProtonVPN's authentication and VPN APIs. The implementation is based on patterns from these official Proton libraries: |
| 4 | + |
| 5 | +## Authentication (SRP Protocol) |
| 6 | +- **[ProtonMail/proton-python-client](https://github.com/ProtonMail/proton-python-client)** - Python implementation of Proton's SRP authentication |
| 7 | + - Reference for: `/auth/info`, `/auth`, `/auth/2fa`, `/auth/refresh` endpoints |
| 8 | + - SRP protocol implementation patterns |
| 9 | +- **[ProtonMail/go-srp](https://github.com/ProtonMail/go-srp)** - Go SRP library (direct dependency) |
| 10 | + |
| 11 | +## VPN API |
| 12 | +- **[ProtonVPN/python-proton-vpn-api-core](https://github.com/ProtonVPN/python-proton-vpn-api-core)** - Official Python VPN API client |
| 13 | + - Reference for: `/vpn/v1/certificate`, `/vpn/v1/logicals`, `/vpn/v1/sessions` endpoints |
| 14 | + - Server filtering and selection patterns |
| 15 | + - Certificate request format (`Duration`, `Features`) |
| 16 | + |
| 17 | +## Key Generation |
| 18 | +- **[ProtonVPN/go-vpn-lib](https://github.com/ProtonVPN/go-vpn-lib)** - Ed25519 to X25519 key conversion (direct dependency) |
| 19 | + |
| 20 | +## Client Version |
| 21 | +- **[ProtonVPN/proton-vpn-gtk-app](https://github.com/ProtonVPN/proton-vpn-gtk-app)** - Official Linux client |
| 22 | + - Source for `x-pm-appversion` header value (fetched dynamically at build time) |
| 23 | + |
| 24 | +## API Endpoints Used |
| 25 | + |
| 26 | +| Endpoint | Method | Description | |
| 27 | +|----------|--------|-------------| |
| 28 | +| `/core/v4/auth/info` | POST | Get SRP authentication parameters | |
| 29 | +| `/core/v4/auth` | POST | Authenticate with SRP proofs | |
| 30 | +| `/core/v4/auth/2fa` | POST | Submit 2FA code for session upgrade | |
| 31 | +| `/auth/refresh` | POST | Refresh session tokens | |
| 32 | +| `/vpn/v1/certificate` | POST | Generate WireGuard certificate | |
| 33 | +| `/vpn/v1/logicals` | GET | List available VPN servers | |
| 34 | + |
| 35 | +## Certificate Request Format |
| 36 | + |
| 37 | +The certificate request to `/vpn/v1/certificate` uses the following format: |
| 38 | + |
| 39 | +```json |
| 40 | +{ |
| 41 | + "ClientPublicKey": "<PEM-encoded public key>", |
| 42 | + "ClientPublicKeyMode": "EC", |
| 43 | + "Mode": "persistent", |
| 44 | + "DeviceName": "<device name>", |
| 45 | + "Duration": "<duration in minutes> min", |
| 46 | + "Features": { |
| 47 | + "NetShieldLevel": 0, |
| 48 | + "RandomNAT": false, |
| 49 | + "PortForwarding": false, |
| 50 | + "SplitTCP": true |
| 51 | + } |
| 52 | +} |
| 53 | +``` |
| 54 | + |
| 55 | +### Feature Keys |
| 56 | + |
| 57 | +| Key | Type | Description | |
| 58 | +|-----|------|-------------| |
| 59 | +| `NetShieldLevel` | int | NetShield ad/malware blocking (0=off, 1=malware, 2=ads+malware) | |
| 60 | +| `RandomNAT` | bool | Moderate NAT / Random NAT for gaming | |
| 61 | +| `PortForwarding` | bool | Port forwarding support | |
| 62 | +| `SplitTCP` | bool | VPN Accelerator (performance optimization) | |
| 63 | + |
| 64 | +## API Response Codes |
| 65 | + |
| 66 | +**Official sources:** |
| 67 | +- [ProtonMail/protoncore_android - ResponseCodes.kt](https://github.com/ProtonMail/protoncore_android/blob/main/network/domain/src/main/kotlin/me/proton/core/network/domain/ResponseCodes.kt) - Kotlin constants (authoritative) |
| 68 | +- [ProtonMail/proton-python-client - README.md](https://github.com/ProtonMail/proton-python-client#error-handling) - Python client error handling |
| 69 | +- [ProtonMail/proton-python-client - api.py](https://github.com/ProtonMail/proton-python-client/blob/master/proton/api.py) - Python API implementation |
| 70 | + |
| 71 | +### Success Codes |
| 72 | +| Code | Constant | Meaning | |
| 73 | +|------|----------|---------| |
| 74 | +| 1000 | OK | Success | |
| 75 | +| 1001 | - | Success (multi-status) | |
| 76 | + |
| 77 | +### Authentication Errors |
| 78 | +| Code | Constant | Meaning | |
| 79 | +|------|----------|---------| |
| 80 | +| 8002 | PASSWORD_WRONG | Incorrect password | |
| 81 | +| 8100 | AUTH_SWITCH_TO_SSO | Switch to SSO authentication | |
| 82 | +| 8101 | AUTH_SWITCH_TO_SRP | Switch to SRP authentication | |
| 83 | +| 9001 | HUMAN_VERIFICATION_REQUIRED | CAPTCHA/human verification required | |
| 84 | +| 9002 | DEVICE_VERIFICATION_REQUIRED | Device verification required | |
| 85 | +| 9101 | SCOPE_REAUTH_LOCKED | Scope re-authentication locked | |
| 86 | +| 9102 | SCOPE_REAUTH_PASSWORD | Scope re-authentication requires password | |
| 87 | + |
| 88 | +### Account Errors |
| 89 | +| Code | Constant | Meaning | |
| 90 | +|------|----------|---------| |
| 91 | +| 10001 | ACCOUNT_FAILED_GENERIC | Generic account failure | |
| 92 | +| 10002 | ACCOUNT_DELETED | Account has been deleted | |
| 93 | +| 10003 | ACCOUNT_DISABLED | Account has been disabled | |
| 94 | + |
| 95 | +### Version Errors |
| 96 | +| Code | Constant | Meaning | |
| 97 | +|------|----------|---------| |
| 98 | +| 5003 | APP_VERSION_BAD | App version no longer supported | |
| 99 | +| 5005 | API_VERSION_INVALID | API version invalid | |
| 100 | +| 5099 | APP_VERSION_NOT_SUPPORTED_FOR_EXTERNAL_ACCOUNTS | App version not supported for external accounts | |
| 101 | + |
| 102 | +### Other Errors |
| 103 | +| Code | Constant | Meaning | |
| 104 | +|------|----------|---------| |
| 105 | +| 6001 | BODY_PARSE_FAILURE | Request body parse failure | |
| 106 | +| 12081 | USER_CREATE_NAME_INVALID | Invalid username during creation | |
| 107 | +| 12087 | USER_CREATE_TOKEN_INVALID | Invalid token during user creation | |
| 108 | + |
| 109 | +### VPN-Specific Codes (observed, not in official docs) |
| 110 | +| Code | Meaning | Notes | |
| 111 | +|------|---------|-------| |
| 112 | +| 9100 | 2FA required for VPN | VPN certificate endpoint requires 2FA-authenticated session | |
| 113 | +| 10013 | Mailbox password required | Legacy 2-password mode (proton-python-client says "RefreshToken invalid") | |
| 114 | + |
| 115 | +**Note:** Codes 9100 and 10013 were observed during VPN operations but are not documented in the official protoncore_android library. Their meanings may vary by context. |
| 116 | + |
| 117 | +## Required Headers |
| 118 | + |
| 119 | +All authenticated requests require these headers: |
| 120 | + |
| 121 | +``` |
| 122 | +Authorization: Bearer <access_token> |
| 123 | +x-pm-uid: <session_uid> |
| 124 | +x-pm-appversion: linux-vpn@X.Y.Z |
| 125 | +User-Agent: ProtonVPN/X.Y.Z (Linux; Ubuntu) |
| 126 | +Content-Type: application/json |
| 127 | +``` |
| 128 | + |
| 129 | +**Important**: Using a web client version (like `web-vpn-settings@X.Y.Z`) may trigger CAPTCHA challenges. Always use the Linux client version format. |
| 130 | + |
| 131 | +## Token Refresh |
| 132 | + |
| 133 | +The token refresh endpoint expects: |
| 134 | + |
| 135 | +```json |
| 136 | +{ |
| 137 | + "ResponseType": "token", |
| 138 | + "GrantType": "refresh_token", |
| 139 | + "RefreshToken": "<refresh_token>", |
| 140 | + "RedirectURI": "http://protonmail.ch" |
| 141 | +} |
| 142 | +``` |
| 143 | + |
| 144 | +## Local Reference Libraries |
| 145 | + |
| 146 | +For debugging and verification, reference implementations are cloned in `.debug-libs/`: |
| 147 | +- `proton-python-client` - SRP authentication reference |
| 148 | +- `python-proton-vpn-api-core` - VPN API reference |
| 149 | +- `proton-vpn-gtk-app` - Linux client reference |
0 commit comments