Skip to content

Authentication

Initialize your client using the overview examples, then choose an authentication method.

Basic


Authentication using HTTP Basic. The username and password are passed in an HTTP header. This method must not be used from web browsers.

Examples

Ruby · Simple
require 'haveapi/client'

api = HaveAPI::Client.new("https://api.vpsfree.cz/", version: "7.0")

api.authenticate(:basic, user: 'user', password: 'secret')
Ruby · With error handling
begin
  require 'haveapi/client'

  api = HaveAPI::Client.new("https://api.vpsfree.cz/", version: "7.0")

  api.setup

  api.authenticate(:basic, user: 'user', password: 'secret')
rescue HaveAPI::Client::ValidationError => error
  warn error.message
  warn error.errors.inspect
rescue HaveAPI::Client::ActionFailed => error
  warn error.message
  warn error.response.errors.inspect if error.response.is_a?(HaveAPI::Client::Response)
rescue HaveAPI::Client::Authentication::AuthenticationFailed, HaveAPI::Client::ProtocolError,
       RestClient::Exception, JSON::ParserError => error
  warn error.message
end
JavaScript (callback) · Simple
import { CallbackClient } from "haveapi-client";

const api = new CallbackClient("https://api.vpsfree.cz/", {version: "7.0"});

api.authenticate("basic", {user: "user", password: "secret"}, (api, ready) => {
  if (!ready) {
    console.error("Discovery or authentication failed");
    return;
  }
});
JavaScript (async) · Simple
import { AsyncClient } from "haveapi-client";

const api = new AsyncClient("https://api.vpsfree.cz/", {version: "7.0"});
await api.authenticate("basic", {user: "user", password: "secret"});
JavaScript (async) · With error handling
import { AsyncClient, AsyncError } from "haveapi-client";

async function main() {
  const api = new AsyncClient("https://api.vpsfree.cz/", {version: "7.0"});
  try {
    await api.authenticate("basic", {user: "user", password: "secret"});
    console.log("Authenticated");
  } catch (error) {
    if (error instanceof AsyncError) {
      console.error(error.kind, error.message, error.errors);
    } else {
      throw error;
    }
  }
}
main().catch(error => console.error(error));
TypeScript (callback) · Simple
import { CallbackClient } from "haveapi-client";

const api = new CallbackClient("https://api.vpsfree.cz/", {version: "7.0"});

api.authenticate("basic", {user: "user", password: "secret"}, (api, ready) => {
  if (!ready) {
    console.error("Discovery or authentication failed");
    return;
  }
});
TypeScript (async) · Simple
import { AsyncClient } from "haveapi-client";

const api = new AsyncClient("https://api.vpsfree.cz/", {version: "7.0"});
await api.authenticate("basic", {user: "user", password: "secret"});
TypeScript (async) · With error handling
import { AsyncClient, AsyncError } from "haveapi-client";

async function main(): Promise<void> {
  const api = new AsyncClient("https://api.vpsfree.cz/", {version: "7.0"});
  try {
    await api.authenticate("basic", {user: "user", password: "secret"});
    console.log("Authenticated");
  } catch (error) {
    if (error instanceof AsyncError) {
      console.error(error.kind, error.message, error.errors);
    } else {
      throw error;
    }
  }
}
main().catch(error => console.error(error));
Python (sync) · Simple
from haveapi_client import Client, BasicAuth

with Client("https://api.vpsfree.cz/", version="7.0", auth=BasicAuth("user", "secret")) as api:
    # Call API actions inside this block.
    pass
Python (sync) · With error handling
from haveapi_client import Client, ActionError, HaveAPIError, BasicAuth

try:
    with Client("https://api.vpsfree.cz/", version="7.0", auth=BasicAuth("user", "secret")) as api:
        print("Authenticated")
except ActionError as error:
    print(error.message, error.errors)
except HaveAPIError as error:
    print(error.message, error.status_code)
Python (async) · Simple
import asyncio

from haveapi_client import AsyncClient, BasicAuth


async def main() -> None:
    async with AsyncClient("https://api.vpsfree.cz/", version="7.0", auth=BasicAuth("user", "secret")) as api:
        # Call API actions inside this block.
        pass


asyncio.run(main())
Python (async) · With error handling
import asyncio

from haveapi_client import AsyncClient, ActionError, HaveAPIError, BasicAuth


async def main() -> None:
    try:
        async with AsyncClient("https://api.vpsfree.cz/", version="7.0", auth=BasicAuth("user", "secret")) as api:
            print("Authenticated")
    except ActionError as error:
        print(error.message, error.errors)
    except HaveAPIError as error:
        print(error.message, error.status_code)


asyncio.run(main())
Go API client · Simple
// go get github.com/vpsfreecz/vpsadmin-go-client/client@latest
package main

import (
	client "github.com/vpsfreecz/vpsadmin-go-client/client"
)

