provisioning and running and stopping are all live: each occupies a slot
under the concurrency ceiling.
Polling
Two traps worth stating plainly
`201 Created` does not mean ready
`201 Created` does not mean ready
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.`stopping` does not mean stopped
`stopping` does not mean stopped
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_centsis not final until the status isstopped.- The rental still occupies a concurrency slot. Stop one and immediately start
its replacement, and you can hit
max_active_rentals_reachedwith what feels like a single machine.
stopped before doing either.Why it ended
Once a rental leavesrunning, 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:
provisioning_failed
provisioning_failed
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.
internal_error
internal_error
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: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.