Act on an environment
Supported actions:
rotate-token— generate fresh per-VM credentials, upload them to the guest filesystem, and persist the orchestrator’s encrypted copy. Returns 204. Note: the running fused process reads its token once at startup and keeps serving the old token until it is restarted; rotation currently takes full effect only after the guest agent restarts.drain— first phase of two-phase teardown. Runs the environment’s configured drain command inside the guest (default: the fused drain command) so in-guest workloads quiesce gracefully; an empty drain command only transitions the state. The VM transitions todrainingbut is not destroyed; a subsequent DELETE tears it down. Only running VMs can be drained — any other state returns 409. If the drain command fails the VM remains indrainingso the caller can still DELETE; the failure is returned as 5xx.fork— create a new environment seeded from a checkpoint of this one. Withreuse_snapshot_idempty the server snapshots the source first; otherwise it reuses that ready snapshot (it must belong to this VM). The fork is pinned to the source’s host, receives its own guest credentials (fused is restarted), and is returned as a new Environment with 201. GPU environments (spec.gpus > 0, including MIG) and QEMU-hosted environments cannot be forked: a vfio device cannot be checkpointed, so the request returns 409conflict. That is a permanent property of the environment and must not be retried.exec— run a single command inside the guest and return its exit code, stdout, and stderr. Takes an ExecEnvironmentRequest body and returns an ExecEnvironmentResponse. See the exit-code contract below.
Exec: a non-zero exit code is not an HTTP error. A guest
command that exits non-zero comes back as 200 with that
code in exit_code. The command ran, and it failed; that is the
answer the caller asked for, not a transport failure. Clients
and SDKs must surface it as a value and must not raise on it.
HTTP errors are reserved for the cases where the command could not be run at all:
- 400
invalid_argument— neithercmdnorshellwas set, or both were. - 403
unauthorized— exec requires the master token. API keys are refused: exec is root in the guest, and keys carry no scopes today. - 404
not_found— unknown VM. - 409
conflict— the VM is not running (e.g. draining). - 501
unimplemented— the provider has no guest to exec into (e.g. the in-memory stub).
Fork error mapping. Fork returns 409 conflict for three
distinct preconditions:
- the reused snapshot (
reuse_snapshot_id) is not in stateready; - the source holds a GPU passthrough device (permanent — do not retry);
- with
reuse_snapshot_idempty, the implicit seed snapshot is refused because the snapshot quota (count or bytes) is exhausted. This 409 has nothing to do with a reused snapshot’s state, so do not infer the cause from the status code alone.
404 covers an unknown VM or snapshot, including a reused snapshot that is no longer present on the host.
Known limitation: the remaining fork and rotate-token
precondition failures — source VM not running, and a provider
with no fork support — still return 500 internal rather than
409/501. Treat the message, not the status code, as the contract
until these move to 4xx.
/v1/environments/{vmId}AuthorizationBearer token · headerrequiredfuse_sessionAPI key · cookierequiredvmIdstringrequiredactionstringrequiredrotate-tokendrainforkexecapplication/jsoncmdstring[]shellstringtimeout_msintegerreuse_snapshot_idstringcommentstringidstringrequiredstatestringrequiredprovisioningrunningdrainingdestroyingtask_idstringrequiredhost_idstringurlstringrequiredspecResourceSpecrequiredShow propertiesHide properties
cpusinteger<int32>ram_mbinteger<int32>storage_gbinteger<int32>gpusinteger<int32>gpu_kindstringgpu_profilestringimagestringregionstringhost_idstringlabelsobjectmax_runtime_secondsinteger<int64>idle_timeout_secondsinteger<int64>created_atstring<date-time>requiredupdated_atstring<date-time>requirederrorstringendpointsEndpoint[]Show propertiesHide properties
EndpointasstringurlstringrequiredportintegerrequiredhealthobjectShow propertiesHide properties
statestringrequiredstartingpassingfailingsincestring<date-time>failuresintegermessagestringexit_codeintegerrequiredstdoutstringrequiredstderrstringrequiredidstringrequiredstatestringrequiredprovisioningrunningdrainingdestroyingtask_idstringrequiredhost_idstringurlstringrequiredspecResourceSpecrequiredShow propertiesHide properties
cpusinteger<int32>ram_mbinteger<int32>storage_gbinteger<int32>gpusinteger<int32>gpu_kindstringgpu_profilestringimagestringregionstringhost_idstringlabelsobjectmax_runtime_secondsinteger<int64>idle_timeout_secondsinteger<int64>created_atstring<date-time>requiredupdated_atstring<date-time>requirederrorstringendpointsEndpoint[]Show propertiesHide properties
EndpointasstringurlstringrequiredportintegerrequiredhealthobjectShow propertiesHide properties
statestringrequiredstartingpassingfailingsincestring<date-time>failuresintegermessagestringerrorobjectrequiredShow propertiesHide properties
codestringrequirednot_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedmessagestringrequireddetailsobjecterrorobjectrequiredShow propertiesHide properties
codestringrequirednot_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedmessagestringrequireddetailsobjecterrorobjectrequiredShow propertiesHide properties
codestringrequirednot_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedmessagestringrequireddetailsobjecterrorobjectrequiredShow propertiesHide properties
codestringrequirednot_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedmessagestringrequireddetailsobjecterrorobjectrequiredShow propertiesHide properties
codestringrequirednot_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedmessagestringrequireddetailsobjecterrorobjectrequiredShow propertiesHide properties
codestringrequirednot_foundroute_not_foundconflictinvalid_argumentunauthorizedforbiddenunavailableinternalunimplementedmessagestringrequireddetailsobjectcurl -X POST "http://localhost:8080/v1/environments/string?action=rotate-token" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"cmd": [
"ls",
"-l"
],
"timeout_ms": 5000
}'const response = await fetch("http://localhost:8080/v1/environments/string?action=rotate-token", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
},
body: JSON.stringify({
"cmd": [
"ls",
"-l"
],
"timeout_ms": 5000
})
});import requests
response = requests.post(
"http://localhost:8080/v1/environments/string?action=rotate-token",
headers={
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
},
json={
"cmd": [
"ls",
"-l"
],
"timeout_ms": 5000
},
){
"id": "string",
"state": "provisioning",
"task_id": "string",
"host_id": "string",
"url": "string",
"spec": {
"cpus": 0,
"ram_mb": 0,
"storage_gb": 0,
"gpus": 0,
"gpu_kind": "string",
"gpu_profile": "string",
"image": "string",
"region": "string",
"host_id": "string",
"labels": {},
"max_runtime_seconds": 0,
"idle_timeout_seconds": 0
},
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z",
"error": "string",
"endpoints": [
{
"as": "string",
"url": "string",
"port": 0
}
],
"health": {
"state": "starting",
"since": "2024-01-01T00:00:00Z",
"failures": 0,
"message": "string"
}
}{
"id": "string",
"state": "provisioning",
"task_id": "string",
"host_id": "string",
"url": "string",
"spec": {
"cpus": 0,
"ram_mb": 0,
"storage_gb": 0,
"gpus": 0,
"gpu_kind": "string",
"gpu_profile": "string",
"image": "string",
"region": "string",
"host_id": "string",
"labels": {},
"max_runtime_seconds": 0,
"idle_timeout_seconds": 0
},
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z",
"error": "string",
"endpoints": [
{
"as": "string",
"url": "string",
"port": 0
}
],
"health": {
"state": "starting",
"since": "2024-01-01T00:00:00Z",
"failures": 0,
"message": "string"
}
}{
"error": {
"code": "not_found",
"message": "string",
"details": {}
}
}{
"error": {
"code": "not_found",
"message": "string",
"details": {}
}
}{
"error": {
"code": "not_found",
"message": "string",
"details": {}
}
}{
"error": {
"code": "not_found",
"message": "string",
"details": {}
}
}{
"error": {
"code": "not_found",
"message": "string",
"details": {}
}
}{
"error": {
"code": "not_found",
"message": "string",
"details": {}
}
}