# VoltageGPU for coding agents

Instructions for an AI coding assistant (Claude Code, Cursor, GitHub Copilot, Codex and similar)
that manages VoltageGPU for its user: keys, Confidential VMs, standard GPU pods, dedicated bare
metal, sandboxes, the OpenAI-compatible inference API, and releasing what it created.

Contract as of 2026-10-25. Sources: the OpenAPI file https://voltagegpu.com/openapi-voltagegpu.yaml,
the API reference https://docs.voltagegpu.com/api-reference and the server code. When this file and
a live API answer disagree, the live answer wins: say so to the user.

## Block to copy into your AGENTS.md or CLAUDE.md

```markdown
## VoltageGPU
- Before any VoltageGPU call, read https://voltagegpu.com/coding-agents.md and follow it.
- Keys come from environment variables only: VOLT_API_KEY (volt_..., GPU pods, header X-API-Key)
  and VOLTAGEGPU_API_KEY (vgpu_..., inference, header Authorization: Bearer). Never print,
  log, commit or paste a key. Never create or revoke keys: the user does it at
  https://voltagegpu.com/api-keys.
- Ask me before anything that spends money: say the machine, the hourly price, that one hour
  is charged at deploy, and the automatic stop you will set. Wait for a yes.
- Keep a list of every pod, VM, bare metal machine and sandbox you create, and release each one
  when the task ends or fails. Powering a machine off from inside does not stop billing.
- Only Confidential VMs are confidential. Standard pods, bare metal and sandboxes have no enclave.
```

## 1. Rules for the agent

1. **Keys.** Read keys from the environment. Never echo them, never put them in a command that is
   shown to the user, a log, a file in the repository or a commit. Use `-H "X-API-Key: $VOLT_API_KEY"`,
   not the literal value. If a key is missing, ask the user to set the variable; do not ask them to
   paste it into the chat.
2. **Keys are created by the user, not by you.** `/api/volt/api-keys` only accepts a logged-in
   dashboard session; an API key sent there answers 401. Point the user to
   https://voltagegpu.com/api-keys. Two kinds exist there: "GPU Pods" (`volt_...`) and
   "AI Inference" (`vgpu_...`). The full key is shown once.
3. **Confirm before spending.** Every deploy charges one hour of the machine at once. Before
   `POST /api/volt/pods` or `POST /api/volt/sandboxes`, tell the user: what you will create, the
   hourly price read from the live list, the amount charged now (one hour), and the automatic stop
   you will set. Wait for an explicit yes. Check `GET /api/volt/balance` first.
4. **Always set an automatic stop**, as a safety net in case your session ends:
   `hardstop_hours` (Confidential VM, 0 to 720; 0 or absent means no automatic stop),
   `auto_terminate_hours` (standard pod, 1 to 720), `hardstop_hours` (bare metal, 1 to 72, mandatory,
   24 by default), `deleteTimeoutSec` (sandbox, optional, at most 7 days).
5. **Release what you create.** Record every id you get back. At the end of the task, or after an
   error, release each one (section 9) and confirm with a final `GET /api/volt/pods` and
   `GET /api/volt/sandboxes` that nothing you created is still listed.
6. **Do not retry a deploy blindly.** If an answer has `"charged": true`, or if a call timed out,
   list your pods before trying again (section 9). Two deploys mean two prepaid hours.
7. **Say what is and is not confidential** (section 11). Never call a standard pod, a bare metal
   machine or a sandbox "confidential", "sealed" or "attested".
8. **Do not invent fields.** Use the fields in this file or in the OpenAPI file. Unknown fields are
   refused on standard pods (400 `Unknown field`).

## 2. Endpoints and authentication

| What | Base URL | Header |
|---|---|---|
| GPU pods, VMs, bare metal, sandboxes, SSH keys, balance | `https://api.voltagegpu.com` (the paths of sections 3 to 9) | `X-API-Key: $VOLT_API_KEY` |
| Inference (OpenAI-compatible) | `https://api.voltagegpu.com/v1` | `Authorization: Bearer $VOLTAGEGPU_API_KEY` |

- Pod routes also accept the same `volt_` key as `Authorization: Bearer volt_...`. `X-API-Key` is the
  documented form; use it.
- A `vgpu_` key does not open pod routes, and a `volt_` key does not open inference routes.
- Missing key: 401 `{"success": false, "error": "Unauthorized", "message": "Missing X-API-Key header", ...}`.
  Wrong key: 401 `{"success": false, "error": "Invalid API key", "status_code": 401}`.