func main() {
	api := client.New("https://api.vpsfree.cz")
	api.SetBasicAuthentication("user", "secret")
}
Rust API client (async) · Simple
// cargo add vpsadmin-client
// cargo add tokio --features macros,rt-multi-thread
// cargo add serde_json
use vpsadmin_client::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api = Client::builder("https://api.vpsfree.cz/")
        .basic_auth("user", "secret")
        .build()?;
    // Configure existing credentials only; building does not validate them with the server.
    let _ = &api;
    Ok(())
}
Rust API client (async) · With error handling
// cargo add vpsadmin-client
// cargo add tokio --features macros,rt-multi-thread
// cargo add serde_json
use vpsadmin_client::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api = match Client::builder("https://api.vpsfree.cz/")
        .basic_auth("user", "secret")
        .build() {
        Ok(api) => api,
        Err(error) => {
            eprintln!("Client configuration failed: {}", error);
            eprintln!("HTTP status: {:?}; timeout: {}", error.http_status(), error.is_timeout());
            return Err(error.into());
        }
    };
    // Configure existing credentials only; building does not validate them with the server.
    let _ = &api;
    Ok(())
}
Rust API client (blocking) · Simple
// cargo add vpsadmin-client --features blocking
// cargo add serde_json
// Construct, use and drop this blocking client outside async runtime threads.
use vpsadmin_client::blocking::Client;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api = Client::builder("https://api.vpsfree.cz/")
        .basic_auth("user", "secret")
        .build()?;
    // Configure existing credentials only; building does not validate them with the server.
    let _ = &api;
    Ok(())
}
Rust API client (blocking) · With error handling
// cargo add vpsadmin-client --features blocking
// cargo add serde_json
// Construct, use and drop this blocking client outside async runtime threads.
use vpsadmin_client::blocking::Client;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api = match Client::builder("https://api.vpsfree.cz/")
        .basic_auth("user", "secret")
        .build() {
        Ok(api) => api,
        Err(error) => {
            eprintln!("Client configuration failed: {}", error);
            eprintln!("HTTP status: {:?}; timeout: {}", error.http_status(), error.is_timeout());
            return Err(error.into());
        }
    };
    // Configure existing credentials only; building does not validate them with the server.
    let _ = &api;
    Ok(())
}
TypeScript API client · Simple
// Configured API client: vpsadmin-typescript-client.
import { AsyncClient } from "haveapi-client";
import { createClient } from "vpsadmin-typescript-client";

async function main(): Promise<void> {
  const runtime = new AsyncClient("https://api.vpsfree.cz/v7.0");
  await runtime.authenticate("basic", { user: "user", password: "secret" });
  const api = createClient({ execute: spec => runtime.request(spec) });
  void api;
}

main().catch(error => { throw error; });
TypeScript API client · With error handling
// Configured API client: vpsadmin-typescript-client.
import { AsyncClient, AsyncError } from "haveapi-client";
import { createClient } from "vpsadmin-typescript-client";

async function main(): Promise<void> {
  try {
    const runtime = new AsyncClient("https://api.vpsfree.cz/v7.0");
    await runtime.authenticate("basic", { user: "user", password: "secret" });
    const api = createClient({ execute: spec => runtime.request(spec) });
    void api;
  } catch (error) {
    if (!(error instanceof AsyncError)) throw error;
    console.error(error.kind, error.httpStatus);
    throw error;
  }
}

main().catch(error => { throw error; });
PHP · Simple
$api = new \HaveAPI\Client('https://api.vpsfree.cz/', '7.0');

$api->authenticate('basic', ['user' => 'user', 'password' => 'secret']);
PHP · With error handling
try {
    $api = new \HaveAPI\Client('https://api.vpsfree.cz/', '7.0');
    $api->setup();

    $api->authenticate('basic', ['user' => 'user', 'password' => 'secret']);
} catch (\HaveAPI\Client\Exception\ValidationError $error) {
    echo $error->getMessage() . "\n";
    print_r($error->getErrors());
} catch (\HaveAPI\Client\Exception\ActionFailed $error) {
    echo $error->getMessage() . "\n";
    print_r($error->getErrors());
} catch (\HaveAPI\Client\Exception\Base $error) {
    echo $error->getMessage() . "\n";
} catch (\Exception $error) {
    // Dependency failures still propagate to the application.
    echo $error->getMessage() . "\n";
    throw $error;
}
CLI · Simple
# Provide credentials on command line
$ haveapi-cli -u https://api.vpsfree.cz/ --version 7.0 --auth basic --user user --password secret

# If username or password isn't provided, the user is asked on stdin
$ haveapi-cli -u https://api.vpsfree.cz/ --version 7.0 --auth basic --user user
# Password: secret
curl · Simple
# Password is asked on standard input
$ curl --request OPTIONS \
       --user user \
       https://api.vpsfree.cz/
# Password: secret

# Password given on the command line
$ curl --request OPTIONS \
       --user user:secret \
       https://api.vpsfree.cz/
HTTP · Simple
GET / HTTP/1.1
Host: api.vpsfree.cz
Authorization: Basic dXNlcjpzZWNyZXQ=

Token


The client authenticates with credentials, usually a username and password, and receives a token. From that point on, the credentials can be forgotten and the token is used instead. Tokens can have different lifetimes and can be renewed or revoked. The token is passed either in an HTTP header or as a query parameter.

Resources

Token

Manage authentication tokens

Renew

Input parameters

No parameters.

Output parameters
ParameterTypeDescription
valid_to
Valid_to
Datetime

Request

Input parameters
ParameterTypeRequiredDetails
user
User
String yes

Default: null

Validation rules
RuleDetails
Present

Must be supplied and cannot be null. Must not be empty; strings must contain a non-whitespace character.

Validation error message: must be present and non-empty

password
Password
String yes

Auto-generated password

Default: null

Validation rules
RuleDetails
Present

Must be supplied and cannot be null. Must not be empty; strings must contain a non-whitespace character.

Validation error message: must be present and non-empty

scope
Scope
String no

Default: all

lifetime
Lifetime
String yes

