01Quickstart
Create an account; it takes an email address. Then, in the console:
- Add credit on Billing. Koi is prepaid, and a launch needs enough for an hour of everything you’d be running.
- Add an SSH key on Keys, so you can log in.
- Launch on Machines: pick a GPU, how many, and optionally a region and image.
- Log in. It takes minutes to start, and shows as Starting until SSH answers. Then the page gives you the command.
ssh koi@203.0.113.7
nvidia-smiThe user is always koi. Some machines answer SSH on another port, and the command includes it when they do. With VS Code and its Remote - SSH extension, “Open in VS Code” next to the command connects straight to the machine.
Terminate it when you’re done. Billing stops at once, and the machine and its disk are deleted, so copy off anything you want to keep first. An account can run 8 GPUs at once to start with. Write to us to raise that.
02From the API
Create an API key on the Keys page. It’s shown once. You’ll need an SSH key on your account too, which you can add there or with POST /ssh-keys.
export KOI_API_KEY=koi_...
# What can be launched right now, and for how much
curl https://console.koicompute.co/api/v1/skus \
-H "Authorization: Bearer $KOI_API_KEY"
# Start one
curl https://console.koicompute.co/api/v1/instances \
-H "Authorization: Bearer $KOI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"sku": "h100-1x", "name": "first-run", "stop_after_minutes": 120}'That returns the machine with an id. Poll it until state is running and ssh is set:
curl https://console.koicompute.co/api/v1/instances/$ID \
-H "Authorization: Bearer $KOI_API_KEY"
# And when you're done, which deletes the machine and its disk
curl -X DELETE https://console.koicompute.co/api/v1/instances/$ID \
-H "Authorization: Bearer $KOI_API_KEY"03CLI
One Python file that needs nothing but Python 3.8 or newer. Every command takes --json, and --help lists the rest, like koi spawn --drift and --container.
curl -fsSL https://console.koicompute.co/koi.py -o ~/.local/bin/koi && chmod +x ~/.local/bin/koi
koi login
koi keys add
koi spawn h100 --name first-run --ttl 2h
# ssh koi@203.0.113.7
koi release first-run| Command | What it does |
|---|---|
| koi login | Saves your API key, once it’s checked it works. Or set KOI_API_KEY. |
| koi keys add [file] | Adds your SSH public key, from ~/.ssh or a file. koi keys lists them, and koi keys rm removes one. |
| koi skus [gpu] | What can be launched right now, and for how much. |
| koi spawn <gpu> | Starts a machine, waits for it, and prints how to log in. h100 is one GPU, h100:8 is eight. --ttl 2h stops it by itself. |
| koi again <machine> | Starts another with the same settings. Koi doesn’t keep environment variable values, so it asks for those. |
| koi watch <gpu> | Emails you once, when a sold-out GPU is free. --drift for spare capacity, --stop to stop waiting. |
| koi ls | What’s running, with its cost so far. --all includes what has ended. |
| koi show <machine> | Everything about one machine, by name or id. |
| koi ssh <machine> | Logs in. |
| koi release <machine> | Stops billing, and deletes the machine and its disk. |
| koi balance | Credit left. |
04Drift
Drift is a machine on spare capacity, at about half the price. When the capacity is needed back, your machine is reclaimed at once, without notice, and billing stops at that moment. The machine goes with its disk, so write checkpoints often to somewhere that outlives it. A Drift machine reclaimed before it’s ready costs nothing.
On machines that support it, resume_after_reclaim keeps the disk instead. The machine shows as paused, with the GPU unbilled and the disk still billed, until capacity returns and its container restarts. If that takes more than a day, the machine and disk are deleted.
curl https://console.koicompute.co/api/v1/instances \
-H "Authorization: Bearer $KOI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"sku": "h100-8x", "spot": true, "container": "ghcr.io/acme/trainer:v3", "resume_after_reclaim": true}'05Containers
Give a machine a public container image and it starts after boot, with GPU access. state says running before the container is up, and /var/log/koi-container.log on the machine shows how it’s going. Images without GPU drivers can’t run a container.
Pass secrets like a Hugging Face token as environment variables, with env on the API, --env NAME=value on the CLI (or just --env NAME to take it from your shell), or the box on the launch form. Koi hands the values to the machine and keeps only their names, so launching again asks for them again.
With stop_when_done, the machine and its disk are deleted when the container exits, so a finished job stops costing money, and we email you how it ended and what it cost. The instance keeps exit_code and the end of the output in container_log. An exit code of -1 means the container never started.
06Disks
Each machine comes with a disk, of the size in disk_gb, deleted with it. Disks are billed by the second, at disk_price_per_hour, until they’re deleted.
A standard disk ($0.08 per GB-month) has no redundancy, so its data is lost if the hardware fails. A redundant disk ($0.15 per GB-month) is mirrored to three drives, and isn’t on every machine. Neither outlives the machine.
07Billing
You pay by the second, from when the provider has your machine running until you ask it to stop or it’s reclaimed. A launch that never becomes ready costs nothing. A running machine’s price doesn’t change, whatever happens to prices after you launch it.
We email you when what’s running has under two hours of credit left. When your balance reaches zero, every machine stops and its disk is deleted, and we email you to say so.
Automatic top-ups charge a saved card when your credit falls below a level you choose while something’s running, up to five times in 24 hours, so a missed email can’t stop your machines. Turn them on under Billing.
Stop after ends a machine by itself after a time you set, so a forgotten one can only cost so much. Its disk goes with it.
Spending limits cap what a key’s machines may cost, in all, for handing a key to a script or an agent. A launch needs an hour under the limit, and machines stop when they reach it. Set one on the Keys page. A key can’t raise its own.
08API reference
The base URL is https://console.koicompute.co/api/v1. Send your key as Authorization: Bearer koi_…. Money is in dollars, as strings, like "1.990000". An error is { "error": { "message": "…" } }, with a message you can show to a person.
Endpoints
| Endpoint | What it does |
|---|---|
| GET /skus | What can be launched right now: regions, images, specs, prices and whether a machine is free. |
| GET /instances | Your machines, newest first. |
| POST /instances | Starts one and returns 201. Poll it until it’s running. |
| GET /instances/:id | One machine. |
| DELETE /instances/:id | Stops billing now and deletes the machine and its disk. |
| GET /balance | Credit left, with usage so far taken off. |
| GET /watches | The sold-out GPUs you’ve asked to hear about. |
| POST /watches | Emails you once, when this GPU is next free, from sku and an optional spot. It’s a heads-up, not a reservation. |
| DELETE /watches | Stops waiting, from the same fields. |
| GET /ssh-keys | Your SSH keys, newest first. |
| POST /ssh-keys | Adds one, from public_key and an optional name. Returns 201. |
| DELETE /ssh-keys/:id | Stops new machines accepting it. Machines already running still do. |
Launching: POST /instances
| Field | What it does |
|---|---|
| sku | Required. An id from /skus, like h100-1x or h100-8x. |
| name | Up to 64 characters. Defaults to the SKU. |
| region | A region from the SKU’s regions, like eu-north. Defaults to wherever’s cheapest with capacity. |
| spot | true launches on Drift. |
| image | An image id from the SKU’s images. Defaults to the first it can boot that has a machine free. |
| container | A public container image to run after boot, like ghcr.io/acme/trainer:v3. |
| stop_when_done | true deletes the machine when its container exits. Needs container. |
| resume_after_reclaim | true keeps a reclaimed Drift machine’s disk and brings it back. Needs spot and container. |
| redundant_disk | true mirrors the disk to three drives, for more. |
| min_memory_gb | Rules out machines with less memory than this. |
| env | Environment variables for its container, as an object, like { "HF_TOKEN": "…" }. Koi keeps only their names, in env_keys. |
| stop_after_minutes | Stops the machine this long after it starts, and deletes its disk. It can overrun by a minute. stops_at says when. |
| ssh_key_ids | Which of your SSH keys to install. Defaults to all of them. |
Machine states
| State | What it means |
|---|---|
| provisioning | Starting. It’s billed once the provider has it running, which can be shortly before SSH answers. |
| running | SSH answers. ssh holds the command to log in with. |
| paused | A Drift machine waiting out a reclaim. The GPU isn’t billed, and the disk is. |
| terminating | Asked to stop. Billing has stopped, and the machine is being deleted. |
| terminated | Gone, with its disk. |
| failed | It never became ready, and wasn’t billed. error says why. |
Errors
| Status | What it means |
|---|---|
| 400 | Something in the request can’t work: a region the GPU isn’t in, an image it can’t boot, or no machine there that can do what you asked. |
| 401 | The API key is missing or isn’t valid. |
| 402 | Not enough credit for an hour of everything you’d be running. |
| 403 | The account is suspended. |
| 404 | No machine of yours has that id. |
| 409 | It would take you over your GPU limit. |
| 429 | Too many requests: 300 a minute per key, and 20 launch attempts a minute per account. Retry-After says how long to wait. |
| 503 | Sold out, or it couldn’t start. The message says what’s free instead, if anything is. |
The API calls machines instances, in its paths and fields. A SKU’s vcpus and memory_gb are the least you’d get. A machine’s say what it really has.
09Not built yet
Shoal (clusters), Current (serverless endpoints), Pond (storage that outlasts a machine) and a Python SDK aren’t available yet, so they aren’t documented here.