Skip to content

Using the VALDI API

A public API is accessible to VALDI customers that enables programmatic provisioning, management, and termination of Virtual Machines.

Authentication

VALDI's API is authenticated with JSON Web Tokens (JWT). The team is in the process of implementing support for API keys, which when complete, will replace the authentication method described here.

Log in

First, log in and obtain a refresh token and access token. This is the programmatic equivalent to logging in to the VALDI dashboard at valdi.ai.

POST  https://api.valdi.ai/account/login

You must include the following payload:

{
  "email": "your.account.email@youremailprovider.com",
  "password": "your_password"
}

An example 200 OK response is:

{
    "access_token": "eyJhbGciOiJiUZI1NiIsInr5cCI6IkpXVCJ9.eyJkYXRhIjP7InVzZXJfaWQiOjgsImNyZWF0aW9uX3RpbWUiOiIymdIzLTEyLTA0IDIzOjU0OjU5LjczMzUwOCJ9LCJwdXJwb3NlIjoiYWNjZXNzX3Rva2VuIiwiZXhwIjoyMDIzMTIwNDIzNTk1Ox0.gTBdAOE1_SdAB7BHeUkOUiZfiiyJJBSJ89_ojRS7oFw",
    "token_type": "Bearer",
    "refresh_token": "eyjhbGciOiJIUzI1NiIsInR5cCI6IkpXVCj9.eyJkyxRhIjp7InVzZXJfawqiOjgsImNyZWF0aW9uX3RpbWUiOiIyMDIzLTEyLTA0IDIzOjU0OjU5LjczMzUwOCJ9LCJwdXJwb3NlIjoicmVmcmVzaC10b2tlbiIsimv4ccI6MjAyNDAxMDMyMzU0NTl9.g8uQyhC7yypj0jQPSK3LmS5MOYs90fD_k7NyfnYhi1m"
}

The access_token is what you will use to authenticate when calling other APIs. The access token expires every 5 minutes. (This is why we are implementing API keys.)

Refresh access token

To obtain a new access token, use the refresh_token from the /account/login call as follows.

POST https://api.valdi.ai/account/refresh_token

You must include the following payload:

{
  "token": "your_refresh_token"
}

An example 200 OK response is:

{
    "access_token": "your_new_access_token",
    "token_type": "Bearer"
}

Virtual Machines (VM)

Fetch available devices

To see the list of available VALDI devices and configurations across all of our different providers, use the following API call.

GET https://api.valdi.ai/v1/devices/available

This endpoint requires authentication. To authenticate, include the following header in the call:

'Authorization: Bearer {your_access_token}'

An example 200 OK response is:

{
  "devices_by_provider": [
    {
      "provider_id": "a45088e0-1681-446e-9a3e-3ed9dfc3d57e",
      "provider_devices": [
        {
          "flavor_id": "94d76997-44ec-4f1e-8291-231de42b6030",
          "gpu_type": "RTX A6000 48GB",
          "cpu_core_count": 6,
          "main_ram": 55,
          "storage": 500,
          "gpu_count": 1,
          "running_cost": "0.660000000000",
          "stopped_cost": "0.100000000000"
        },
        {
          "flavor_id": "b5917017-7ca4-403e-b08b-ba5cc31c7d2a",
          "gpu_type": "RTX A6000 48GB",
          "cpu_core_count": 12,
          "main_ram": 110,
          "storage": 1000,
          "gpu_count": 2,
          "running_cost": "1.320000000000",
          "stopped_cost": "0.200000000000"
        }
      ]
    },
    {
      "provider_id": "66730e5d-98d2-45f6-8aaa-6ad8cdcbc285",
      "provider_devices": [
        {
          "cpu_type": "AMD EPYC 7713P",
          "cpu_core_count": 128,
          "main_ram": 185,
          "gpu_enabled": true,
          "gpu_ram": 80,
          "gpu_type": "A100 80GB",
          "gpu_code": "a100-pcie-80gb",
          "gpu_count": 2,
          "location": "Exmouth, Devon, United Kingdom",
          "storage": 300,
          "hostnode": "b2ce5479-fa59-483f-86ba-0aa128051821",
          "available_port": [
            21299,
            21298,
            21297,
            21296,
            21295,
            21294
          ],
          "cpu_cost": 0.0035,
          "ram_cost": 0.0025,
          "storage_cost": 0.0002,
          "gpu_cost": "2.044000000000000",
          "upload_bw": 1000.0,
          "download_bw": 1000.0
        }
      ]
    }
  ]
}

Generate an SSH key

Some VALDI servers require SSH key authentication, while others require password authentication. This is a consequence of the requirements and configurations implemented by the actual host of the server.

For security purposes, and in line with best practices of major hyperscalers, VALDI does not allow externally generated SSH keys to be used for provisioning a VM.

