API reference
This page covers the Spheron AI REST API for programmatic access to GPU instances, SSH keys, volumes, and account balance.
Table of contents
- Quick start
- Authentication
- Endpoints
- Error reference
- Status values
- Rate limits
- Security
- Common workflows
Quick start
1. Get your API key
Generate an API key from your Spheron dashboard.
2. Make your first API call
Test your connection by listing available providers:
curl -H "Authorization: Bearer <your-api-key>" \
https://app.spheron.ai/api/providers3. List available GPUs
curl -H "Authorization: Bearer <your-api-key>" \
"https://app.spheron.ai/api/gpu-offers?limit=5"4. Deploy your first instance
curl -X POST "https://app.spheron.ai/api/deployments" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
-d '{
"provider": "spheron-ai",
"offerId": "rtx-4090-spheron-ai-1",
"gpuType": "rtx-4090",
"gpuCount": 1,
"region": "us-east-1",
"operatingSystem": "ubuntu-22.04",
"instanceType": "DEDICATED",
"sshKeyId": "your_ssh_key_id"
}'Base URL
https://app.spheron.aiAuthentication
Include your API key in the Authorization header for all authenticated requests:
Authorization: Bearer <your-api-key>Security note: Treat API keys like passwords. Never expose them in client-side code or public repositories. See Security best practices for more information.
Endpoints
Get providers
Get a list of all available GPU providers (public endpoint). Returns the subset of providers currently configured on the server.
Method: GET
Path: /api/providers
[
"data-crunch",
"massed-compute",
"sesterce",
"spheron-ai",
"voltage-park"
]Get GPU offers
Get available GPU offers with filtering and pagination. Authenticate to see team discounts.
Method: GET
Path: /api/gpu-offers
Authorization: Bearer<your-api-key>(optional)
| Name | Type | Required | Description |
|---|---|---|---|
page | number | No | Page number (default: 1) |
limit | number | No | Items per page (default: 10) |
search | string | No | Search term for GPU models |
sortBy | string | No | Sort field (default: popularity) |
sortOrder | string | No | asc or desc (default: asc) |
instanceType | string | No | Filter by type: 'SPOT', 'DEDICATED', or 'BARE_METAL' (case-insensitive) |
{
"data": [
{
"gpuType": "rtx-4090",
"gpuModel": "RTX 4090",
"baseGpuType": "rtx-4090",
"interconnectVariants": ["PCIe"],
"hasMultipleVariants": false,
"displayName": "RTX 4090",
"popularity": 85,
"totalAvailable": 12,
"lowestPrice": 0.45,
"highestPrice": 0.65,
"averagePrice": 0.55,
"providers": ["spheron-ai", "voltage-park"],
"offers": [
{
"provider": "spheron-ai",
"offerId": "rtx-4090-spheron-ai-1-dedicated",
"name": "RTX 4090",
"description": "High-performance gaming and AI GPU",
"vcpus": 8,
"memory": 32,
"storage": 100,
"gpuCount": 1,
"price": 0.50,
"available": true,
"clusters": ["us-east-1", "us-west-2"],
"region": "us-east-1",
"gpu_memory": 24,
"os_options": ["ubuntu-20.04", "ubuntu-22.04"],
"maintenance": false,
"interconnectType": "PCIe",
"interconnectDescription": "PCIe interface",
"instanceType": "DEDICATED",
"supportsCloudInit": true,
"extras": {
"deployment_type": "vm",
"networking_type": "standard"
}
},
{
"provider": "data-crunch",
"offerId": "rtx-4090-datacrunch-1-spot",
"name": "RTX 4090 Spot",
"description": "Cost-effective Spot instance (lower price, may be interrupted)",
"vcpus": 8,
"memory": 32,
"storage": 100,
"gpuCount": 1,
"price": 0.25,
"spot_price": 0.25,
"available": true,
"clusters": ["us-east-1", "eu-west-1"],
"region": "us-east-1",
"gpu_memory": 24,
"os_options": ["ubuntu-20.04", "ubuntu-22.04"],
"maintenance": false,
"interconnectType": "PCIe",
"interconnectDescription": "PCIe interface",
"instanceType": "SPOT",
"supportsCloudInit": true,
"extras": {
"deployment_type": "vm",
"networking_type": "standard"
},
"note": "For Spot instances: price = spot_price (discounted rate with possible interruption)"
},
{
"provider": "voltage-park",
"offerId": "baremetal_h100_8_ethernet",
"name": "H100 8x GPU Bare Metal (Ethernet)",
"description": "8x H100 GPUs, 832 vCPUs, 8192GB RAM, 144000GB Storage. Bare Metal with 100 Gbps Ethernet networking.",
"vcpus": 832,
"memory": 8192,
"storage": 144000,
"gpuCount": 8,
"price": 15.84,
"available": true,
"clusters": ["dalas-united states"],
"region": "dalas-united states",
"gpu_memory": 80,
"os_options": ["Ubuntu 20.04 LTS", "Ubuntu 22.04 LTS"],
"maintenance": false,
"interconnectType": "NVLink",
"interconnectDescription": "NVLink high-speed GPU interconnect",
"instanceType": "CLUSTER",
"supportsCloudInit": true,
"extras": {
"deployment_type": "cluster",
"networking_type": "ethernet",
"kubernetes_addon": {
"available": true,
"total_cost_per_hour": 0.384
}
},
"note": "Bare-metal offers may include kubernetes_addon in extras showing addon availability and cost per hour (with commission included)"
}
]
}
],
"total": 50,
"page": 1,
"limit": 10,
"totalPages": 5
}Deployments
Create deployment
Create a new GPU instance deployment. Optionally add a Kubernetes cluster for Voltage Park bare-metal instances.
Method: POST
Path: /api/deployments
Authorization: Bearer<your-api-key>Content-Type: application/json
| Name | Type | Required | Description |
|---|---|---|---|
provider | string | Yes | Provider name (e.g., voltage-park, data-crunch, massed-compute, sesterce, spheron-ai). Call GET /api/providers for the live list of configured providers. |
offerId | string | Yes | Unique offer ID from the GPU offers endpoint |
gpuType | string | Yes | GPU type identifier (e.g., rtx-4090, h100) |
gpuCount | number | Yes | Number of GPUs to deploy |
region | string | Yes | Deployment region/cluster |
operatingSystem | string | Yes | Operating system (e.g., ubuntu-20.04, ubuntu-22.04) |
instanceType | string | Yes | Instance type: 'SPOT', 'DEDICATED', or 'CLUSTER' (case-insensitive) |
sshKeyId | string | No | SSH key ID from your saved keys (either this or ssh_public_key required) |
ssh_public_key | string | No | Inline SSH public key content (either this or sshKeyId required). A temporary key will be created. |
teamId | string | No | Team ID for team deployments (optional) |
name | string | No | Optional name for the deployment |
cloudInit | object | No | Cloud-Init configuration object. Supports fields: runcmd (string[]), packages (string[]), writeFiles (array of objects with path, content, owner, permissions). |
kubernetesAddon | object | No | Kubernetes add-on configuration (Voltage Park bare-metal only). Object with 'version' (string, e.g., '1.35') and optional 'authentication_config_b64' (base64-encoded Kubernetes AuthenticationConfiguration YAML). Additional hourly cost applies per GPU. |
volumeIds | string[] | No | IDs of persistent volumes to attach at launch. Each volume must match the deployment's provider and region. See Volume attachment rules for per-provider limits. |
{
"provider": "spheron-ai",
"offerId": "rtx-4090-spheron-ai-1",
"gpuType": "rtx-4090",
"gpuCount": 1,
"region": "us-east-1",
"operatingSystem": "ubuntu-20.04",
"instanceType": "DEDICATED",
"sshKeyId": "ssh_key_id_here",
"teamId": "team_id_optional",
"name": "My GPU Instance",
"note": "Alternatively, use 'ssh_public_key' instead of 'sshKeyId' to create a temporary SSH key",
"cloudInit": {
"runcmd": [
"echo 'Hello from cloud-init'",
"apt-get update"
],
"packages": ["curl", "git"],
"writeFiles": [
{
"path": "/etc/motd",
"content": "Welcome to your instance!",
"owner": "root:root",
"permissions": "0644"
}
]
},
"kubernetesAddon": {
"version": "1.35",
"authentication_config_b64": "YXBpVmVyc2lvbjogYXBpc2VydmVyLmNvbmZpZy5rOHMuaW8vdjFiZXRhMQpraW5kOiBBdXRoZW50aWNhdGlvbkNvbmZpZ3VyYXRpb24Kand0OiBbXQ==",
"note": "Optional - only for Voltage Park CLUSTER instances. authentication_config_b64 is optional. Additional hourly cost applies."
},
"volumeIds": ["vol_abc123"]
}{
"id": "deployment_id",
"name": "My GPU Instance",
"userId": "user_id",
"teamId": "team_id",
"gpuModelId": "rtx-4090-rtx-4090-spheron-ai-1",
"gpuType": "rtx-4090",
"offerId": "rtx-4090-spheron-ai-1",
"providerId": "spheron-ai",
"gpuCount": 1,
"region": "us-east-1",
"operatingSystem": "ubuntu-20.04",
"instanceType": "DEDICATED",
"sshKeyId": "ssh_key_id_here",
"tempSshKeyId": null,
"sshKeyName": "My SSH Key",
"sshKeyFingerprint": "SHA256:abc123...",
"ipAddress": null,
"user": null,
"status": "deploying",
"startedAt": null,
"stoppedAt": null,
"lastCreditDeduction": null,
"totalCost": 0,
"hourlyRate": 0.50,
"originalHourlyRate": 0.50,
"discountPercentage": 0,
"hasDiscount": false,
"vcpus": 8,
"memory": 32,
"storage": 100,
"sshCommand": null,
"sshPort": null,
"portForwards": [],
"kubernetesAddon": {
"version": "1.35",
"kubeconfig": "apiVersion: v1\nclusters:...",
"k8s_cluster_id": "550e8400-e29b-41d4-a716-446655440000",
"service_links": ["https://grafana-cluster-id.voltagepark.com"],
"restore": false,
"note": "kubeconfig, k8s_cluster_id, and service_links populate once cluster is running. Only present when kubernetesAddon is requested."
},
"createdAt": "2024-01-15T10:30:00Z"
}Get deployments
Get a list of your deployments with optional filtering.
Method: GET
Path: /api/deployments
Authorization: Bearer<your-api-key>
| Name | Type | Required | Description |
|---|---|---|---|
userId | string | No | Filter by user ID (must be your own) |
teamId | string | No | Filter by team ID |
status | string | No | Filter by status: active (running/deploying), inactive (terminated/failed/terminated-provider), or a specific status value: running, deploying, terminated, terminated-provider, failed |
[
{
"id": "deployment_id",
"name": "My GPU Instance",
"userId": "user_id",
"teamId": "team_id",
"gpuModelId": "rtx-4090-spheron-ai-1",
"gpuType": "rtx-4090",
"offerId": "rtx-4090-spheron-ai-1",
"providerId": "spheron-ai",
"gpuCount": 1,
"region": "us-east-1",
"operatingSystem": "ubuntu-20.04",
"instanceType": "DEDICATED",
"sshKeyId": "ssh_key_id_here",
"tempSshKeyId": null,
"sshKeyName": "My SSH Key",
"sshKeyFingerprint": "SHA256:abc123...",
"ipAddress": "192.168.1.100",
"user": "ubuntu",
"status": "running",
"startedAt": "2024-01-15T10:30:00Z",
"stoppedAt": null,
"lastCreditDeduction": "2024-01-15T11:30:00Z",
"totalCost": 12.50,
"hourlyRate": 0.50,
"hasDiscount": false,
"discountPercentage": 0,
"originalHourlyRate": 0.50,
"vcpus": 8,
"memory": 32,
"storage": 100,
"sshCommand": "ssh ubuntu@192.168.1.100",
"sshPort": 22,
"portForwards": [],
"kubernetesAddon": {
"version": "1.35",
"kubeconfig": "apiVersion: v1\nclusters:...",
"k8s_cluster_id": "550e8400-e29b-41d4-a716-446655440000",
"service_links": ["https://grafana-cluster-id.voltagepark.com"],
"restore": false,
"note": "Only present for deployments with Kubernetes addon"
},
"createdAt": "2024-01-15T10:30:00Z"
}
]Get deployment details
Get details of a specific deployment by ID.
Method: GET
Path: /api/deployments/{deploymentId}
Authorization: Bearer<your-api-key>
| Name | Type | Required | Description |
|---|---|---|---|
deploymentId | string | Yes | Deployment ID |
{
"id": "deployment_id",
"name": "My GPU Instance",
"userId": "user_id",
"teamId": "team_id",
"gpuModelId": "rtx-4090-spheron-ai-1",
"gpuType": "rtx-4090",
"offerId": "rtx-4090-spheron-ai-1",
"providerId": "spheron-ai",
"gpuCount": 1,
"region": "us-east-1",
"operatingSystem": "ubuntu-20.04",
"instanceType": "DEDICATED",
"sshKeyId": "ssh_key_id_here",
"tempSshKeyId": null,
"sshKeyName": "My SSH Key",
"sshKeyFingerprint": "SHA256:abc123...",
"ipAddress": "192.168.1.100",
"user": "ubuntu",
"status": "running",
"startedAt": "2024-01-15T10:30:00Z",
"stoppedAt": null,
"lastCreditDeduction": "2024-01-15T11:30:00Z",
"totalCost": 12.50,
"hourlyRate": 0.50,
"hasDiscount": false,
"discountPercentage": 0,
"originalHourlyRate": 0.50,
"vcpus": 8,
"memory": 32,
"storage": 100,
"sshCommand": "ssh ubuntu@192.168.1.100",
"sshPort": 22,
"portForwards": [],
"kubernetesAddon": {
"version": "1.35",
"kubeconfig": "apiVersion: v1\nclusters:...",
"k8s_cluster_id": "550e8400-e29b-41d4-a716-446655440000",
"service_links": ["https://grafana-cluster-id.voltagepark.com"],
"restore": false,
"note": "Only present for deployments with Kubernetes addon"
},
"extras": {},
"createdAt": "2024-01-15T10:30:00Z"
}Terminate deployment
Terminate a deployment and its associated cloud instance.
Method: DELETE
Path: /api/deployments/{deploymentId}
Authorization: Bearer<your-api-key>
| Name | Type | Required | Description |
|---|---|---|---|
deploymentId | string | Yes | Deployment ID to terminate |
{
"message": "Instance destruction initiated",
"deployment": {
"id": "deployment_id",
"status": "terminated",
"stoppedAt": "2024-01-15T12:30:00Z"
}
}Check if deployment can be terminated
Check whether a deployment has met the minimum runtime and can be safely terminated. Use this before calling the terminate endpoint to avoid rejected requests.
Method: GET
Path: /api/deployments/{deploymentId}/can-terminate
Authorization: Bearer<your-api-key>
| Name | Type | Required | Description |
|---|---|---|---|
deploymentId | string | Yes | Deployment ID to check |
{
"canTerminate": true,
"runtime": 25,
"timeRemaining": 0,
"minimumRuntime": 20
}Kubernetes
Get Kubernetes versions
Get available Kubernetes versions for Voltage Park bare-metal deployments.
Method: GET
Path: /api/kubernetes/versions
Authorization: Bearer<your-api-key>
| Name | Type | Required | Description |
|---|---|---|---|
provider | string | Yes | Provider name (currently only 'voltage-park' is supported) |
{
"versions": [
{ "version": "1.35", "available": true },
{ "version": "1.34", "available": true },
{ "version": "1.33", "available": true },
{ "version": "1.32", "available": true }
]
}Get Kubernetes cluster health
Get health status of a Kubernetes cluster by cluster ID.
Method: GET
Path: /api/kubernetes/{clusterId}/health
Authorization: Bearer<your-api-key>
| Name | Type | Required | Description |
|---|---|---|---|
clusterId | string | Yes | Kubernetes cluster ID (UUID) |
{
"health": {
"controlPlaneNodes": { "healthy": 3, "total": 3, "status": "healthy" },
"workerNodes": { "healthy": 8, "total": 8, "status": "healthy" },
"networkComponents": { "healthy": 2, "total": 2, "status": "healthy" },
"overallHealth": "healthy"
}
}SSH keys
Get SSH keys
Get a list of your SSH keys.
Method: GET
Path: /api/ssh-keys
Authorization: Bearer<your-api-key>
| Name | Type | Required | Description |
|---|---|---|---|
userId | string | No | Filter by user ID (must be your own) |
teamId | string | No | Filter by team ID |
[
{
"id": "ssh_key_id",
"userId": "user_id",
"teamId": "team_id",
"name": "My SSH Key",
"publicKey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB...",
"fingerprint": "sha256:abc123def456...",
"createdAt": "2024-01-15T10:30:00Z"
}
]Add SSH key
Add a new SSH key.
Method: POST
Path: /api/ssh-keys
Authorization: Bearer<your-api-key>Content-Type: application/json
{
"name": "My SSH Key",
"publicKey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB... user@hostname",
"teamId": "team_id_optional"
}{
"id": "ssh_key_id",
"userId": "user_id",
"teamId": "team_id",
"name": "My SSH Key",
"publicKey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB...",
"fingerprint": "sha256:abc123def456...",
"createdAt": "2024-01-15T10:30:00Z"
}Get SSH key details
Get a specific SSH key by ID.
Method: GET
Path: /api/ssh-keys/{id}
Authorization: Bearer<your-api-key>
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | SSH key ID |
{
"id": "ssh_key_id",
"userId": "user_id",
"teamId": "team_id",
"name": "My SSH Key",
"publicKey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB...",
"fingerprint": "sha256:abc123def456...",
"createdAt": "2024-01-15T10:30:00Z"
}Delete SSH key
Delete an SSH key.
Method: DELETE
Path: /api/ssh-keys/{id}
Authorization: Bearer<your-api-key>
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | SSH key ID to delete |
{
"success": true
}Volumes
Supported providers: voltage-park, data-crunch, sesterce, and spheron-ai. Each provider has different rules around size limits, regions, attachment, and mutability. Before creating a volume, call GET /api/volumes/regions?provider=<id> to discover valid regions (and for Sesterce, the required cloudId).
List volumes
List all persistent storage volumes for a team with pagination and status filtering.
Method: GET
Path: /api/volumes
Authorization: Bearer<your-api-key>
| Name | Type | Required | Description |
|---|---|---|---|
teamId | string | No | Filter by team ID (defaults to current team) |
page | number | No | Page number (default: 1) |
limit | number | No | Items per page (default: 20) |
status | string | No | Filter by status: 'available', 'attached', 'deleting', or 'deleted' |
{
"volumes": [{
"id": "volume_internal_id",
"volumeId": "vol_abc123",
"name": "my-data-volume",
"userId": "user_id",
"teamId": "team_id",
"providerId": "voltage-park",
"sizeInGb": 100,
"usedCapacityBytes": 52428800000,
"virtualIp": "192.168.100.50",
"attachedToDeploymentIds": ["deployment_id_1"],
"attachedToOrderIds": ["order_123"],
"status": "attached",
"hourlyRate": 0.0137,
"lastPriceUpdate": "2026-02-07T10:30:00Z",
"createdAt": "2026-02-07T10:00:00Z",
"lastAttachedAt": "2026-02-07T10:15:00Z"
}],
"total": 5,
"page": 1,
"limit": 20,
"totalPages": 1
}Create volume
Create a new persistent storage volume. Optionally attach to an existing deployment during creation (Voltage Park, Verda, and Spheron AI). Sesterce volumes bind at instance launch only and do not accept deploymentId on create. Pass the volume ID in volumeIds on POST /api/deployments instead.
Method: POST
Path: /api/volumes
Authorization: Bearer<your-api-key>Content-Type: application/json
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Volume name (lowercase alphanumeric with hyphens/underscores, max 60 chars) |
sizeInGb | number | Yes | Volume size in GB. Limits vary by provider (see below). |
provider | string | Yes | Provider name: voltage-park, data-crunch, sesterce, or spheron-ai |
region | string | Conditional | Region for the volume. Required for data-crunch, sesterce, and spheron-ai. Use GET /api/volumes/regions?provider=<id> to list available options. |
cloudId | string | Conditional | Cloud provider identifier. Required for sesterce only. Fetch alongside the region from GET /api/volumes/regions?provider=sesterce. |
teamId | string | No | Team ID (defaults to current team) |
deploymentId | string | No | Deployment ID to attach to during creation. Supported for voltage-park, data-crunch, and spheron-ai. Not supported for sesterce. |
{
"name": "my-data-volume",
"sizeInGb": 100,
"provider": "voltage-park",
"teamId": "team_id_optional",
"deploymentId": "deployment_id_optional"
}{
"name": "my-data-volume",
"sizeInGb": 100,
"provider": "data-crunch",
"region": "FIN-01"
}{
"name": "my-data-volume",
"sizeInGb": 100,
"provider": "sesterce",
"region": "eu-west-1",
"cloudId": "668f9d8df664e3c028ce5de9"
}{
"name": "my-data-volume",
"sizeInGb": 100,
"provider": "spheron-ai",
"region": "CANADA-1"
}{
"id": "volume_internal_id",
"volumeId": "vol_abc123",
"name": "my-data-volume",
"userId": "user_id",
"teamId": "team_id",
"providerId": "voltage-park",
"sizeInGb": 100,
"usedCapacityBytes": 0,
"virtualIp": "192.168.100.50",
"attachedToDeploymentIds": [],
"attachedToOrderIds": [],
"status": "available",
"hourlyRate": 0.0137,
"lastPriceUpdate": "2026-02-07T10:00:00Z",
"createdAt": "2026-02-07T10:00:00Z"
}Get volume details
Get volume details with fresh usage data from the provider.
Method: GET
Path: /api/volumes/{volumeId}
Authorization: Bearer<your-api-key>
| Name | Type | Required | Description |
|---|---|---|---|
volumeId | string | Yes | Volume ID to retrieve |
{
"id": "volume_internal_id",
"volumeId": "vol_abc123",
"name": "my-data-volume",
"userId": "user_id",
"teamId": "team_id",
"providerId": "voltage-park",
"sizeInGb": 100,
"usedCapacityBytes": 52428800000,
"virtualIp": "192.168.100.50",
"attachedToDeploymentIds": ["deployment_id_1"],
"attachedToOrderIds": ["order_123"],
"status": "attached",
"hourlyRate": 0.0137,
"lastPriceUpdate": "2026-02-07T10:00:00Z",
"createdAt": "2026-02-07T10:00:00Z",
"lastAttachedAt": "2026-02-07T10:15:00Z"
}Update volume
Update volume properties. Support depends on provider.
Method: PATCH
Path: /api/volumes/{volumeId}
Authorization: Bearer<your-api-key>Content-Type: application/json
| Name | Type | Required | Description |
|---|---|---|---|
volumeId | string | Yes | Volume ID to update |
{
"name": "renamed-volume",
"sizeInGb": 200
}{
"id": "volume_internal_id",
"volumeId": "vol_abc123",
"name": "renamed-volume",
"sizeInGb": 200,
"virtualIp": "192.168.100.50",
"hourlyRate": 0.0274,
"lastPriceUpdate": "2026-02-07T11:00:00Z"
}Delete volume
Delete a volume. The volume must not be attached to any active deployments. Terminate the instance first, then delete the volume. This applies to all providers including Sesterce.
Method: DELETE
Path: /api/volumes/{volumeId}
Authorization: Bearer<your-api-key>
| Name | Type | Required | Description |
|---|---|---|---|
volumeId | string | Yes | Volume ID to delete |
{
"success": true
}Attach volume
Attach a volume to a running deployment. Volume and deployment must be from the same provider and region.
Method: POST
Path: /api/volumes/{volumeId}/attach
Authorization: Bearer<your-api-key>Content-Type: application/json
| Name | Type | Required | Description |
|---|---|---|---|
volumeId | string | Yes | Volume ID to attach |
{
"deploymentId": "deployment_id_here"
}{
"id": "volume_internal_id",
"volumeId": "vol_abc123",
"status": "attached",
"virtualIp": "192.168.100.50",
"attachedToDeploymentIds": ["deployment_id_here"],
"attachedToOrderIds": ["order_123"],
"lastAttachedAt": "2026-02-07T12:00:00Z"
}Detach volume
Detach a volume from a deployment. Volume data is preserved and can be attached to another deployment.
Method: POST
Path: /api/volumes/{volumeId}/detach
Authorization: Bearer<your-api-key>Content-Type: application/json
| Name | Type | Required | Description |
|---|---|---|---|
volumeId | string | Yes | Volume ID to detach |
{
"deploymentId": "deployment_id_here"
}{
"id": "volume_internal_id",
"volumeId": "vol_abc123",
"status": "available",
"virtualIp": "192.168.100.50",
"attachedToDeploymentIds": [],
"attachedToOrderIds": [],
"lastDetachedAt": "2026-02-07T13:00:00Z"
}Get volume pricing
Get storage pricing per GB per hour for a specific provider. For Sesterce, pass cloudId and region to get the rate for a specific availability zone. Sesterce pricing varies significantly by AZ.
Method: GET
Path: /api/volumes/pricing
Authorization: Bearer<your-api-key>
| Name | Type | Required | Description |
|---|---|---|---|
provider | string | No | Provider name: voltage-park, data-crunch, sesterce, or spheron-ai. Defaults to voltage-park. |
cloudId | string | Conditional | Cloud provider identifier. Sesterce only. Use alongside region to fetch the rate for a specific AZ. |
region | string | Conditional | Region identifier. Sesterce only. Use alongside cloudId to fetch the rate for a specific AZ. |
{
"provider": "voltage-park",
"hourlyRatePerGb": 0.000137
}Get volume regions
Get available regions and volume tiers for a given storage provider. Required before creating data-crunch, sesterce, or spheron-ai volumes to pick valid region (and cloud) values. Each region entry is annotated with hasGpuOffers so you can check whether any GPU offers exist in that region before creating a volume there. A top-level hasAnyOffers flag indicates whether the provider has any live GPU offers at all.
Method: GET
Path: /api/volumes/regions
Authorization: Bearer<your-api-key>
| Name | Type | Required | Description |
|---|---|---|---|
provider | string | No | Provider name: voltage-park, data-crunch, sesterce, or spheron-ai. Defaults to voltage-park. Unknown values return 400. |
voltage-park):
{
"hasAnyOffers": true,
"regions": [
{ "id": "Texas", "name": "Dallas, TX", "country_code": "US", "types": ["NFS"], "hasGpuOffers": true }
]
}?provider=data-crunch):
{
"hasAnyOffers": true,
"regions": [
{ "id": "FIN-01", "name": "Finland 1", "country_code": "FI", "types": ["NVMe_Shared"], "hasGpuOffers": true },
{ "id": "FIN-02", "name": "Finland 2", "country_code": "FI", "types": ["NVMe_Shared"], "hasGpuOffers": true },
{ "id": "FIN-03", "name": "Finland 3", "country_code": "FI", "types": ["NVMe_Shared"], "hasGpuOffers": false }
]
}?provider=sesterce):
Sesterce entries include cloudId and cloudName. Pass both region (the id) and cloudId when creating a Sesterce volume.
{
"hasAnyOffers": true,
"regions": [
{ "id": "eu-west-1", "name": "EU West 1", "cloudId": "668f9d8df664e3c028ce5de9", "cloudName": "Sesterce EU", "types": ["block-storage"], "hasGpuOffers": true },
{ "id": "us-east-1", "name": "US East 1", "cloudId": "77af9d8df664e3c028ce5ef0", "cloudName": "Sesterce US", "types": ["block-storage"], "hasGpuOffers": true }
]
}?provider=spheron-ai):
{
"hasAnyOffers": true,
"regions": [
{ "id": "CANADA-1", "name": "Canada 1", "types": ["Cloud-SSD"], "hasGpuOffers": true }
]
}Teams
Get balance
Get account balance. Returns all teams by default.
Method: GET
Path: /api/balance
Authorization: Bearer<your-api-key>
| Name | Type | Required | Description |
|---|---|---|---|
teamId | string | No | Get balance for a specific team ID only |
all | boolean | No | Set to 'false' to get current team only (default: true) |
{
"teams": [
{
"teamId": "team_1",
"teamName": "My Personal Team",
"balance": 25.50,
"isCurrentTeam": true,
"role": "owner"
},
{
"teamId": "team_2",
"teamName": "Company Team",
"balance": 150.75,
"isCurrentTeam": false,
"role": "admin"
}
],
"currency": "USD"
}Error reference
All error responses follow this format:
{
"error": "Error message",
"code": "ERROR_CODE",
"details": {}
}Common HTTP status codes
200 OK: Request succeeded
201 Created: Resource created successfully
400 Bad Request: Invalid parameters or request body
{
"error": "Missing required field: gpuType",
"code": "VALIDATION_ERROR"
}401 Unauthorized: Invalid or missing API key
{
"error": "Invalid API key",
"code": "UNAUTHORIZED"
}403 Forbidden: Insufficient permissions
{
"error": "Insufficient permissions to access this resource",
"code": "FORBIDDEN"
}404 Not Found: Resource does not exist
{
"error": "Deployment not found",
"code": "NOT_FOUND"
}429 Too Many Requests: Rate limit exceeded
{
"error": "Rate limit exceeded. Try again in 15 minutes",
"code": "RATE_LIMIT_EXCEEDED"
}500 Internal Server Error: Server error
{
"error": "Internal server error",
"code": "INTERNAL_ERROR"
}Status values
Deployment statuses
deploying: Instance is being provisioned. Usually takes 30-60 seconds.
running: Instance is active and accessible via SSH.
failed: Deployment failed. Check error details in the deployment object.
terminated: Instance has been terminated by the user and is no longer accessible.
terminated-provider: Instance was reclaimed or stopped by the provider (e.g., a Spot instance was interrupted). No further action is needed.
Status lifecycle
deploying → running → terminated
↓ ↓
failed terminated-providerdeployingtorunning: Successful deploymentdeployingtofailed: Deployment errorrunningtoterminated: Manual termination by userrunningtoterminated-provider: Provider reclaimed the instance (Spot interruption or provider-side stop)- Any status can transition to
failedif errors occur
Rate limits
All API endpoints are subject to rate limiting to ensure fair usage and system stability. Rate limits are tracked per IP address for unauthenticated requests and per user (Firebase UID) for authenticated requests.
Rate limit headers
All responses include these headers:
X-RateLimit-Limit: 250
X-RateLimit-Remaining: 245
X-RateLimit-Reset: 2025-12-29T14:00:00.000ZRate limits by endpoint
GPU offers and providers
GET /api/providers
GET /api/gpu-offers- Limit: 250 requests per 15 minutes
- Scope: Per IP address
- Authentication: Optional (authenticated users see team discounts)
Deployments
POST /api/deployments- Default limit: 10 deployments per 15 minutes
- Scope: Per authenticated user
- Custom limits: Admins can increase limits for enterprise users
- Authentication: Required
GET /api/deployments
GET /api/deployments/{deploymentId}
DELETE /api/deployments/{deploymentId}- Limit: 250 requests per 15 minutes
- Scope: Per IP address
- Authentication: Required
SSH keys
GET /api/ssh-keys
GET /api/ssh-keys/{id}
POST /api/ssh-keys
DELETE /api/ssh-keys/{id}- Limit: 250 requests per 15 minutes
- Scope: Per IP address
- Authentication: Required
Balance and teams
GET /api/balance- Limit: 250 requests per 15 minutes
- Scope: Per IP address
- Authentication: Required
Rate limit response
When the rate limit is exceeded (HTTP 429):
{
"error": "Too many requests",
"message": "Too many requests from this IP, please try again later.",
"retryAfter": 900
}Custom rate limits (enterprise)
Enterprise customers can request custom deployment creation limits:
- Contact: info@spheron.ai
- Configurable: Deployment creation limit (default: 10 per 15 min)
- Options: Custom limit or unlimited deployments
Quick reference
| Endpoint | Rate Limit | Window | Scope | Custom Limits |
|---|---|---|---|---|
| General API | 250 requests | 15 min | IP | No |
| Deployment Creation | 10 requests | 15 min | User | Yes |
| All Other API Endpoints | 250 requests | 15 min | IP | No |
Security
Best practices
Treat API keys like passwords:
- Never expose keys in client-side code
- Do not commit keys to version control
- Use environment variables for credentials
- Rotate keys regularly
Key management:
- Generate keys from dashboard settings
- Set expiry dates for keys
- Revoke compromised keys immediately
- Use separate keys for different environments
Connection security:
- All API requests must use HTTPS
- Verify SSL certificates
- Do not disable certificate validation
For comprehensive security guidelines, see Security best practices.
Common workflows
Complete deployment flow
# 1. Check available GPU offers
curl -H "Authorization: Bearer <your-api-key>" \
"https://app.spheron.ai/api/gpu-offers?search=rtx-4090&limit=5"
# 2. Add SSH key (if not already added)
curl -X POST "https://app.spheron.ai/api/ssh-keys" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
-d '{"name": "My Key", "publicKey": "ssh-rsa AAA..."}'
# 3. Deploy instance
curl -X POST "https://app.spheron.ai/api/deployments" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
-d '{
"provider": "spheron-ai",
"offerId": "rtx-4090-spheron-ai-1",
"gpuType": "rtx-4090",
"gpuCount": 1,
"region": "us-east-1",
"operatingSystem": "ubuntu-22.04",
"instanceType": "DEDICATED",
"sshKeyId": "your_ssh_key_id"
}'
# 4. Monitor deployment status
curl -H "Authorization: Bearer <your-api-key>" \
"https://app.spheron.ai/api/deployments/deployment_id"
# 5. Terminate when done
curl -X DELETE "https://app.spheron.ai/api/deployments/deployment_id" \
-H "Authorization: Bearer <your-api-key>"What's next
- Getting Started: Account setup and first deployment
- Security best practices: API key management and security
- Connecting to instances: SSH and networking setup
- Billing: Credits and usage monitoring