Machines
A machine is a Linux computer of your own, reached through the API. It runs your commands and keeps your files, and it is charged by the second while it runs.
wm
$ wm machines create --name trainer --cpus 8 --label team=ml --idle-after 30m
ID NAME STATE SIZE LOCATION AGE
m_01jb2xk3n4p5q6r7s8t9v0w1x2 trainer running 8 CPU, 16 GB Helsinki, FI 0sPython
machine = client.machines.create(
name="trainer", cpus=8, labels={"team": "ml"}, idle_after_s=1800
)
print(machine.id, machine.state)TypeScript
const machine = await client.machines.create({
name: "trainer", cpus: 8, labels: { team: "ml" }, idle_after_s: 1800,
});
console.log(machine.id, machine.state);curl
curl -X POST https://api.wheelmachine.ai/v1/machines \
-H "Authorization: Bearer $WHEELMACHINE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "trainer", "cpus": 8, "labels": {"team": "ml"}, "idle_after_s": 1800}'States#
pause, stop and archive put a
machine away, each keeping more or less of it; start brings it back. delete ends it from
any state.Being made ready. When no server has room at once, one is made ready
for it: the answer is 202, and a wait follows it until it runs.
It runs; commands and files work. Charged by the second.
Its memory is kept and nothing runs; no running time is charged. A
command wakes it, and so does start: it carries on where it was.
Its files are kept, its memory is not. start runs it
again from its files.
Its files are put away in storage: the cheapest way to keep a
machine. start brings it back.
Its server was lost, and it is being brought back from its last
moments. Wait for running.
Gone, with its files. Deleting cannot be undone.
| To | wm | API |
|---|---|---|
| Pause it | wm machines pause <machine> | POST /v1/machines/{machine_id}/pause |
| Run it again | wm machines start <machine> | POST /v1/machines/{machine_id}/start |
| Stop it | wm machines stop <machine> | POST /v1/machines/{machine_id}/stop |
| Archive it | wm machines archive <machine> | POST /v1/machines/{machine_id}/archive |
| Delete it | wm machines rm <machine> | DELETE /v1/machines/{machine_id} |
A move its state does not allow, such as pausing a machine that is not running, answers
409 conflict.
Sizes#
A machine has 2, 4, 8 or 16 CPUs, with 2 GB of memory for each. It is charged by the second at the 2-CPU price that many times over: a 16-CPU machine costs eight times a 2-CPU one.
| CPUs | Memory | wm | API |
|---|---|---|---|
| 2 (when not said) | 4 GB | --cpus 2 | "cpus": 2 |
| 4 | 8 GB | --cpus 4 | "cpus": 4 |
| 8 | 16 GB | --cpus 8 | "cpus": 8 |
| 16 | 32 GB | --cpus 16 | "cpus": 16 |
The size is chosen when the machine is made, and a copy has its original's size.
Coming Machines with a GPU. They are not open to every account
yet; wm gpus shows what is coming.
Sleep when idle#
A machine pauses by itself once it is idle: nothing has reached it for idle_after_s seconds (300,
five minutes, when not said), and its programs have been quiet as long, under 5% of one CPU on average. A job left
working keeps it awake. Paused, it keeps its memory and no
running time is charged; the next command wakes it.
wm
$ wm machines create --name nightly --idle-after 2h # 1m to 24h
$ wm machines create --name server --no-sleep # never pauses by itselfAPI
{"name": "nightly", "idle_after_s": 7200}
{"name": "server", "sleep_when_idle": false}idle_after_s is 60 to 86400 seconds. A machine made with sleep_when_idle false never
pauses by itself: it runs, and is charged, until it is paused or stopped. Both are set when the machine is made; a
copy sleeps as its original does. The machine says how it sleeps in sleep_when_idle and
idle_after_s (null when it never does).
Wait for it#
Making, starting or copying a machine answers once it runs, usually in well under a second. When no server has
room just now, one is made ready for it; if that takes longer than wait_s (60 seconds when not said,
at most 600), the answer is 202 with the machine starting, and a wait follows it:
wm
$ wm machines wait box # until it runs, for up to 10 minutes
$ wm machines wait box --state paused --timeout 2mPython
machine = client.machines.wait(machine.id, "running", timeout_s=600)TypeScript
const ready = await client.machines.wait(machine.id, "running", { timeout_s: 600 });curl
curl "https://api.wheelmachine.ai/v1/machines/m_01jb2xk3n4p5q6r7s8t9v0w1x2/wait?state=running&timeout_s=120" \
-H "Authorization: Bearer $WHEELMACHINE_API_KEY"One wait call lasts at most 600 seconds; a machine not there by then answers
408 timeout, and you can wait again. wm and the libraries
wait for you; wm machines create --no-wait answers at once instead.
Copies#
$ wm machines copy box --name box-2
ID NAME STATE SIZE LOCATION AGE
m_01jb2xm7c9d4e8f2g6h1j5k3n0 box-2 running 2 CPU, 4 GB Helsinki, FI 0sA copy is a new machine, made from the original as it is now, files and all, beside it where there is room, so
its files are copied in a moment. It has the original's name and labels unless you give others
(--label gives the copy its own labels in place of the original's), and the original's size and sleep.
From then on it is a machine of its own: charged, paused and deleted on its own.
Snapshots#
$ wm machines snapshot box --note "before the upgrade"
SNAPSHOT MACHINE NOTE MADE
20261023T093500Z-3f2a0001 m_01jb2xk3n4p5q6r7s8t9v0w1x2 before the upgrade 2026-10-23 09:35 UTC
$ wm machines create --name box-again --from-snapshot box:20261023T093500Z-3f2a0001A snapshot keeps the machine's files as they are now. A new machine made from_snapshot starts with
those files; give the machine alone (--from-snapshot box) for its latest snapshot. Keep a snapshot's
id when it is made: the API does not list them.
Names and labels#
A machine's id is made by the API: m_ and 26 letters and digits. Its name is for people, up to 80
characters. wm takes a name wherever it takes an id; when two machines share a name, give the id.
$ wm machines label box team=ml stage=test # set two labels
$ wm machines label box stage- # take one off
$ wm machines ls --label team=ml # machines with that label
$ wm machines rename box trainerA machine holds up to 32 labels. A label's name begins with a letter or a digit and goes on with
letters, digits, ., _, - and /, up to 63 of them; its value is up to 200 characters. Through the API, labels
given to PATCH /v1/machines/{machine_id} merge with the ones there, and a label given
null is taken off.
Projects#
Every machine is in a project. An account starts with one, and machines go there unless another is named.
$ wm projects create research
$ wm machines create --name box --project research
$ wm machines ls --project researchA key can be limited to some projects, so a program sees only its own machines: see Keys for some projects. A project can be deleted only once it holds no machines.
Where it runs#
--region (region in the API) asks for a machine near a place: an id from
wm regions. It runs near there, wherever there is room soonest, and says where it actually runs in its
location.
Running time and money#
A machine is charged by the second while it runs. running_seconds is all the time it has run, and
wm usage (GET /v1/usage) says what each machine ran for and cost in a month:
$ wm usage --month 2026-10
MACHINE PROJECT RAN COST
m_01jb2xk3n4p5q6r7s8t9v0w1x2 prj_01jb2xk3n4p5q6r7s8t9v0w1x2 1h 38m $0.1312
total 2026-10 - - $0.1312When the account cannot spend - its limit for the month is reached, or the account is held - its running machines
are paused within about half a minute, with their memory kept, and making or starting machines, running commands and
reaching files answer 402 payment_required until it can again.
wm me says whether the account can spend.
Delete#
wm machines rm box asks first; --yes does not. Deleting takes the machine's files with
it and cannot be undone. Deleting a machine that is already deleted is not an error.
What a machine says about itself#
{
"id": "m_01jb2xk3n4p5q6r7s8t9v0w1x2",
"object": "machine",
"name": "trainer",
"project": "prj_01jb2xk3n4p5q6r7s8t9v0w1x2",
"state": "running",
"gpu": null,
"size": {"cpus": 8, "memory_gb": 16},
"location": {"city": "Helsinki", "country": "FI"},
"cpus": 8,
"memory_gb": 16,
"sleep_when_idle": true,
"idle_after_s": 1800,
"labels": {"team": "ml"},
"network": {"internet": "open", "allow": []},
"files_sealed": true,
"running_seconds": 5904.2,
"cpu_cores": 6.4,
"memory_bytes": 9126805504,
"created_at": "2026-10-23T09:30:00Z",
"last_used_at": "2026-10-23T11:08:24Z"
}Every field is in the reference: Machine.