Skip to main content
Renting is two calls: an optional quote, then the create.

Quote first

Requires rentals:read. It reads your balance to fill in sufficient_balance, which is why it is not merely catalog:read — and it changes nothing, which is why it is not rentals:write.
string
required
From /offers.
integer
default:"1"
Must be at least 1, and no more than the offer’s max_gpus. An out-of-range value is rejected, not silently clamped — quietly pricing a different rental than the one you asked about would be worse than an error.
'on_demand' | 'spot'
default:"on_demand"
number
Planned duration, used only to compute estimated_total_cents. It does not cap, schedule or reserve anything — a rental runs until you stop it.
integer
required
For the whole rental at this size — unlike /offers, which quotes per GPU. This is the number to show a user.
integer
required
What we reserve on your balance when the rental starts. Not a charge and not a cap — see Holds.
boolean
required
Whether this can start right now. A snapshot, not a reservation.
boolean
required
Whether your balance covers hold_cents at quote time.
A quote reserves nothing and costs nothing. Capacity and price can both move between the quote and the create. available: true can still lose the race, and your create can still come back offer_unavailable. Treat a quote as an estimate to show a human, never as a promise to your scheduler.
Skip the quote entirely in an automated path — it is a round trip that guarantees nothing. Its value is in a UI, where a person is about to click a button and deserves to see the number first.

Create

Requires rentals:write and a live key. Idempotency-Key is mandatory — see Idempotency.
string
required
integer
default:"1"
At least 1, at most the offer’s max_gpus.
'on_demand' | 'spot'
default:"on_demand"
spot is cheaper and can be reclaimed at any time, ending the rental with termination_reason: preempted. Not for work that cannot be interrupted.
string
Up to 64 characters. Your label, shown back to you here and in the dashboard. Worth setting — sweep-run-14 beats rnt_8h2k4m when you are looking at a list of nine machines wondering which one to stop.
string
The environment to boot. Omit for the default image. An unknown id is 400 invalid_template.
string
Authorised on the machine in addition to the keys already on your account.Supply one when the rental is driven by automation that should not depend on dashboard state: a CI job that generates an ephemeral keypair per run does not want its access to hinge on which keys someone left in the account settings.
The response is a rental with status: "provisioning" and access: null. It is not ready.

Every way it can be refused

The distinction that matters most is 409 offer_unavailable versus 503 capacity_unavailable:
  • offer_unavailable is about this offer — no free capacity at this size, or the seller withdrew it. Retrying it will keep failing. Pick another offer.
  • capacity_unavailable is ours and temporary — capacity we expected was not there. No rental was created. Retry the same request with backoff.
Every 402 is a billing_error: well-formed, permitted, unpayable. Retrying unchanged will never succeed. This is the single most common mishandled case in a scheduler, because a 402 looks transient and is not.

A create that handles reality

Note what it does with the idempotency key: the same key across retries of one offer, a fresh key for the next offer. Retrying with a new key would risk two machines; carrying one key across different offers would earn idempotency_key_reused, since the body changed.