fixed - the token has a fixed validity period and cannot be renewed renewable_manual - the token can be renewed, but only manually using the renew action renewable_auto - the token is renewed automatically to now + interval whenever it is used permanent - the token is valid forever unless deleted

Default: null

Validation rules
RuleDetails
Present

Must be supplied and cannot be null. Must not be empty; strings must contain a non-whitespace character.

Validation error message: must be present and non-empty

Include

Allowed values:

  • fixed
  • renewable_manual
  • renewable_auto
  • permanent

Validation error message: %{value} cannot be used

interval
Interval
Integer no

How long the requested token will be valid, in seconds.

Default: 300

Validation rules
RuleDetails
Number
  • Must be a number after parameter type conversion.
  • Minimum: 1 (inclusive).
  • Maximum: 86400 (inclusive).

Validation error message: must be between 1 and 86400

Output parameters
ParameterTypeDescription
token
Token
String Authentication token
valid_to
Valid_to
Datetime
complete
Complete
Boolean
next_action
Next_action
String

Reset_password

Input parameters
ParameterTypeRequiredDetails
token
Token
String yes

Authentication token

Default: null

Validation rules
RuleDetails
Present

Must be supplied and cannot be null. Must not be empty; strings must contain a non-whitespace character.

Validation error message: must be present and non-empty

new_password1
New password
String yes

Default: null

Validation rules
RuleDetails
Present

Must be supplied and cannot be null. Must not be empty; strings must contain a non-whitespace character.

Validation error message: must be present and non-empty

new_password2
Repeat new password
String yes

Default: null

Validation rules
RuleDetails
Present

Must be supplied and cannot be null. Must not be empty; strings must contain a non-whitespace character.

Validation error message: must be present and non-empty

Output parameters
ParameterTypeDescription
token
Token
String Authentication token
valid_to
Valid_to
Datetime
complete
Complete
Boolean
next_action
Next_action
String

Revoke

Input parameters

No parameters.

Output parameters

No parameters.

Totp

Input parameters
ParameterTypeRequiredDetails
token
Token
String yes

Authentication token

Default: null

Validation rules
RuleDetails
Present

Must be supplied and cannot be null. Must not be empty; strings must contain a non-whitespace character.

Validation error message: must be present and non-empty

code
TOTP code
String yes

Default: null

Validation rules
RuleDetails
Present

Must be supplied and cannot be null. Must not be empty; strings must contain a non-whitespace character.

Validation error message: must be present and non-empty

Output parameters
ParameterTypeDescription
token
Token
String Authentication token
valid_to
Valid_to
Datetime
complete
Complete
Boolean
next_action
Next_action
String

Examples

Ruby · Simple
require 'haveapi/client'

api = HaveAPI::Client.new("https://api.vpsfree.cz/", version: "7.0")

api.authenticate(:token, **{user: "user", password: "secret", scope: "scope", lifetime: "fixed"}) do |action, parameters|
  continuations = {"totp" => {"code" => "code"}, "reset_password" => {"new_password1" => "new_password1", "new_password2" => "new_password2"}}
  input = continuations.fetch(action.to_s) { raise ArgumentError, 'Unknown authentication continuation' }
  unless (parameters.keys.map(&:to_s) - input.keys - ['token']).empty?
    raise ArgumentError, 'Unknown authentication input'
  end
  input.transform_keys(&:to_sym)
end

# Reuse an existing token
api.authenticate(:token, token: 'example-token')
Ruby · With error handling
begin
  require 'haveapi/client'

  api = HaveAPI::Client.new("https://api.vpsfree.cz/", version: "7.0")

  api.setup

  api.authenticate(:token, **{user: "user", password: "secret", scope: "scope", lifetime: "fixed"}) do |action, parameters|
    continuations = {"totp" => {"code" => "code"}, "reset_password" => {"new_password1" => "new_password1", "new_password2" => "new_password2"}}
    input = continuations.fetch(action.to_s) { raise ArgumentError, 'Unknown authentication continuation' }
    unless (parameters.keys.map(&:to_s) - input.keys - ['token']).empty?
      raise ArgumentError, 'Unknown authentication input'
    end
    input.transform_keys(&:to_sym)
  end

  # Reuse an existing token
  api.authenticate(:token, token: 'example-token')
rescue HaveAPI::Client::ValidationError => error
  warn error.message
  warn error.errors.inspect
rescue HaveAPI::Client::ActionFailed => error
  warn error.message
  warn error.response.errors.inspect if error.response.is_a?(HaveAPI::Client::Response)
rescue HaveAPI::Client::Authentication::AuthenticationFailed, HaveAPI::Client::ProtocolError,
       RestClient::Exception, JSON::ParserError => error
  warn error.message
end
JavaScript (callback) · Simple
import { CallbackClient } from "haveapi-client";

const api = new CallbackClient("https://api.vpsfree.cz/", {version: "7.0"});

api.authenticate("token", {["user"]: "user",
["password"]: "secret",
["scope"]: "scope",
["lifetime"]: "fixed",
callback: (action, parameters) => {
  const continuations = {["totp"]: {["code"]: "code"}, ["reset_password"]: {["new_password1"]: "new_password1", ["new_password2"]: "new_password2"}};
  if (!Object.prototype.hasOwnProperty.call(continuations, action)) throw new Error("Unknown authentication continuation");
  const input = continuations[action];
  for (const name of Object.keys(parameters)) {
    if (name !== "token" && !Object.prototype.hasOwnProperty.call(input, name)) throw new Error("Unknown authentication input");
  }
  return input;
}}, (api, ready) => {
  if (!ready) {
    console.error("Discovery or authentication failed");
    return;
  }
});
JavaScript (async) · Simple
import { AsyncClient } from "haveapi-client";

