VPNHouse Client API
1. Overall API Flow
Generally, API calls are divided by 3 groups:
- Authorizing-related - provides authentication token to access further API calls
- Discovery-related - provides credentials to target VPN nodes
- Tunnel-related - manages actual wireguard tunnel
Please, take a look at the next diagram to get the actual sequence of requests.
2. Errors
2.1. Generic Description
All errors are returned with meaningful HTTP error code and JSON body with more detailed information. For example, syntax error will return HTTP 400 error with next body:
{
result: "INVALID_ARGUMENT",
error: "Invalid request",
details: "invalid character '\\n' in string literal"
}
Check the table below for the field description.
Field | Description |
---|---|
result | A predefined set of strings, identifying the type of error. See below all types. |
error | More detailed error information. |
details | Some extra information about errors. |
2.2. List of Errors
HTTP code | Result code | Description |
---|---|---|
500 | INTERNAL_ERROR | Any unexpected behavior of backend components. |
400 | INVALID_ARGUMENT | Invalid request data, like syntax or type errors. |
404 | NOT_FOUND | Managed entities are not found (for example, when a ping request is done for outdated peers). |
409 | ENTRY_EXISTS | Can't create entry due to conflict. Can happen when the wireguard key is already used. |
500 | STORAGE_ERROR | Internal storage failure. |
500 | TUNNEL_ERROR | Tunnel management failure. |
401 | UNAUTHORIZED | Request requires authorization. |
401 | AUTH_FAILED | Requests can't be done with provided authorization data. |
507 | INSUFFICIENT_STORAGE | Out of resources to perform requests. |
503 | SERVICE_UNAVAILABLE | Happens when a request is made while the service is shutting down or restarting. |
3. Authorizer API
3.1. Authorize client
URL: https://api.vpnhouse.net/api/client/signin
Method: POST
Authentication: None
Query string: None
Request body: JSON
Fields, marked with * are mandatory.
OBJECT
{
project*: string
client_platform*: string
client_version*: string
device_id*: uuid
auth_type*: string
auth_info*: string
}
Fields, marked with * are mandatory.
Name | Format | Description |
---|---|---|
project * | string | Name of the project |
client_platform * | string | Client platform (i.e. ios, android, etc.) |
client_version * | string | Version of client application release (i.e. 1.2.3) |
device_id * | string | Device ID in UUID format |
auth_type * | string | Authentication scheme |
auth_info * | string | Authentication information |
{
"project": "Project",
"client_platform": "iphone",
"client_version": "1.0.1",
"device_id": "f7df7c7a-3569-401c-b612-f49b775bb19e",
"auth_type": "firebase",
"auth_info": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
}
{
"project": "Project",
"client_platform": "iphone",
"client_version": "1.0.1",
"device_id": "f7df7c7a-3569-401c-b612-f49b775bb19e",
"auth_type": "anonymous",
"auth_info": "be2757b5-f8ba-49ea-9c7d-dcce2d1390f2"
}
Response body: JSON
Fields, marked with * are mandatory.
OBJECT
{
access_token*: string
refresh_token: string
discovery_addresses: [uri]
}
Fields, marked with * are mandatory.
Name | Format | Description |
---|---|---|
access_token * | string | JWT token, used for all further operations with backend |
refresh_token | string | JWT token, used to get new access token. |
discovery_addresses | array[uri] | Array of URLs for requesting locations and node credentials. |
If refresh_token is not specified, you should authenticate again to get next token.
If discovery_addresses is not specified or empty, you should keep using same base URL (i.e. https://api.vpnhouse.net) for discovery requests.
{
access_token: "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBmNmQwZGFiLWU0NzgtNGQ1Ni1hZGJhLTU5M2ZhYmE4ZTRhYiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ2cG4tbm9kZSIsImV4cCI6MTYyNDk0OTk0NywianRpIjoiNTUxNzYyODQtZDdkZS0xMWViLWE2NDUtMDI0MmFjMTIwMDAyIiwiaWF0IjoxNjI0ODYzNTQ3LCJpc3MiOiJUZXN0UHJvamVjdC1BdXRoLTEtMiIsIm5iZiI6MTYyNDg2MzU0Nywic3ViIjoiRmVuZFZQTlRlc3RQcm9qZWN0L2ZpcmViYXNlL0pvaG5Eb2UifQ.REIfc3DB4e4pU7GyNU7vmJfsJBDu-0PLghV06KIdEM0Vhg4jVFA4MzgRU_j151PrAalSrpj0gLJGW8qZfqSLyDshRQCjgKYEt_X5PmNVkFmAjUz6hwCBJ8tMRxfhG2vcG1WZF80aTLLx6LQ0NwGT6hfAYEemzAecVwvnTuE1BQow3c1T71uZSByLDP1WAa0ZYnNZjceOGeikSXK5RtHogSyZkud7zfi_dKhDzW8Pgd_06HYEmexogv3LMpbJ0NY0nrRnxqPlJ1-uqQ6OIktQe1RvLe7BTGBthp_wrAv3Z9YdGSzJrlJhr1hg6qTzzdo0UHdvCpMeIun8bpr7OWVEIg",
refresh_token: "eyJhbGciOiJSUzI1NiIsImtpZCI6IjBmNmQwZGFiLWU0NzgtNGQ1Ni1hZGJhLTU5M2ZhYmE4ZTRhYiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJyZWZyZXNoIiwiZXhwIjoxNjMwMTMzOTQ3LCJqdGkiOiI1NTE3NjI4NC1kN2RlLTExZWItYTY0NS0wMjQyYWMxMjAwMDIiLCJpYXQiOjE2MjQ4NjM1NDcsImlzcyI6IlRlc3RQcm9qZWN0LUF1dGgtMS0yIiwibmJmIjoxNjI0ODYzNTQ3LCJzdWIiOiJGZW5kVlBOVGVzdFByb2plY3QvZmlyZWJhc2UvSm9obkRvZSJ9.GbhbrSxLcoj7yJFQnh1Pq2_3OXMnffihRaRyOsHay8RLyZzwHTpHN_uEcT-5z7l_kbrcWWMuswChrnt6zYuzzMa_qPFXpSIwkf3xXrFOr4Og-wLQqsy6Uh7-hJB546mMt-bT7tCFXZbNRtCm_lzIW6mPAcIJtofJsqSPaFL-xWrJEl0m4vRNV4NusGwlCuE7uvjQPLUF5gS98QLLWNWyHipVWxjSEK57I0ngrsOU7b4jETHxtgYYQ_O2S5GoOUe0YrwYFkrKP1LB3eE_aAw-toOJSP6eVm_Y345MBVJj8NcGa3Kbdm5SzZhHs2P-ZoKc8Yp2FdiFPyCq6VDmQ2PyXw",
discovery_addresses: [
"https://discovery.project.io/api/client/locations"
]
}
4. Discovery API
4.1. List locations
URL: https://api.vpnhouse.net/api/client/locations
Method: GET
Authentication: Bearer
Query string: None
Request body: None
Response body: JSON
Fields, marked with * are mandatory.
ARRAY
[
{
id*: string
name*: string
labels: {}
}
]
Fields, marked with * are mandatory.
Name | Format | Description |
---|---|---|
id * | string | Location identifier. |
name * | string | Location user-friendly name. |
labels | array | Map of location labels, if specified. |
[
{
id: "US",
name: "United States",
labels: { },
}
]
4.2. Get location nodes
URL: https://api.vpnhouse.net/api/client/credentials
Method: GET
Authentication: Bearer
Query string: location=<LOCATION_ID>
Request body: None
Response body: JSON
Fields, marked with * are mandatory.
ARRAY
[
{
id*: string
connection_addresses: [string]
}
]
Fields, marked with * are mandatory.
Name | Format | Description |
---|---|---|
id * | string | Server unique identifier. |
connection_addresses | string | Array of servers URLs. |
Response contains an array of a server nodes in order to try them. I.e. application should always start from first entry in array, if it's failed - go to second, etc.
If connection_addresses is not specified or empty, you should keep using same base URL to establish tunnel connections. This can happen when you use demo backend.
[
{
id: "US",
name: "United States",
labels: { },
}
]
5. Tunneling API
5.1. Initiate connection.
URL: https://some-server-name.vpnhouse.net/api/client/connect
Method: POST
Authentication: Bearer
Query string: None
Request body: JSON
Fields, marked with * are mandatory.
OBJECT
{
info_wireguard*: {
public_key: string
}
identifiers* {
installation_id: uuid
session_id: uuid
}
location: string
}
Fields, marked with * are mandatory.
Name | Format | Description |
---|---|---|
info_wireguard | object | Wireguard-specific connection information. |
public_key * | string | Client wireguard public key. |
uuid | Application installation ID. Generated during installation or first application startup. | |
session_id * | uuid | Session ID. Generated every time when user starts connection. |
location | string | Location ID. |
{
"info_wireguard": {
"public_key": "+NK8yiGfvGOoAFVFii8bU6JCqd4j5dSpMppfIeJDtx0="
},
"identifiers": {
"installation_id": "d1a1b2e2-d84b-4537-9a93-c4d3cd412598",
"session_id": "de9e0337-fb16-4669-b07d-9f261c329461"
},
"location": "US"
}
Response body: JSON
OBJECT
{
info_wireguard: {
server_public_key*: string
server_ipv4*: ipv4
server_port*: integer
tunnel_ipv4*: ipv4
keepalive*: integer
allowed_ips*: [string]
dns*: [ipv4]
ping_interval*: integer
}
}
Name | Format | Description |
---|---|---|
info_wireguard | object | Wireguard-specific connection information. |
server_public_key | string | Server wireguard public key. |
server_ipv4 | ipv4 | Server ipv4. |
server_port | integer | Server port. |
tunnel_ipv4 | ipv4 | Client in-tunnel ipv4 address. |
keepalive | integer | Wireguard keepalive interval. Zero means no keepalive. |
allowed_ips | array[cidr] | List of allowed IPs in terms of wireguard configuration. |
dns | array[ipv4] | List of DNS addresses to use. |
ping_interval | integer | Interval to do a heartbeat request. |
{
info_wireguard: {
server_public_key: "b0o7b8vXx9EH3uLJucOJUed0slvSppv7RCmC8jXRr1o=",
server_ipv4: "1.2.3.4",
server_port: 3000,
tunnel_ipv4: "192.168.2.2",
keepalive: 60,
allowed_ips: [
"0.0.0.0/0"
],
dns: [
"198.51.100.42"
],
ping_interval: 60
}
}
Wireguard config pattern
[Interface]
Address = $tunnel_ipv4/32
DNS = $dns_comma_separated_list
PrivateKey = $private_key
[Peer]
PublicKey = $server_public_key
AllowedIPs = $allowed_ips_comma_separated_list
Endpoint = $server_ipv4:$server_port
Wireguard config example
[Interface]
Address = 192.168.2.2/32
DNS = 198.51.100.42
PrivateKey = ADKch0tZqNb7iH/Wupl4STtCAJNI0jS5JCHr9Rg9WUk=
[Peer]
PublicKey = b0o7b8vXx9EH3uLJucOJUed0slvSppv7RCmC8jXRr1o=
AllowedIPs = 0.0.0.0/0
Endpoint = 1.2.3.4:3000
5.2. Heartbeat request.
URL: https://some-server-name.vpnhouse.net/api/client/ping
Method: POST
Authentication: Bearer
Query string: None
Request body: JSON
OBJECT
{
installation_id: uuid
session_id: uuid
}
Name | Format | Description |
---|---|---|
installation_id * | uuid | Application installation ID. Generated during installation or first application startup. |
session_id * | uuid | Session ID. Generated every time when user starts connection. |
{
"installation_id": "d1a1b2e2-d84b-4537-9a93-c4d3cd412598",
"session_id": "de9e0337-fb16-4669-b07d-9f261c329461"
}
Response body: None
5.3. Drop connection.
URL: https://some-server-name.vpnhouse.net/api/client/disconnect
Method: POST
Authentication: Bearer
Query string: None
Request body: JSON
OBJECT
{
installation_id: uuid
session_id: uuid
}
Name | Format | Description |
---|---|---|
installation_id * | uuid | Application installation ID. Generated during installation or first application startup. |
session_id * | uuid | Session ID. Generated every time when user starts connection. |
{
"installation_id": "d1a1b2e2-d84b-4537-9a93-c4d3cd412598",
"session_id": "de9e0337-fb16-4669-b07d-9f261c329461"
}
Response body: None