Skip to content

Concepts

Operations and idempotency

How VMYard accepts a change, carries it out, reports the truth about the result, and makes retries safe.

On this page

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.

202 Accepted
{
  "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.

StatusMeaning
pendingAccepted and queued.
runningA worker is carrying it out.
succeededDone, and VMYard observed the requested result on the machine's host.
failedIt definitely did not happen. error_code says why.
uncertainThe outcome could not be confirmed yet. VMYard retries it with the exact same request until it settles.
correlation_missThe 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.
sh
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, and 504; they retry mutations only on 429 and 503, always with the same key, and honour Retry-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.