const api = new AsyncClient("https://api.vpsfree.cz/", {version: "7.0"});
await api.authenticate("token", {["user"]: "user",
["password"]: "secret",
["scope"]: "scope",
["lifetime"]: "fixed",
onChallenge: (action, parameters) => {
  const continuations = {["totp"]: {["code"]: "code"}, ["reset_password"]: {["new_password1"]: "new_password1", ["new_password2"]: "new_password2"}};
  if (!Object.prototype.hasOwnProperty.call(continuations, action)) throw new Error("Unknown authentication continuation");
  const input = continuations[action];
  for (const name of Object.keys(parameters)) {
    if (name !== "token" && !Object.prototype.hasOwnProperty.call(input, name)) throw new Error("Unknown authentication input");
  }
  return input;
}});
JavaScript (async) · With error handling
import { AsyncClient, AsyncError } from "haveapi-client";

async function main() {
  const api = new AsyncClient("https://api.vpsfree.cz/", {version: "7.0"});
  try {
    await api.authenticate("token", {["user"]: "user",
    ["password"]: "secret",
    ["scope"]: "scope",
    ["lifetime"]: "fixed",
    onChallenge: (action, parameters) => {
      const continuations = {["totp"]: {["code"]: "code"}, ["reset_password"]: {["new_password1"]: "new_password1", ["new_password2"]: "new_password2"}};
      if (!Object.prototype.hasOwnProperty.call(continuations, action)) throw new Error("Unknown authentication continuation");
      const input = continuations[action];
      for (const name of Object.keys(parameters)) {
        if (name !== "token" && !Object.prototype.hasOwnProperty.call(input, name)) throw new Error("Unknown authentication input");
      }
      return input;
    }});
    console.log("Authenticated");
  } catch (error) {
    if (error instanceof AsyncError) {
      console.error(error.kind, error.message, error.errors);
    } else {
      throw error;
    }
  }
}
main().catch(error => console.error(error));
TypeScript (callback) · Simple
import { CallbackClient } from "haveapi-client";

const api = new CallbackClient("https://api.vpsfree.cz/", {version: "7.0"});

api.authenticate("token", {["user"]: "user",
["password"]: "secret",
["scope"]: "scope",
["lifetime"]: "fixed",
callback: (action, parameters) => {
  const continuations: Record<string, Record<string, unknown>> = {["totp"]: {["code"]: "code"}, ["reset_password"]: {["new_password1"]: "new_password1", ["new_password2"]: "new_password2"}};
  if (!Object.prototype.hasOwnProperty.call(continuations, action)) throw new Error("Unknown authentication continuation");
  const input = continuations[action];
  for (const name of Object.keys(parameters)) {
    if (name !== "token" && !Object.prototype.hasOwnProperty.call(input, name)) throw new Error("Unknown authentication input");
  }
  return input;
}}, (api, ready) => {
  if (!ready) {
    console.error("Discovery or authentication failed");
    return;
  }
});
TypeScript (async) · Simple
import { AsyncClient } from "haveapi-client";

const api = new AsyncClient("https://api.vpsfree.cz/", {version: "7.0"});
await api.authenticate("token", {["user"]: "user",
["password"]: "secret",
["scope"]: "scope",
["lifetime"]: "fixed",
onChallenge: (action, parameters) => {
  const continuations: Record<string, Record<string, unknown>> = {["totp"]: {["code"]: "code"}, ["reset_password"]: {["new_password1"]: "new_password1", ["new_password2"]: "new_password2"}};
  if (!Object.prototype.hasOwnProperty.call(continuations, action)) throw new Error("Unknown authentication continuation");
  const input = continuations[action];
  for (const name of Object.keys(parameters)) {
    if (name !== "token" && !Object.prototype.hasOwnProperty.call(input, name)) throw new Error("Unknown authentication input");
  }
  return input;
}});
TypeScript (async) · With error handling
import { AsyncClient, AsyncError } from "haveapi-client";

async function main(): Promise<void> {
  const api = new AsyncClient("https://api.vpsfree.cz/", {version: "7.0"});
  try {
    await api.authenticate("token", {["user"]: "user",
    ["password"]: "secret",
    ["scope"]: "scope",
    ["lifetime"]: "fixed",
    onChallenge: (action, parameters) => {
      const continuations: Record<string, Record<string, unknown>> = {["totp"]: {["code"]: "code"}, ["reset_password"]: {["new_password1"]: "new_password1", ["new_password2"]: "new_password2"}};
      if (!Object.prototype.hasOwnProperty.call(continuations, action)) throw new Error("Unknown authentication continuation");
      const input = continuations[action];
      for (const name of Object.keys(parameters)) {
        if (name !== "token" && !Object.prototype.hasOwnProperty.call(input, name)) throw new Error("Unknown authentication input");
      }
      return input;
    }});
    console.log("Authenticated");
  } catch (error) {
    if (error instanceof AsyncError) {
      console.error(error.kind, error.message, error.errors);
    } else {
      throw error;
    }
  }
}
main().catch(error => console.error(error));
Python (sync) · Simple
from haveapi_client import Client, AuthenticationChallenge

