SSH/VNC, screenshots, snapshots, and the action surface
Connect & control
Connect & control, at a glance
SSH/VNC, screenshots, snapshots, and the action surface
POST /v1/machines/{id}/actions- 01Inspectconnection or screenshot
- 02Commandtyped operation
- 03Fenceownership + policy
- 04Receiptstructured result
SSH/VNC credentials apply only to Coasty-managed machines; the direct-control and agent-run surfaces support both managed and caller-owned external machines. Once a machine is running, you can drive it through Coasty's control endpoints or hand it to an agent run; managed machines can also be reached directly over SSH/VNC. Normal machine responses redact secrets and only expose has_ssh_key / has_vnc_password booleans plus ports.
Connection secrets. GET /v1/machines/{id}/connection returns the full ssh_private_key_pem, vnc_password, public IP, and ports. It is gated by the opt-in connection:read scope (not granted by default — request it when you mint the key), and the response is sent Cache-Control: no-store. Treat that payload like a password: never log it. SSH usernames are ubuntu on Linux and Administrator on Windows; VNC details exist only on desktop_enabled machines.
curl https://coasty.ai/v1/machines/$MACHINE_ID/connection \
-H "X-API-Key: $COASTY_API_KEY"Screenshots & snapshots. GET /v1/machines/{id}/screenshot returns the current screen of a desktop machine (a still-booting VM returns 502 SCREENSHOT_FAILED — poll for running first). An external response also returns a canonical frame_id for those exact pixels; a fresh capture is a safe read-only resynchronization and advances that frame. POST /v1/machines/{id}/snapshot captures a restorable image (Linux), needs the snapshots:write scope, and is the one machine op with a flat fee ($0.01 per snapshot). A conclusive pre-creation failure is refunded, confirmed by X-Credits-Refunded. A timeout, an upstream 5xx, or malformed post-dispatch result may already have created the image and instead returns terminal 503 SNAPSHOT_OUTCOME_UNKNOWN without a blind refund or re-execution. Boot a future machine from a confirmed snapshot with restore_from_snapshot: true.
The control surface. Drive the VM directly with these endpoints. Each enforces a specific scope, and the high-risk ones — browser_execute (arbitrary JS) and anything under connection:read — are opt-in. /actions/batch runs up to 50 steps and stops on the first error by default (stop_on_error: false to continue); /terminal truncates output to 5000 chars.
Strict command contracts. /actions is a 50-command discriminated API, not a free-form command tunnel. The selected command chooses an exact parameter schema; unknown keys, incomplete alias pairs, mixed mutually exclusive shapes, non-JSON values, and parameter objects over 1,000,000 bytes are rejected before dispatch. Discover the exact command list from GET /v1/models under machine_action_commands, and generate validators from the OpenAPI ActionRequest.oneOf catalog.
POST /v1/predict), and send one action with that frame_id as precondition_frame_id. The driver rechecks the screen immediately before OS input and atomically returns the post-action screenshot, new frame_id, and observation_available. If pixels are unavailable after a committed mutation, capture again and re-plan; never repeat the mutation just to recover an image. Prefer single actions over external GUI batches because a future step cannot safely name a frame that does not exist yet. Missing mutation frames return 409 FRAME_PRECONDITION_REQUIRED; stale frames return 409 FRAME_PRECONDITION_MISMATCH or a typed unsuccessful device result.curl -X POST https://coasty.ai/v1/machines/$MACHINE_ID/terminal \
-H "X-API-Key: $COASTY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"command": "ls -la /home/ubuntu"}'Idempotency & safety. The machine operations in the exact reserve-and-replay set — provision, snapshot, actions, action batches, browser, terminal, and file operations — accept an Idempotency-Key (≤128 chars). Lifecycle start/stop/restart, TTL updates, and termination do not. For supported operations, a duplicate key replays the original result without re-executing; a duplicate that arrives while the first is still running waits up to ~25s, then returns 409 IDEMPOTENCY_IN_FLIGHT. One nuance worth knowing: a command that never reached the VM (a dispatch failure) is not cached, so retrying the same key runs it fresh; a command the VM actually ran (even if it errored) is cached. Screenshot pixels are response-only and are never kept in the generic replay cache. A replay does not execute again: it retains frame_id, but returns screenshot: null and observation_available: false. Every machine lookup is ownership-scoped, so a wrong or someone-else's id returns 404 — never a leak. Full code list in Errors.
422 IDEMPOTENCY_KEY_REUSED. Rotating the owner API key starts a new replay namespace. External-machine enrollment is intentionally account-scoped so an exact enrollment replay can recover its device token after key rotation. BYOK-capable operations also bind the non-secret effective provider, model roles, and one-way key fingerprint; plaintext provider keys never enter the replay hash.