Skip to main content

Errors

Any response outside the 2xx range carries a JSON body. Branch on code, never on message — messages are written for humans and can be reworded.

The envelope

{
"detail": {
"code": "INSUFFICIENT_BALANCE",
"message": "Add credits before deploying an instance",
"balance_microusd": 0,
"required_microusd": 2290000
}
}
KeyTypeMeaning
detail.codestringStable, uppercase, safe to branch on
detail.messagestringOne-line human explanation
Extra keysvariesContext for that specific failure

Two failures use a different shape. Request validation errors from the framework put a list under detail, one entry per bad field:

{"detail": [{"type": "greater_than_equal", "loc": ["body", "disk_gb"], "msg": "Input should be greater than or equal to 10"}]}

And an unexpected server-side failure puts a plain string there, such as {"detail": "Internal Server Error"}. Handle all three forms if you are writing a client library.

HTTP statuses

StatusMeaning
200The request succeeded
201Something was created — an instance, a template copy, an API key
204Succeeded with no body: revoking a key, deleting an SSH key
400The request is malformed, such as an X-Org-Id that is not an id
401The bearer token is missing, invalid, expired, revoked, or an API key on an account endpoint
402The organization has no credit left
403You are authenticated but not allowed: admin-only action, wrong organization, or an immutable object
404Not found, or not visible to your organization — the two are deliberately indistinguishable
409The state conflicts: the offer is taken, the instance is in the wrong status, the name is used
422The values are wrong: a field out of range, a disk larger than the machine, an unknown enum value

What a renter actually hits

ConditionStatusCodeWhat to do
Deploying or starting with an empty balance402INSUFFICIENT_BALANCEAn admin adds credits in the console. The body carries balance_microusd and required_microusd. API keys cannot top up.
The offer was rented between your list call and your deploy409OFFER_UNAVAILABLETake the next offer from your filtered list and retry. Do not retry the same offer_id.
The machine is booked offline sooner than an instance can be started on it409MACHINE_IN_MAINTENANCEThe body carries next_maintenance. Deploy elsewhere, or wait for the window to pass. This is not a capacity problem — the machine has free GPUs — so retrying the same offer works once the window is over.
disk_gb outside 10–20000422validation listSend a value inside the range
disk_gb larger than the host's disk422DISK_TOO_LARGEThe body carries max_disk_gb. Retry at or below it, or pick a bigger machine.
Admin-only action, or any admin action attempted with an API key403ADMIN_REQUIREDUse a session token belonging to an admin. Checkout, invites and member management are never available to keys. See Roles and permissions.
Revoking a key that is unknown, already revoked, or in another organization404API_KEY_NOT_FOUNDRe-list GET /v1/api-keys and use a current id
Stopping, starting or destroying from a status that forbids it409INVALID_STATERead status first. The message names the current one, for example Cannot start an instance while it is running.
A vm template on a machine that is not VM-capable422OFFER_NOT_VM_CAPABLEFilter for offers whose vm_capable is true
An ssh_key_id that is not on your account404SSH_KEY_NOT_FOUNDList GET /v1/ssh-keys with a session token and use one of those ids
An instance, offer or template your organization cannot see404INSTANCE_NOT_FOUND, OFFER_NOT_FOUND, TEMPLATE_NOT_FOUNDCheck the X-Org-Id you sent, and that the object still exists

Authentication and organization failures — TOKEN_INVALID, TOKEN_EXPIRED, NOT_A_MEMBER, ORG_MISMATCH, INVALID_ORG_ID — are covered in Authentication. The complete list of codes is in Error codes.

Retrying

ResponseRetry?
402No. Nothing changes until credits arrive.
409 OFFER_UNAVAILABLEYes, with a different offer.
409 MACHINE_IN_MAINTENANCEYes, with a different machine — or with the same one after next_maintenance.
409 INVALID_STATEOnly after re-reading the instance and confirming the transition is now legal.
422No. Fix the request first.
401 TOKEN_EXPIREDYes, once, with a fresh session token. An shk_ key does not expire, so a 401 on a key means it was revoked.

POST /v1/instances takes no idempotency key, so a timeout leaves you unsure whether the rental happened. Resolve it by looking, not by retrying: GET /v1/instances and match on your label.

Retrying the same offer_id is not safe. An offer is a shape, not a single slot — a machine with GPUs left answers the same offer again and you get a second instance, billed separately, from one intended deploy. It only 409s once that machine's units are gone, which is exactly the case where you were not double-charged anyway.