with Client("https://api.vpsfree.cz/", version="7.0") as api:
    continuations = {"totp": {"code": "code"}, "reset_password": {"new_password1": "new_password1", "new_password2": "new_password2"}}
    step = api.begin_token_login({"user": "user", "password": "secret", "scope": "scope", "lifetime": "fixed"})
    while isinstance(step, AuthenticationChallenge):
        if step.next_action not in continuations:
            raise ValueError("Unknown authentication continuation")
        values = continuations[step.next_action]
        if any(name != "token" and name not in values for name in step.input):
            raise ValueError("Unknown authentication input")
        step = step.submit(values)
Python (sync) · With error handling
from haveapi_client import Client, ActionError, HaveAPIError, AuthenticationChallenge

try:
    with Client("https://api.vpsfree.cz/", version="7.0") as api:
        continuations = {"totp": {"code": "code"}, "reset_password": {"new_password1": "new_password1", "new_password2": "new_password2"}}
        step = api.begin_token_login({"user": "user", "password": "secret", "scope": "scope", "lifetime": "fixed"})
        while isinstance(step, AuthenticationChallenge):
            if step.next_action not in continuations:
                raise ValueError("Unknown authentication continuation")
            values = continuations[step.next_action]
            if any(name != "token" and name not in values for name in step.input):
                raise ValueError("Unknown authentication input")
            step = step.submit(values)
        print("Authenticated")
except ActionError as error:
    print(error.message, error.errors)
except HaveAPIError as error:
    print(error.message, error.status_code)
Python (async) · Simple
import asyncio

from haveapi_client import AsyncClient, AsyncAuthenticationChallenge


async def main() -> None:
    async with AsyncClient("https://api.vpsfree.cz/", version="7.0") as api:
        continuations = {"totp": {"code": "code"}, "reset_password": {"new_password1": "new_password1", "new_password2": "new_password2"}}
        step = await api.begin_token_login({"user": "user", "password": "secret", "scope": "scope", "lifetime": "fixed"})
        while isinstance(step, AsyncAuthenticationChallenge):
            if step.next_action not in continuations:
                raise ValueError("Unknown authentication continuation")
            values = continuations[step.next_action]
            if any(name != "token" and name not in values for name in step.input):
                raise ValueError("Unknown authentication input")
            step = await step.submit(values)


asyncio.run(main())
Python (async) · With error handling
import asyncio

from haveapi_client import AsyncClient, ActionError, HaveAPIError, AsyncAuthenticationChallenge


async def main() -> None:
    try:
        async with AsyncClient("https://api.vpsfree.cz/", version="7.0") as api:
            continuations = {"totp": {"code": "code"}, "reset_password": {"new_password1": "new_password1", "new_password2": "new_password2"}}
            step = await api.begin_token_login({"user": "user", "password": "secret", "scope": "scope", "lifetime": "fixed"})
            while isinstance(step, AsyncAuthenticationChallenge):
                if step.next_action not in continuations:
                    raise ValueError("Unknown authentication continuation")
                values = continuations[step.next_action]
                if any(name != "token" and name not in values for name in step.input):
                    raise ValueError("Unknown authentication input")
                step = await step.submit(values)
            print("Authenticated")
    except ActionError as error:
        print(error.message, error.errors)
    except HaveAPIError as error:
        print(error.message, error.status_code)


asyncio.run(main())
Go API client · Simple
// go get github.com/vpsfreecz/vpsadmin-go-client/client@latest
package main

import (
	client "github.com/vpsfreecz/vpsadmin-go-client/client"
)

func main() {
	api := client.New("https://api.vpsfree.cz")
	api.SetExistingTokenAuth("example-token")
	// Use a token obtained through the advertised authentication provider.
}
Rust API client (async) · Simple
// cargo add vpsadmin-client
// cargo add tokio --features macros,rt-multi-thread
// cargo add serde_json
use vpsadmin_client::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api = Client::builder("https://api.vpsfree.cz/")
        .token("example-token")
        .build()?;
    // Configure existing credentials only; building does not validate them with the server.
    let _ = &api;
    Ok(())
}
Rust API client (async) · With error handling
// cargo add vpsadmin-client
// cargo add tokio --features macros,rt-multi-thread
// cargo add serde_json
use vpsadmin_client::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api = match Client::builder("https://api.vpsfree.cz/")
        .token("example-token")
        .build() {
        Ok(api) => api,
        Err(error) => {
            eprintln!("Client configuration failed: {}", error);
            eprintln!("HTTP status: {:?}; timeout: {}", error.http_status(), error.is_timeout());
            return Err(error.into());
        }
    };
    // Configure existing credentials only; building does not validate them with the server.
    let _ = &api;
    Ok(())
}
Rust API client (blocking) · Simple
// cargo add vpsadmin-client --features blocking
// cargo add serde_json
// Construct, use and drop this blocking client outside async runtime threads.
use vpsadmin_client::blocking::Client;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api = Client::builder("https://api.vpsfree.cz/")
        .token("example-token")
        .build()?;
    // Configure existing credentials only; building does not validate them with the server.
    let _ = &api;
    Ok(())
}
Rust API client (blocking) · With error handling
// cargo add vpsadmin-client --features blocking
// cargo add serde_json
// Construct, use and drop this blocking client outside async runtime threads.
use vpsadmin_client::blocking::Client;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api = match Client::builder("https://api.vpsfree.cz/")
        .token("example-token")
        .build() {
        Ok(api) => api,
        Err(error) => {
            eprintln!("Client configuration failed: {}", error);
            eprintln!("HTTP status: {:?}; timeout: {}", error.http_status(), error.is_timeout());
            return Err(error.into());
        }
    };
    // Configure existing credentials only; building does not validate them with the server.
    let _ = &api;
    Ok(())
}
TypeScript API client · Simple
// Configured API client: vpsadmin-typescript-client.
import { AsyncClient } from "haveapi-client";
import { createClient } from "vpsadmin-typescript-client";

