Skip to main content
A rental moves through five statuses. Getting the transitions right is most of what a correct integration does.
provisioning and running and stopping are all live: each occupies a slot under the concurrency ceiling.

Polling

Loop while the status is provisioning, not while it is not running. The second version spins forever on a failed rental — the most common bug in a first integration, and one that only shows up on a bad day.
Poll every two to three seconds. Provisioning takes tens of seconds; polling five times a second spends your whole rate limit to learn the same thing.

Two traps worth stating plainly

POST /rentals returns immediately with provisioning. The machine does not exist yet, access is null, and nothing is reachable. Everything after the create call has to wait for running.
POST /rentals/{id}/stop returns stopping. Teardown is asynchronous and the final charge is computed when the machine is actually gone.Two consequences:
  • billing.accrued_cents is not final until the status is stopped.
  • The rental still occupies a concurrency slot. Stop one and immediately start its replacement, and you can hit max_active_rentals_reached with what feels like a single machine.
Poll until stopped before doing either.

Why it ended

Once a rental leaves running, termination_reason says why:

When it never came up

status: "failed" means the machine never became usable. Nothing is charged for a failed rental. failure_code says what to do next:
The machine was allocated but never came up. Retry, or pick another offer — retrying the same offer is reasonable once, since this is often a single bad host.
The capacity disappeared during start-up. Retry with backoff; prefer a different offer if it happens twice.
Our fault. Quote the rental id to support.
We do not publish the upstream’s error text. It names infrastructure this API deliberately keeps out of view, and its wording changes without notice — so a handler written against it would break silently. The three codes above are stable and are what you should branch on.

The event history

Rather than diffing polled objects to work out what happened, read the history:
Append-only, oldest first, cursor-paginated. Events are pruned after 90 days. data holds the rental as it looked when the event was recorded. History is not rewritten by today’s serializer, so an old event may lack fields added since — read it defensively.
These are the same event names webhook deliveries will carry. A handler written against this list keeps working when webhooks ship, so it is worth shaping your code around events now rather than around polled diffs.