NOTE: It is generally easier and faster to generate your SSH keys through the dashboard at valdi.ai.

To generate an SSH key, use the following endpoint.

POST https://api.valdi.ai/sshkeys/sshkey

This endpoint requires authentication. To authenticate, include the following header in the call:

'Authorization: Bearer {your_access_token}'

The format of the payload is very simple:

{
  "name": "whatever-you-want-to-name-the-key"
}

An example 201 Created response is:

{
  "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIJKAIBAAKCAgEAvVslMAKcIKk4blv182E2Fh7oJOzvOfzgoenual92VvOG6WPB\n30SHs4+MXBf17Nei+PRUsZ4aYGodt1GIjz3sX/nUdLEdN1oIEYIEqZuMSD899LAh\nme9wBRqydbhhYJOTksbufAkBJNjJT9QkZDArVpvMQ1hqOwCRqpBMY4QsYwxdK3wN\nYr/moffJEXiHvY3XnpaIAPfX+KzO/vp7N01K3L5mugQDisgxXlk7TQn3Py3fJkiD...",
  "ssh_key_id": "your-new-ssh-key-uuid"
}

Please save both the private key and the SSH key ID. This is the only time you will be able to retrieve the private key, and the SSH key ID is needed to provision VMs that require SSH key authentication.

Remove new lines from private key

After copying and pasting the private key into a plain text file, you will need to manually remove new line characters and replace them with actual new lines. One way to do this is by opening the file in vim (sorry emacs fans), entering command mode by pressing :, and then running the following command:

:%s/\\n/\r/g

If you generate the SSH key in the dashboard, you don't have to deal with this. :)

Modify permissions of private key

The private key file should have the following permissions, or ssh may refuse to connect you.

-rw-------

To assign such permissions, use the following command:

chmod 600 {private_key_filename}

Get SSH Keys

To get a list of the SSH keys under your account, use the following authenticated API.

GET https://api.valdi.ai/sshkeys

An example 200 OK response is as follows.

{
  "ssh_keys": [
    {
      "name": "api-docs-key",
      "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC9WyUwApwgqThuW/XzYTYWHugk7O85/OCh6e5qX3ZW84bpY8HfRIezj4xcF/Xs16L49FSxnhpgah23UYiPPexf+dR0sR03WggRggSpm4xIPz30sCGZ73AFGrJ1uGFgk5OSxu58CQEk2MlP1CRkMCtWm8xDWGo7AJGqkExjhCxjDF0rfA1iv+ah98kReIe9jdeelogA99f4rM7++ns3TUrcvma6BAOKyDFeWTtNCfc/Ld8mSIPWCyxC+D3bmrIOm7re87oW01lanp7SSk1xU3P3hXNBsZRf1SkCjNXJIWEq3xp5WJDQYL4yy+J0FnahZC6o6LxeCkc/fEWfTV7yC4Cp7lBstCn9fiZyh2YAnFJd5FjD1JNThiWTw7KUB8qePbhZdxPfNJhMt3qRknMj2wRM6aDAQ68OSKMjUvJjDoJnr3jmlo4ZVvpcU2qRO73vJdrJDtwTCRUheDTXrSd0091JrQGN7qEsjj8BtC4NsPMuQpNJpUAVvCftBgjTD3OH892Ey8geDctLgI8HXoGhkIZNuRsmdL4SmWeH2nyWKRtnKpjiMTUi32Y6KV+Fs7ttvJZ5nG8x+SZ+4G2XfkeFXp/tRypiU7bYnYm5AQINXhSloaHsG/sztCaWyettQje5khNmnrHT/29XQB8vfcSHI3nnY/xkA9I5SN+fB2Vxcav69w==",
      "ssh_key_id": "02a18443-93d1-4c86-92f9-65f90d129a74",
      "created_at": "2023-12-12T23:13:54.285477"
    },
    {
      "name": "valdi-test-key",
      "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCXPGUW6PkZjDtOjNf4o9mqtkTTl2w2UCLelcsVDXS2Hh/pS28D6Jyq9JFeLxgusvJrcMA+xUfW7Jc5PiWlvsSzkiaHHDd+Qp38TluxXPiCLz/grLURC6jwQt39z3DMh4Yqrc3ybUdVr8ScD54h6dEw/OtDchdgqmjkdAWTCdlGxmpdw4lPPFuR0MoTVR9ebbwtKxlB2eXk6+voNIYykLdlVxia71xpuVdaBBSI2c59fDK7KsGqkQw7xv31gE3RKc3Z663ieOB3sSClU9FFaixBplrqa2kU8Cb3c5zcmM7VXQiR2rVKSvIdFgIbHdIaEnSn0D9vauNxhJMsONxbVSY2+a6zx+tJ4FR25qsBWkCUwxe2vlMVeoR4kppk11XPiVQBVWPI+Pkygzh0PhrpCqrPz30m9Ue7Oug5SueCefJtrb3GBId2sCuAhiVxQETvUG0873D/TpMI+4mL4tmsNb/RgrxE7kAOAji+bJUaYORmLbJuY98VRJlECJsKHUn52VX9HpA2Vnpfo1RNcnUnMBUzDmh1kqBzzi8mx3c0xL/JQozqtNVuwDg9dAy79CNdU6+nwQdAqvYLU11v68x1i8XssA8b+rRJWzZ2W7QBXssIyPPvsvP1F8Na+8yBam9+XO1nyjL4i4XzmMCcddJJ/edb1xk0Lbrehh5J1LWTPHXVWQ==",
      "ssh_key_id": "708bffd3-bce7-4806-aa55-cbaa9a3740b9",
      "created_at": "2023-11-30T22:57:53.425409"
    }
  ]
}