async function main(): Promise<void> {
  const runtime = new AsyncClient("https://api.vpsfree.cz/v7.0");
  await runtime.authenticate("token", { token: "example-token" });
  const api = createClient({ execute: spec => runtime.request(spec) });
  void api;
}

main().catch(error => { throw error; });
TypeScript API client · With error handling
// Configured API client: vpsadmin-typescript-client.
import { AsyncClient, AsyncError } from "haveapi-client";
import { createClient } from "vpsadmin-typescript-client";

async function main(): Promise<void> {
  try {
    const runtime = new AsyncClient("https://api.vpsfree.cz/v7.0");
    await runtime.authenticate("token", { token: "example-token" });
    const api = createClient({ execute: spec => runtime.request(spec) });
    void api;
  } catch (error) {
    if (!(error instanceof AsyncError)) throw error;
    console.error(error.kind, error.httpStatus);
    throw error;
  }
}

main().catch(error => { throw error; });
PHP · Simple
$api = new \HaveAPI\Client('https://api.vpsfree.cz/', '7.0');

// Get token using username and password
$api->authenticate('token', [
    'user' => 'user',
    'password' => 'secret',
    'scope' => 'scope',
    'lifetime' => 'fixed',
    'callback' => function ($action, $token, $parameters) {
        $continuations = ['totp' => ['code' => 'code'], 'reset_password' => ['new_password1' => 'new_password1', 'new_password2' => 'new_password2']];
        if (!array_key_exists($action, $continuations)) {
            throw new \InvalidArgumentException('Unknown authentication continuation');
        }
        $input = $continuations[$action];
        foreach (array_keys((array) $parameters) as $name) {
            if ($name !== 'token' && !array_key_exists($name, $input)) {
                throw new \InvalidArgumentException('Unknown authentication input');
            }
        }
        return $input;
    }
]);

// Next time, the client can authenticate using the token directly
$api->authenticate('token', ['token' => 'example-token']);
PHP · With error handling
try {
    $api = new \HaveAPI\Client('https://api.vpsfree.cz/', '7.0');
    $api->setup();

    // Get token using username and password
    $api->authenticate('token', [
        'user' => 'user',
        'password' => 'secret',
        'scope' => 'scope',
        'lifetime' => 'fixed',
        'callback' => function ($action, $token, $parameters) {
            $continuations = ['totp' => ['code' => 'code'], 'reset_password' => ['new_password1' => 'new_password1', 'new_password2' => 'new_password2']];
            if (!array_key_exists($action, $continuations)) {
                throw new \InvalidArgumentException('Unknown authentication continuation');
            }
            $input = $continuations[$action];
            foreach (array_keys((array) $parameters) as $name) {
                if ($name !== 'token' && !array_key_exists($name, $input)) {
                    throw new \InvalidArgumentException('Unknown authentication input');
                }
            }
            return $input;
        }
    ]);

    // Next time, the client can authenticate using the token directly
    $api->authenticate('token', ['token' => 'example-token']);
} catch (\HaveAPI\Client\Exception\ValidationError $error) {
    echo $error->getMessage() . "\n";
    print_r($error->getErrors());
} catch (\HaveAPI\Client\Exception\ActionFailed $error) {
    echo $error->getMessage() . "\n";
    print_r($error->getErrors());
} catch (\HaveAPI\Client\Exception\Base $error) {
    echo $error->getMessage() . "\n";
} catch (\Exception $error) {
    // Dependency failures still propagate to the application.
    echo $error->getMessage() . "\n";
    throw $error;
}
CLI · Simple
# Get token using username and password and save it to disk
# Note that the client always has to call some action. APIs should provide
# an action to get information about the current user, so that's what we're
# calling now.
$ haveapi-cli -u https://api.vpsfree.cz/ --version 7.0 --auth token --user user --scope scope --lifetime fixed --save user current
# Password: secret