- `POST /api/volt/pods` is limited to 10 requests per 10 seconds per client IP (429, see `Retry-After`).
- Errors on `/api/volt/pods` and `/api/volt/machines` usually look like
  `{"success": false, "error": "<plain English, says what to call next>", "status_code": <n>, ...}`.
  Bare metal and sandbox refusals add a `code`: `BALANCE_TOO_LOW`, `SOLD_OUT`, `NOT_ELIGIBLE`,
  `FEATURE_DISABLED`, `PROVIDER_ERROR`, and `RATE_LIMITED` for too many attempts.
- An MCP server also exists (https://voltagegpu.com/mcp-server-confidential) for the Confidential VM
  flow. This file describes the REST API.

## 3. Before any deploy

```bash
# Balance (USD, four decimals) and number of running pods
curl -s -H "X-API-Key: $VOLT_API_KEY" https://api.voltagegpu.com/api/volt/balance
# {"success": true, "balance": 11.0314, "currency": "USD", "active_pods": 0, "top_up_url": "https://voltagegpu.com/billing"}

# SSH keys on the account (newest first); each has id, name, publicKey, createdAt
curl -s -H "X-API-Key: $VOLT_API_KEY" https://api.voltagegpu.com/api/volt/ssh-keys

# Register the user's PUBLIC key if there is none (never a private key)
curl -s -X POST https://api.voltagegpu.com/api/volt/ssh-keys \
  -H "X-API-Key: $VOLT_API_KEY" -H "Content-Type: application/json" \
  -d "{\"name\": \"laptop\", \"public_key\": \"$(cat ~/.ssh/id_ed25519.pub)\"}"
# 201 {"id": "...", "name": "laptop", "publicKey": "ssh-ed25519 ...", "createdAt": "..."}
# 400 {"success": false, "error": "name and public_key required"}
```

Delete a key: `DELETE /api/volt/ssh-keys/{id}` (200 `{"success": true}`, 404 if not yours).

The balance must cover one hour of the chosen machine, otherwise the deploy answers 402 and
nothing is charged. Top-ups happen at https://voltagegpu.com/billing, by the user.

## 4. Confidential VM (Intel TDX, the confidential product)

1. **List tiers.** `GET /api/volt/machines` (no `provider`, or `provider=confidential`). Each entry has
   `resource_name` (for example `h100-small`), `name`, `price` (per hour for the whole VM),
   `gpu_type`, `gpu_count`, `provider: "confidential"`, `confidential_compute: true`. Only tiers in
   stock are listed.
2. **Confirm with the user** (rule 3).
3. **Deploy.**

   ```bash
   curl -s -X POST https://api.voltagegpu.com/api/volt/pods \
     -H "X-API-Key: $VOLT_API_KEY" -H "Content-Type: application/json" \
     -d '{"provider": "confidential", "name": "my-vm", "resource_name": "h100-small", "hardstop_hours": 4}'
   ```

   - Body: `provider` (required), `name` (required; a random suffix is added), `resource_name`
     (required), `hardstop_hours` (0 to 720), `ports` (optional, `[{"port": 8080, "protocol": "tcp"}]`,
     at most eight, port 22 refused because SSH is mapped for you, refused on the 8-GPU tiers whose
     `resource_name` ends in `-xlarge`).
   - SSH keys: omit `ssh_key_uids`. The VM binds keys already registered on the account (up to
     five) at creation. A key cannot be added to a running VM, so register it first (section 3).
   - Success, HTTP 200: `podId`, `workloadUid`, `resourceName`, `hourlyPrice`, `sudoPassword`
     (usually `null`: sudo works without a password for `ubuntu`), `hardStopAt`, `ports`,
     `attestation` (`verified`, `verifiedOn`, `evidenceUrl`, `verifyInsideTheVm`), `message`.
     If `sudoPassword` is not null it is shown once: hand it to the user, do not log it.
4. **Wait for SSH.** Poll `GET /api/volt/pods` every 15 seconds. Find the entry whose `id` equals
   `workloadUid`. `provider_status` goes from `provisioning` to `running`; when `ssh_ready` is
   `true`, `ssh_command` is `ssh -p <port> ubuntu@<ip>` (also `ssh_host`, `ssh_port`, `ssh_user`).
   Count about two minutes. `GET /api/volt/pods/{id}` returns the raw machine state for a VM, not
   `ssh_command`: use the list.
5. **Verify the attestation inside the VM** (section 8), if the user needs the proof.
6. **Release**: `DELETE /api/volt/pods/{workloadUid}` (section 9).

Errors: 400 (`name and resource_name are required`, not a Confidential VM tier, `ports` problems,
`needsSshKey: true` with "Add an SSH key first"), 402 (balance below one hour, nothing charged),
409 (tier sold out), 502 (availability could not be checked), 503 (price unavailable, or
`retry: true` when the SSH key could not be registered: nothing charged, retry in a minute).
If you get 410 or `name is required, plus either (resource_name and image) or template_uid`, the
`resource_name` is not a current VM tier: list the tiers again.

## 5. Standard GPU pod (NO enclave, for data that is not sensitive)

1. `GET /api/volt/machines?provider=standard`: machines that can be deployed now, rented whole,
   cheapest first, refreshed at most once a minute. Use `machine_id`; `price_per_hour` is for the
   whole machine (also `gpu_type`, `gpu_count`, `gpu_memory_gb`, `price_per_gpu_hour`, `location`).
   503 if the list is temporarily unavailable.
2. Optional: `GET /api/volt/templates?provider=standard` (`items[].id` is the `template_id`; the
   entry with `default: true` is used when you omit it).
3. Confirm with the user, then deploy:

   ```bash
   curl -s -X POST https://api.voltagegpu.com/api/volt/pods \
     -H "X-API-Key: $VOLT_API_KEY" -H "Content-Type: application/json" \
     -d '{"provider": "standard", "name": "my-run", "machine_id": "<machine_id>", "auto_terminate_hours": 2}'
   ```

   - Required: `provider`, `name` (lowercase letters, digits, hyphens, at most 40), `machine_id`.
   - Optional: `ssh_key_id` (required only when the account has more than one key), `template_id`
     or your own public `image` (linux/amd64; not both), `start_command` (one command:
     `;` `&` `|` `<` `>` backticks, `$(` and line breaks are refused), `ports`, `env`, `gpu_count`
     (must equal the machine's count), `jupyter`, `port_count` (1 to 31), `auto_terminate_hours`
     (1 to 720), `volume_id`.
   - Success, HTTP 201: `pod.id`, `hourly_price`, `prepaid_amount` (charged now), `status: "RUNNING"`,
     `confidential_compute: false`, `ssh_command: null`.
4. Poll `GET /api/volt/pods/{id}` until `ssh_command` is set.
5. Release: `DELETE /api/volt/pods/{id}`. The answer carries `prepaidRefund`.

Errors (every refusal says `charged`): 400 (field problems, `Unknown field`, `reason: image_not_found`
or `settings_refused` for a custom image), 402 (balance below one hour; `required` and `balance`),
403 `FEATURE_DISABLED` (standard volumes closed), 404 (machine, SSH key or volume not found),
409 (machine cannot be rented whole right now: pick another), 429, 502 (`charged: false`: nothing
taken; `charged: true`: see section 9), 503 (templates or machine list unavailable).
A running pod cannot be edited: `PUT /api/volt/pods/{id}` answers 405 (409 for a Confidential VM).
`DELETE` on a pod still being deployed answers 409: retry in a minute.

Check the hardware against the listing, read-only, inside the pod:
`curl -fsSL https://voltagegpu.com/hwcheck.sh | bash -s -- --gpu "<model>" --gpus <n>`.

## 6. Dedicated bare metal (NO enclave, NO hypervisor, whole machine)

Access rules, checked server-side: a verified account with at least $100 of card top-ups, the
first one more than 14 days old, no disputed payment, an account at least one day old, one machine
at a time, 30 minutes between two deployments, 5 attempts per 10 minutes. The offer can be
closed (403 `FEATURE_DISABLED`); while it is closed, the machine list shows `available: 0`.
Newer accounts can ask for a manual review at contact@voltagegpu.com.

1. `GET /api/volt/machines?provider=dedicated`: `machine_id` (for example `bm-a5-h100-sxm`),
   `name`, `gpuModel`, `gpuCount`, `vcpu`, `pricePerHour` (whole machine), `available`, `region`,
   `tier: "dedicated"`, `enclave: "none"`, `gpuAttestation: false`.
2. Confirm with the user (the price is per hour for the whole machine; one hour is charged now).
3. Deploy:

   ```bash
   curl -s -X POST https://api.voltagegpu.com/api/volt/pods \
     -H "X-API-Key: $VOLT_API_KEY" -H "Content-Type: application/json" \
     -d '{"provider": "dedicated", "machine_id": "bm-a5-h100-sxm", "ssh_key_ids": ["<ssh_key_id>"], "hardstop_hours": 8, "image": "ubuntu-24.04"}'
   ```

   - `ssh_key_ids`: at least one `id` from `GET /api/volt/ssh-keys` (keys bind at creation).
   - `hardstop_hours`: 1 to 72, default 24. The automatic release is mandatory. It can be set lower
     than you asked: read `pod.hardStopAt` in the answer.
   - `image`: only `ubuntu-24.04`. The image has no NVIDIA driver; install it with Fabric Manager:
     `curl -fsSL https://voltagegpu.com/dedicated-setup.sh | bash`.
   - Success, HTTP 200: `pod.id`, `pod.hourlyPrice`, `pod.hardStopAt`, `pod.region`, `message`.
4. **Wait 15 to 25 minutes** (disks erased, OS installed). Poll `GET /api/volt/pods` every minute and
   take the entry with `tier: "dedicated"` (the account can hold only one). Its `id` is not the
   `pod.id` of the deploy answer. When `ssh_ready` is `true`, use its `ssh_command`.
5. Check the hardware yourself: the hwcheck script, `systemd-detect-virt` (must print `none`),
   `nvidia-smi topo -m` (every GPU pair on an `NV<n>` path, never `SYS`, `PHB` or `PIX`).
   Not proven by these commands: the BMC and its firmware, VBIOS and firmware versions, disk erasure
   between tenants.
6. Release: `DELETE /api/volt/pods/{pod.id}`. The disks are wiped, nothing is kept.

Errors (`{"error": "...", "code": "..."}`): 400 (`resourceName is required`, `hardstopHours must be
between 1 and 72`, `Only ubuntu-24.04 ...`, `At least one SSH key is required`, keys not on the
account, not a dedicated machine; the messages use the internal names `resourceName` and
`hardstopHours` for `machine_id` and `hardstop_hours`), 402 `BALANCE_TOO_LOW`, 403 `NOT_ELIGIBLE` or
`FEATURE_DISABLED`, 409 `SOLD_OUT`, 429 `RATE_LIMITED`, 500/502/503 `PROVIDER_ERROR` (nothing charged).

## 7. Sandboxes (NO enclave, CPU only)

Small Ubuntu environments: `sandbox-small` (1 vCPU), `sandbox-medium` (2 vCPU), `sandbox-large`
(4 vCPU), 2 GB RAM and 10 GB disk each, image `ubuntu-24.04` or `ubuntu-26.04`. Account rule: a
verified email and one successful card payment. At most 20 active sandboxes, 20 creations per
10 minutes. The offer can be closed (403 `FEATURE_DISABLED`).

```bash
# Create (one hour charged at creation, then per second)
curl -s -X POST https://api.voltagegpu.com/api/volt/sandboxes \
  -H "X-API-Key: $VOLT_API_KEY" -H "Content-Type: application/json" \
  -d '{"templateName": "sandbox-small", "image": "ubuntu-24.04", "name": "agent-task-1",
       "idleTimeoutSec": 300, "deleteTimeoutSec": 7200, "sshKeyIds": ["<ssh_key_id>"]}'
# 200 {"success": true, "podId": "...", "hourlyPrice": ..., "sandbox": {"id": "...", "status": "RUNNING" | "PENDING",
#      "pricePerHour": ..., "pausedPricePerHour": ..., "sshCommand": "ssh -p <port> root@<ip>" | null, ...}}

curl -s -H "X-API-Key: $VOLT_API_KEY" https://api.voltagegpu.com/api/volt/sandboxes              # list: {"sandboxes": [...]}
curl -s -X POST -H "X-API-Key: $VOLT_API_KEY" https://api.voltagegpu.com/api/volt/sandboxes/<id>/pause
curl -s -X POST -H "X-API-Key: $VOLT_API_KEY" https://api.voltagegpu.com/api/volt/sandboxes/<id>/resume
curl -s -X DELETE -H "X-API-Key: $VOLT_API_KEY" https://api.voltagegpu.com/api/volt/sandboxes/<id>
# delete: {"success": true, "status": "STOPPED", "charged": ..., "refunded": ...}
```

- `templateName` and `image` are required. `idleTimeoutSec`: 30 to 86400, default 300: the sandbox
  pauses itself after that much inactivity. `deleteTimeoutSec`: optional, greater than
  `idleTimeoutSec`, at most 604800 (7 days): the sandbox is deleted server-side. `sshKeyIds`: ids
  from `GET /api/volt/ssh-keys`, optional.
- SSH is as `root`. `sshCommand` is set only while the sandbox runs; if it is `null` after
  creation, read it from the list.
- A paused sandbox is still billed, at `pausedPricePerHour`. Only `DELETE` stops billing. Use
  `DELETE /api/volt/sandboxes/{id}` for sandboxes, not `/api/volt/pods/{id}`.

Errors (`{"error": "...", "code": "..."}`): 400 (`templateName and image are required`, timeout
ranges), 402 `BALANCE_TOO_LOW`, 403 `FEATURE_DISABLED` or `NOT_ELIGIBLE`, 409 `SOLD_OUT` (no ready
template for that size and image) or `RATE_LIMITED` (20 active), 429 `RATE_LIMITED` (see
`Retry-After`), 502/503 `PROVIDER_ERROR` (nothing charged). Pause and resume: 400 when the state
does not allow it, 404 if not yours, 502 `PROVIDER_ERROR` (retry in a few seconds).

## 8. Attestation of a Confidential VM

The proof is generated by the tenant inside the VM, on a nonce the tenant chooses. The deploy
answer lists the exact commands in `attestation.verifyInsideTheVm`; as of 2026-10-25 they are:

```bash
curl -sS https://bootstrap.pypa.io/get-pip.py | python3 - --user --break-system-packages
python3 -m pip install --user --break-system-packages "voltage-verify[attest]>=0.2.1"
export PATH=$HOME/.local/bin:$PATH
voltage-verify manifest --challenge auto -o manifest.json
sudo env PATH=$PATH PYTHONPATH=$(python3 -c 'import site;print(site.getusersitepackages())') voltage-verify attest --manifest manifest.json --mode single-gpu -o bundle.json
voltage-verify verify bundle.json --challenge $(python3 -c 'import json;print(json.load(open("manifest.json"))["challenge"])')
```

Then copy `bundle.json` and `manifest.json` off the VM and run the same `verify` on the user's own
machine (`pip install "voltage-verify>=0.2.1"`, `--offline` for no network). The verification that
counts is the one outside the VM. Public index of attested SKUs, no key:
https://voltagegpu.com/api/attestation/evidence

## 9. Release, billing and automatic stops

| Kind | Release | Answer |
|---|---|---|
| Confidential VM | `DELETE /api/volt/pods/{workloadUid}` | `{"success": true}` |
| Standard pod | `DELETE /api/volt/pods/{id}` | `{"success": true, "prepaidRefund": <USD>}` |
| Bare metal | `DELETE /api/volt/pods/{pod.id}` | `{"success": true}` |
| Sandbox | `DELETE /api/volt/sandboxes/{id}` | `{"success": true, "status": "STOPPED", "charged": ..., "refunded": ...}` |

- Every kind: one hour charged when the deploy succeeds, then billing per second at the hourly
  price. Releasing within that first hour refunds the unused seconds to the balance.
- Bare metal: 15 minutes are always billed, even if released sooner.
- Standard pod that never started: the whole prepaid hour is returned on release.
- Halting the machine from inside (`shutdown`, `poweroff`) does not stop billing. Only a release or
  the automatic stop does.
- The prices returned by the API are the prices charged. A volume attached to a standard pod is
  billed separately, on the data it holds.
- When the balance can no longer pay, running machines are stopped automatically, and machines
  billed $20/hour or more are stopped as soon as the balance no longer covers the next 15 minutes.
  Data on a stopped machine is lost.

**Uncertain deploy.** A 502 with `"charged": true` means we could not confirm whether the pod
started: one hour is held and returned automatically within two hours if nothing started. Do not
deploy again. Wait a few minutes, call `GET /api/volt/pods`, and release anything that appeared.
The same applies after a timeout on any deploy call.

## 10. Inference API (OpenAI-compatible)

```bash
# Models (only confidential models, ids ending in -TEE), with price per million tokens and a live status
curl -s https://api.voltagegpu.com/v1/models
# each entry: "id", "pricing": {"prompt", "completion", "unit": "usd_per_million_tokens"},
#             "status": {"state": "available" | "busy" | "saturated" | "unavailable", ...}

curl -s https://api.voltagegpu.com/v1/chat/completions \
  -H "Authorization: Bearer $VOLTAGEGPU_API_KEY" -H "Content-Type: application/json" \
  -d '{"model": "<model id from /v1/models>", "messages": [{"role": "user", "content": "Hello"}]}'
```

With an OpenAI SDK: `base_url="https://api.voltagegpu.com/v1"`, `api_key=os.environ["VOLTAGEGPU_API_KEY"]`.

- Use the exact `id` from `/v1/models`. Other models are refused.
- `fallback_models`: optional, up to 3 confidential models tried in order if the requested one
  stays saturated after retries. Without it, only the requested model runs.
- Response headers: `X-VoltageGPU-Model` (the model that ran and was billed),
  `X-VoltageGPU-Retries`, `X-VoltageGPU-Confidential: tee`, and `X-VoltageGPU-Cost-USD` when not
  streaming.
- Billed per token from the same prepaid balance. 402 when the balance is too low, 401 for a
  missing or invalid key, 429 rate limit, 502 when the model side fails.
- `GET /v1/attestation?model=<id>&nonce=<64 hex characters>` returns the Intel TDX quotes and NVIDIA
  GPU evidence of the model's running instances, bound to your nonce (6 requests per minute per
  key; 404 when the model has no running instance). It proves genuine Intel TDX guests with
  confidential-computing GPUs answering your nonce. It does not prove which instance served a given
  response, nor which code runs.
- Prompts are processed inside Intel TDX on the model side; our API relays them over TLS without
  storing or logging them. There is no end-to-end encryption from the client into the enclave.
- `/v1/embeddings` and `/v1/images/generations` are in the OpenAPI file; this guide does not cover
  them.

## 11. Verified, not verified

| Claim | Status |
|---|---|
| Confidential VM: Intel TDX trust domain, `/dev/tdx_guest` in the VM, quote generated by the tenant | Verified on the VM tier |
| NVIDIA GPU attestation from inside the VM | Verified on four SKUs only: single-GPU H200 (2026-09-04), 8x H100 node (2026-09-10, Protected PCIe multi-GPU mode, all 8 GPUs attested), single-GPU H100 (2026-09-16), single-GPU RTX PRO 6000 Blackwell (2026-09-17, again 2026-10-09). The deploy answer says it: `attestation.verified` |
| NVSwitch / NVLink fabric on the 8x H100 node | NOT verified, never claimed |
| 8x H200 node | Reads the same mode, attestation NOT run |
| B200, B300 Confidential VMs | NOT verified |
| Standard pods | NO enclave, no memory encryption, no TDX quote, no GPU attestation |
| Dedicated bare metal | NO enclave, NO attestation (the same 8x H100 sold as bare metal has no `/dev/tdx_guest`) |
| Sandboxes | NO enclave, NO attestation |
| Confidential CPU servers (AMD EPYC) | NOT verified by us, NOT deployable at the moment |
| Inference attestation | Proves confidential hardware answering your nonce; not which instance answered, not the code |

Proofs index: https://voltagegpu.com/proofs

## 12. Quick error table

| Status | Meaning | What the agent does |
|---|---|---|
| 400 | A field is wrong; `error` names it and says what to call next | Fix the body, do not retry unchanged |
| 401 | Missing or invalid key, or the wrong key kind | Check the variable and the header; ask the user |
| 402 | Balance below one hour (`BALANCE_TOO_LOW` on bare metal and sandboxes) | Tell the user the amount; they top up at https://voltagegpu.com/billing |
| 403 | `NOT_ELIGIBLE` or `FEATURE_DISABLED` | Tell the user; do not retry |
| 404 | Not found on this account (pod, machine, key, volume, sandbox) | List again, use a fresh id |
| 405 | Running pod edited with PUT | Release and deploy a new one, after asking |
| 409 | Sold out, machine taken, deploy still in progress, 20 sandboxes | Pick another machine, or wait a minute |
| 410 | Retired container tier requested | List Confidential VM tiers again |
| 429 | Rate limit (`RATE_LIMITED`) | Wait `Retry-After` seconds |
| 502 | Upstream problem; read `charged` | `false`: retry later. `true`: section 9, list before anything else |
| 503 | List, price or templates unavailable, or key registration (`retry: true`) | Retry after a short wait; nothing was charged |

## Links

- OpenAPI: https://voltagegpu.com/openapi-voltagegpu.yaml
- API reference: https://docs.voltagegpu.com/api-reference
- This guide explained for humans: https://docs.voltagegpu.com/ai-agents
- Site summary for assistants: https://voltagegpu.com/llms.txt
- Live prices, no key: https://voltagegpu.com/api/pricing/snapshot
- Support: contact@voltagegpu.com
