---
title: "Execute a shell command"
method: POST
path: "/v1/machines/{machine_id}/terminal"
tags: ["machines"]
---

# Execute a shell command

`POST /v1/machines/{machine_id}/terminal`

Output truncated VM-side to 5000 chars. Hard cap 120s (Cloudflare edge timeout). Requires `terminal:exec` scope. An external terminal execution is a mutation and requires precondition_frame_id; use the direct action surface for terminal_read if a read-only operation is needed.

## Headers

- `Idempotency-Key` string

## Request body

- TerminalRequest
  - `command` string, required
  - `timeout_ms` integer
  - `session_id` string, nullable
  - `cwd` string, nullable
  - `precondition_frame_id` string, uuid, nullable — Required when executing this mutating terminal command on an external machine.

## Response `200`

Terminal output.

- ActionResultResponse
  - `machine_id` string, required
  - `command` string, required
  - `success` boolean, required
  - `result` object, nullable
  - `error` string, nullable
  - `duration_ms` integer, required
  - `screenshot` string, nullable — Typed post-action screenshot when the transport returns one. External-machine mutations commit this observation atomically with their result. Data URI or raw base64; never duplicated inside result. Screenshot pixels are not persisted in idempotency replay records.
  - `frame_id` string, uuid, nullable — Accepted post-action external observation identity. Use it as the next action's precondition_frame_id.
  - `observation_available` boolean, nullable — Whether screenshot pixels are present in this response. An idempotent replay may retain frame_id while returning screenshot=null and observation_available=false.
  - `request_id` string, required

## Other responses

- `400` — Invalid request body or parameters.
- `401` — Missing, invalid, or revoked API key. Pass `X-API-Key: sk-coasty-live-...` (or test).
- `402` — Insufficient balance for this operation. Direct metered API calls and managed-machine runtime use the prepaid Developer API wallet; scheduled execution is the documented consumer subscription-credit exception. Follow the operation's billing fields and top up the matching balance in the dashboard.
- `403` — API key lacks the required scope or tier-feature is unavailable on the caller's plan.
- `404` — Resource not found in this key's namespace.
- `409` — The resource state conflicts with this operation.
- `413` — The request body exceeds the endpoint limit.
- `422` — The JSON shape is valid but one or more values violate the endpoint contract.
- `429` — Rate or concurrency limit exceeded.
- `500` — Unexpected server error. Retry with exponential backoff.
- `502` — An upstream dependency returned an invalid response.
- `503` — A required service is temporarily unavailable.
- `504` — An upstream dependency timed out.

---

[API](https://skmtc.net/coasty/apis/coasty-public-api.md) · [All operations](https://skmtc.net/coasty/apis/coasty-public-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/coasty/coasty-public-api/versions/f50d93b0d8a1/schema)