# Now the token is read from disk and the user does not have to provide username
# nor password and be authenticated
$ haveapi-cli -u https://api.vpsfree.cz/ --version 7.0 user current
curl · Simple
# Acquire the token
$ curl --request POST \
       --header 'Content-Type: application/json' \
       --data-binary \{\"token\":\{\"user\":\"user\",\"password\":\"secret\",\"scope\":\"scope\",\"lifetime\":\"fixed\"\}\} \
       https://api.vpsfree.cz/_auth/token/tokens

# Use a previously acquired token
$ curl --request OPTIONS \
       --header X-HaveAPI-Auth-Token:\ example-token \
       https://api.vpsfree.cz/
HTTP · Simple
POST /_auth/token/tokens HTTP/1.1
Host: api.vpsfree.cz
Content-Type: application/json

{
  "token": {
    "user": "user",
    "password": "secret",
    "scope": "scope",
    "lifetime": "fixed"
  }
}

Oauth2


OAuth2 authorization provider. HaveAPI clients have limited OAuth2 support, but the API can be used as an authentication source and OAuth2 tokens can be used to access it. HaveAPI partially implements RFC 6749: authorization response type "code" and token grant types "authorization_code" and "refresh_token". Other response and grant types are not supported at this time. The access token can be passed as a bearer token according to RFC 6750, or using a custom HTTP header when the Authorization header is not practical. Access and refresh tokens can be revoked according to RFC 7009.

Examples

Ruby · Simple
# OAuth2 is not supported by HaveAPI Ruby client.
JavaScript (callback) · Simple
// Use an existing access token; this client does not run an OAuth authorization flow.
import { CallbackClient } from "haveapi-client";

const api = new CallbackClient("https://api.vpsfree.cz/", {version: "7.0"});

api.authenticate("oauth2", {access_token: {access_token: "example-access-token"}}, (api, ready) => {
  if (!ready) {
    console.error("Discovery or authentication failed");
    return;
  }
});
JavaScript (async) · Simple
// Use an existing access token; this client does not run an OAuth authorization flow.
import { AsyncClient } from "haveapi-client";

const api = new AsyncClient("https://api.vpsfree.cz/", {version: "7.0"});
await api.authenticate("oauth2", {access_token: {access_token: "example-access-token"}});
JavaScript (async) · With error handling
// Use an existing access token; this client does not run an OAuth authorization flow.
import { AsyncClient, AsyncError } from "haveapi-client";

async function main() {
  const api = new AsyncClient("https://api.vpsfree.cz/", {version: "7.0"});
  try {
    await api.authenticate("oauth2", {access_token: {access_token: "example-access-token"}});
    console.log("Authenticated");
  } catch (error) {
    if (error instanceof AsyncError) {
      console.error(error.kind, error.message, error.errors);
    } else {
      throw error;
    }
  }
}
main().catch(error => console.error(error));
TypeScript (callback) · Simple
// Use an existing access token; this client does not run an OAuth authorization flow.
import { CallbackClient } from "haveapi-client";

const api = new CallbackClient("https://api.vpsfree.cz/", {version: "7.0"});

api.authenticate("oauth2", {access_token: {access_token: "example-access-token"}}, (api, ready) => {
  if (!ready) {
    console.error("Discovery or authentication failed");
    return;
  }
});
TypeScript (async) · Simple
// Use an existing access token; this client does not run an OAuth authorization flow.
import { AsyncClient } from "haveapi-client";

const api = new AsyncClient("https://api.vpsfree.cz/", {version: "7.0"});
await api.authenticate("oauth2", {access_token: {access_token: "example-access-token"}});
TypeScript (async) · With error handling
// Use an existing access token; this client does not run an OAuth authorization flow.
import { AsyncClient, AsyncError } from "haveapi-client";

async function main(): Promise<void> {
  const api = new AsyncClient("https://api.vpsfree.cz/", {version: "7.0"});
  try {
    await api.authenticate("oauth2", {access_token: {access_token: "example-access-token"}});
    console.log("Authenticated");
  } catch (error) {
    if (error instanceof AsyncError) {
      console.error(error.kind, error.message, error.errors);
    } else {
      throw error;
    }
  }
}
main().catch(error => console.error(error));
Python (sync) · Simple
# Use an existing access token; OAuth acquisition and refresh are outside this client.
from haveapi_client import Client, OAuth2Auth

with Client("https://api.vpsfree.cz/", version="7.0", auth=OAuth2Auth("example-access-token")) as api:
    # Call API actions inside this block.
    pass
Python (sync) · With error handling
# Use an existing access token; OAuth acquisition and refresh are outside this client.
from haveapi_client import Client, ActionError, HaveAPIError, OAuth2Auth

try:
    with Client("https://api.vpsfree.cz/", version="7.0", auth=OAuth2Auth("example-access-token")) as api:
        print("Authenticated")
except ActionError as error:
    print(error.message, error.errors)
except HaveAPIError as error:
    print(error.message, error.status_code)
Python (async) · Simple
# Use an existing access token; OAuth acquisition and refresh are outside this client.
import asyncio

from haveapi_client import AsyncClient, OAuth2Auth


async def main() -> None:
    async with AsyncClient("https://api.vpsfree.cz/", version="7.0", auth=OAuth2Auth("example-access-token")) as api:
        # Call API actions inside this block.
        pass


asyncio.run(main())
Python (async) · With error handling
# Use an existing access token; OAuth acquisition and refresh are outside this client.
import asyncio

from haveapi_client import AsyncClient, ActionError, HaveAPIError, OAuth2Auth


async def main() -> None:
    try:
        async with AsyncClient("https://api.vpsfree.cz/", version="7.0", auth=OAuth2Auth("example-access-token")) as api:
            print("Authenticated")
    except ActionError as error:
        print(error.message, error.errors)
    except HaveAPIError as error:
        print(error.message, error.status_code)


asyncio.run(main())
Go API client · Simple
// go get github.com/vpsfreecz/vpsadmin-go-client/client@latest
package main

import (
	client "github.com/vpsfreecz/vpsadmin-go-client/client"
)

func main() {
	api := client.New("https://api.vpsfree.cz")
	api.SetExistingOAuth2Auth("example-access-token")
	// Obtain the access token through the OAuth2 provider before running this program.
}
Rust API client (async) · Simple
// cargo add vpsadmin-client
// cargo add tokio --features macros,rt-multi-thread
// cargo add serde_json
use vpsadmin_client::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api = Client::builder("https://api.vpsfree.cz/")
        .oauth2_token("example-access-token")
        .build()?;
    // Configure existing credentials only; building does not validate them with the server.
    let _ = &api;
    Ok(())
}
Rust API client (async) · With error handling
// cargo add vpsadmin-client
// cargo add tokio --features macros,rt-multi-thread
// cargo add serde_json
use vpsadmin_client::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api = match Client::builder("https://api.vpsfree.cz/")
        .oauth2_token("example-access-token")
        .build() {
        Ok(api) => api,
        Err(error) => {
            eprintln!("Client configuration failed: {}", error);
            eprintln!("HTTP status: {:?}; timeout: {}", error.http_status(), error.is_timeout());
            return Err(error.into());
        }
    };
    // Configure existing credentials only; building does not validate them with the server.
    let _ = &api;
    Ok(())
}
Rust API client (blocking) · Simple
// cargo add vpsadmin-client --features blocking
// cargo add serde_json
// Construct, use and drop this blocking client outside async runtime threads.
use vpsadmin_client::blocking::Client;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api = Client::builder("https://api.vpsfree.cz/")
        .oauth2_token("example-access-token")
        .build()?;
    // Configure existing credentials only; building does not validate them with the server.
    let _ = &api;
    Ok(())
}
Rust API client (blocking) · With error handling
// cargo add vpsadmin-client --features blocking
// cargo add serde_json
// Construct, use and drop this blocking client outside async runtime threads.
use vpsadmin_client::blocking::Client;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api = match Client::builder("https://api.vpsfree.cz/")
        .oauth2_token("example-access-token")
        .build() {
        Ok(api) => api,
        Err(error) => {
            eprintln!("Client configuration failed: {}", error);
            eprintln!("HTTP status: {:?}; timeout: {}", error.http_status(), error.is_timeout());
            return Err(error.into());
        }
    };
    // Configure existing credentials only; building does not validate them with the server.
    let _ = &api;
    Ok(())
}
TypeScript API client · Simple

