Concepts
Operations and idempotency
How VMYard accepts a change, carries it out, reports the truth about the result, and makes retries safe.
Every change to a machine (create, start, stop, restart, delete, running a command, writing a file, exposing a port, installing an SSH key, changing internet access) is an operation. The API answers 202 Accepted right away and a worker carries out the change in the background.
{
"operation_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"machine_id": "0b6f6c55-2f1d-4f0e-9a51-6f0f4cba7a10",
"status": "pending",
"operation_url": "/v1/operations/6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"requested_action": "create"
}Following an operation
Poll GET /v1/operations/{id} until status is terminal, or stream GET /v1/operations/{id}/events as server-sent events. The event stream replays the persisted history first, then live events; send Last-Event-ID to resume after a disconnect.
| Status | Meaning |
|---|---|
pending | Accepted and queued. |
running | A worker is carrying it out. |
succeeded | Done, and VMYard observed the requested result on the machine's host. |
failed | It definitely did not happen. error_code says why. |
uncertain | The outcome could not be confirmed yet. VMYard retries it with the exact same request until it settles. |
correlation_miss | The work finished but the observed machine did not match what was asked for. Treat it as not done. |
succeeded, failed, and correlation_miss are terminal. The SDKs and vy … --wait poll for you (250 ms, growing to 2 s, for up to 10 minutes) and raise an error for anything but succeeded. They raise on uncertain too; replaying the same request with the same idempotency key is safe and picks the operation up again. A wait that times out does not cancel the operation.
Ordering
Operations on one machine run one at a time, in the order they were accepted. A long command on one machine never delays another machine.
Idempotency keys
Send a unique Idempotency-Key header with every request that creates an operation. The key is scoped to your organization.
- Repeating a request with the same key and the same body returns the original operation instead of doing the work again. This is how you recover from a timeout or a dropped connection: retry with the same key.
- Using a key again with a different body is refused with
409 idempotency_conflict. For creates this includes the name, auto-stop, idle sleep, and setup script. - A new key is a new request.
KEY=$(uuidgen)
curl -X POST "$VMYARD_API_URL/v1/machines/$MACHINE_ID/stop" \
-H "Authorization: Bearer $VMYARD_API_KEY" \
-H "Idempotency-Key: $KEY" \
-H "Content-Type: application/json" -d '{}'
# Safe to repeat with the same $KEY: you get the same operation back.The SDKs generate a UUID key for every mutation and reuse it when they retry. Pass your own (idempotencyKey / idempotency_key) when you need to retry across process restarts.
Settings changes (PATCH /v1/machines/{id}), port access tokens, environments, webhooks, API keys, billing, and sign-in routes are not operations and take no idempotency key; they answer synchronously. Upgrading an environment creates operations, but its keys are derived from the version and the machine, so repeating the request replays them.
Retries
- Retry reads freely.
- Retry a mutation only with the same idempotency key and body.
- The SDKs retry reads on connection errors and
408,429,502,503, and504; they retry mutations only on429and503, always with the same key, and honourRetry-After.
Operation results
A terminal operation keeps its result. Exec operations carry exec_result (exit code, base64 output, and timed_out, cancelled, truncated). A completed file read carries file_ranges. A stop carries stop_reason: api when a caller asked for it, or auto_stop, billing, idle_sleep, suspension, or abuse when VMYard stopped the machine itself (auto-stop, an exhausted balance, idle sleep, a suspension of the organization, or the guard against sustained full CPU use on trials); other kinds have null. See Running commands and Files.