Notice that the private keys are not returned. VALDI does not store your private key, so you need to make sure to save it when you first create it.

Provision a VM

POST https://api.valdi.ai/v1/vm/provision

This endpoint requires authentication. To authenticate, include the following header in the call:

'Authorization: Bearer {your_access_token}'

The format of the payload is as follows:

{
  "provider_id": "provider_id_from_available_devices_api",
  "name": "whatever-name-you-want",
  "details": PROVIDER-SPECIFIC OBJECT (SEE BELOW)
}

As noted in the above, the format of the details object varies depending on the provider.

Provider ID a45088e0

An example details object for this provider is shown below.

{
  "flavor_id": "94d76997-44ec-4f1e-8291-231de42b6030",
  "ssh_key_id": "02a18443-93d1-4c86-92f9-65f90d129a74"
}

The definitions of the two fields are:

  • flavor_id: The UUID of the desired server configuration as returned by GET /v1/devices/available
  • ssh_key_id: The UUID of the SSH key you would like to use to access this machine

A full example payload for provider ID a45088e0-1681-446e-9a3e-3ed9dfc3d57e is as follows.

{
  "provider_id": "a45088e0-1681-446e-9a3e-3ed9dfc3d57e",
  "name": "whatever-name-you-want",
  "details": {
    "flavor_id": "94d76997-44ec-4f1e-8291-231de42b6030",
    "ssh_key_id": "02a18443-93d1-4c86-92f9-65f90d129a74"
  }
}

These VMs have ports 80, 443, and 22 open by default. Other ports can be configured using ufw once logged in.

Provider ID 66730e5d

An example details object for this provider is shown below.

{
  "gpu_model": "a100-pcie-80gb",
  "operating_system": "Ubuntu 20.04 LTS",
  "external_ports": "{21299}",
  "internal_ports": "{22}",
  "gpu_count": 1,
  "password": "your-desired-password-to-access-the-vm",
  "hostnode": "b2ce5479-fa59-483f-86ba-0aa128051821",
  "storage": 256,
  "vcpus": 64,
  "ram": 128
}