This sample is unavailable or incompatible with the configured TypeScript API client.

PHP · Simple
// OAuth2 requires session
session_start();

// Client instance
$api = new \HaveAPI\Client('https://api.vpsfree.cz/', '7.0');

// Check if we already have an access token
if (isset($_SESSION['access_token'])) {
    // We're already authenticated, reuse the existing access token
    $api->authenticate('oauth2', ['access_token' => $_SESSION['access_token']]);
} else {
    // Follow the OAuth2 authorization process to get an access token using
    // authorization code
    $api->authenticate('oauth2', [
        // Client id and secret are given by the API server
        'client_id' => 'example-client',
        'client_secret' => 'example-client-secret',

        // This example code should run on the URL below
        'redirect_uri' => 'https://your-client.tld/oauth2-callback',

        // Scopes are specific to the API implementation
        'scope' => 'all',
    ]);

    $provider = $api->getAuthenticationProvider();

    // We don't have authorization code yet, request one
    if (!isset($_GET['code'])) {
        // Redirect the user to the authorization endpoint
        $provider->requestAuthorizationCode();
        exit;
    } else {
        // Request access token using the token endpoint
        $provider->requestAccessToken();

        // Store the access token in the session
        $_SESSION['access_token'] = $provider->jsonSerialize();
    }
}
PHP · With error handling
try {
    // OAuth2 requires session
    session_start();

    // Client instance
    $api = new \HaveAPI\Client('https://api.vpsfree.cz/', '7.0');
    $api->setup();

    // Check if we already have an access token
    if (isset($_SESSION['access_token'])) {
        // We're already authenticated, reuse the existing access token
        $api->authenticate('oauth2', ['access_token' => $_SESSION['access_token']]);
    } else {
        // Follow the OAuth2 authorization process to get an access token using
        // authorization code
        $api->authenticate('oauth2', [
            // Client id and secret are given by the API server
            'client_id' => 'example-client',
            'client_secret' => 'example-client-secret',

            // This example code should run on the URL below
            'redirect_uri' => 'https://your-client.tld/oauth2-callback',

            // Scopes are specific to the API implementation
            'scope' => 'all',
        ]);

        $provider = $api->getAuthenticationProvider();

        // We don't have authorization code yet, request one
        if (!isset($_GET['code'])) {
            // Redirect the user to the authorization endpoint
            $provider->requestAuthorizationCode();
            exit;
        } else {
            // Request access token using the token endpoint
            $provider->requestAccessToken();

            // Store the access token in the session
            $_SESSION['access_token'] = $provider->jsonSerialize();
        }
    }
} catch (\HaveAPI\Client\Exception\ValidationError $error) {
    echo $error->getMessage() . "\n";
    print_r($error->getErrors());
} catch (\HaveAPI\Client\Exception\ActionFailed $error) {
    echo $error->getMessage() . "\n";
    print_r($error->getErrors());
} catch (\HaveAPI\Client\Exception\Base $error) {
    echo $error->getMessage() . "\n";
} catch (\Exception $error) {
    // Dependency failures still propagate to the application.
    echo $error->getMessage() . "\n";
    throw $error;
}
CLI · Simple
# OAuth2 is not supported by HaveAPI Ruby CLI.
curl · Simple
# See RFC 6749 for authorization process and RFC 6750 for access token usage.
HTTP · Simple
# 1) Request authorization code
GET /_auth/oauth2/authorize?response_type=code&client_id=example-client&state=example-state&redirect_uri=https%3A%2F%2Fexample.org%2Fcallback HTTP/1.1
Host: api.vpsfree.cz

# 2) The user logs in using this API

# 3) The API then redirects the user back to the client application
GET /callback?code=example-code&state=example-state
Host: client-application

# 4) The client application requests access token
POST /_auth/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=example-code&redirect_uri=https%3A%2F%2Fexample.org%2Fcallback&client_id=example-client&client_secret=example-client-secret