The definitions of the various fields are:

  • gpu_model: The desired GPU model as returned by GET /v1/devices/available under gpu_code
  • operating_system: One of the following:
    • Ubuntu 20.04 LTS: Vanilla image of Ubuntu 20.04 LTS (min. 20 GB storage req'd)
    • Ubuntu 22.04 LTS: Vanilla image of Ubuntu 22.04 LTS (min. 20 GB storage req'd)
    • TensorML 20 TensorFlow: Ubuntu 20.04 with TensorFlow and Jupyter (min. 40 GB storage req'd)
    • TensorML 20 PyTorch: Ubuntu 20.04 with PyTorch and Jupyter (min. 40 GB storage req'd)
    • TensorML 20 Everything: Ubuntu 20.04 with TensorFlow, PyTorch, MxNet, and Jupyter (min. 60 GB storage req'd)
  • external_ports: A list of external ports you want to be exposed (e.g., {21297, 21298, 21299})
  • internal_ports: A list of corresponding internal ports to which the external ports will map (.e.g, {22, 80, 443})
    • This would map 21297 to 22, 21298 to 80, and 21299 to 443
  • gpu_count: The number of GPUs you want to attach to the VM
  • password: Your desired password
  • hostnode: The UUID of the hostnode as returned by GET /v1/devices/available
  • storage: The desired amount of storage in GB
  • vcpus: The desired number of vCPUs
  • ram: The desired amount of RAM in GB

A full example payload for provider ID 66730e5d-98d2-45f6-8aaa-6ad8cdcbc285 is as follows.

{
  "provider_id": "66730e5d-98d2-45f6-8aaa-6ad8cdcbc285",
  "name": "whatever-name-you-want",
  "details": {
    "gpu_model": "a100-pcie-80gb",
    "operating_system": "Ubuntu 20.04 LTS",
    "external_ports": "{21297, 21298, 21299}",
    "internal_ports": "{22, 80, 443}",
    "gpu_count": 1,
    "password": "your-desired-password-to-access-the-vm",
    "hostnode": "b2ce5479-fa59-483f-86ba-0aa128051821",
    "storage": 256,
    "vcpus": 64,
    "ram": 128
  }
}

This request is comparatively complex because this provider's VM specifications and networking are configurable.

NOTE: Virtual machines can take up to 15 minutes to provision, especially for large RAM deployments. If you are getting a "Connection refused" error from ssh, it is best to wait a bit longer and try again.

Get VM status

You can retrieve the full list of your virtual machines with the following authenticated call.

GET https://api.valdi.ai/v1/vm

An example 200 OK response is:

{
  "virtual_machines": [
    {
      "server": "5bebf874-05d9-49d7-a45f-801a702ac27c",
      "ip": "2a0b:d40:0:4c::1",
      "provider_id": "a45088e0-1681-446e-9a3e-3ed9dfc3d57e",
      "ssh_key_id": "02a18443-93d1-4c86-92f9-65f90d129a74",
      "name": "valdi-customer-Vlj!%k",
      "user_provided_name": "api-docs-test",
      "gpu_count": 1,
      "gpu_model": "RTXA6000.1GPU",
      "pretty_gpu_name": "RTX A6000 48GB",
      "vcpus": 6,
      "ram": 55,
      "storage": 500,
      "operating_system": "Ubuntu 20.04 LTS",
      "port_forwards": "{\"22\": \"22\", \"443\": \"443\", \"80\": \"80\"}",
      "all_inclusive": true,
      "cpu_cost": null,
      "ram_cost": null,
      "storage_cost": null,
      "gpu_cost": null,
      "all_inclusive_running_cost": "0.830000000000",
      "all_inclusive_stopped_cost": "0.130000000000",
      "last_stopped_time": null,
      "last_restarted_time": null,
      "created_at": "2023-12-12T23:41:05.232767",
      "status": "running"
    },
    {
      "server": "52703e5e-347a-47af-bdf4-1ac8fbb9942e",
      "ip": "217.79.242.232",
      "provider_id": "66730e5d-98d2-45f6-8aaa-6ad8cdcbc285",
      "ssh_key_id": null,
      "name": "valdi-customer-li03lg",
      "user_provided_name": "api-docs-test",
      "gpu_count": 1,
      "gpu_model": "v100-pcie-16gb",
      "pretty_gpu_name": "V100 16GB",
      "vcpus": 2,
      "ram": 4,
      "storage": 20,
      "operating_system": "Ubuntu 20.04 LTS",
      "port_forwards": "{\"60000\": \"22\"}",
      "all_inclusive": false,
      "cpu_cost": "0.003500000000",
      "ram_cost": "0.002500000000",
      "storage_cost": "0.000100000000",
      "gpu_cost": "0.292000000000",
      "all_inclusive_running_cost": null,
      "all_inclusive_stopped_cost": null,
      "last_stopped_time": null,
      "last_restarted_time": null,
      "created_at": "2023-12-12T23:40:28.217619",
      "status": "running"
    }
  ]
}

Note that different fields are null depending on the provider.

You can get the status of specific VMs by appending the VM ID to the path of the GET call. For example, GET /v1/vm/52703e5e-347a-47af-bdf4-1ac8fbb9942e would return only the second entry in the list above.

Stop a VM

To stop (i.e., temporarily turn off) your VM but retain your locally stored data, use the following authenticated endpoint.

POST https://api.valdi.ai/v1/vm/stop/{server_id}

Upon success, you will get the following 200 OK response:

{
    "message": "success"
}

For VMs from Provider ID a45088e0, the cost of the VM while stopped will be 13-16% of the cost while running. Your data will be retained, and you can restart the VM at any time.

For VMs from Provider ID 66730e5d, you will only pay for the amount of storage you assigned to the VM. Your data will be retained, but you are not guaranteed to be able to restart the VM at any time. (If all GPUs attached to your physical server are rented out while your VM is stopped, you will have to wait until at least one GPU becomes available again.)

Start a VM

To start a VM that had been stopped, use the following authenticated endpoint.

POST https://api.valdi.ai/v1/vm/start/{server_id}

Upon success, you will get the following 200 OK response:

{
  "message": "success"
}

It may take a few minutes for your VM to come online and be accessible again.

Terminate a VM

To permanently delete a VM, use the following command. The VM can be either in a running or stopped state.

POST https://api.valdi.ai/v1/vm/destroy/{server_id}

Upon success, you will get the following 200 OK response:

{
  "message": "success"
}