# Smol Machines — Orthogonal API > Pay-per-use API on Orthogonal. Each call is billed to your Orthogonal balance. > Base API: `https://api.orthogonal.com/v1/run` · [llms.txt](https://orthogonal.com/llms.txt) · [browse all APIs](https://orthogonal.com/discover) Cloud microVM platform. Create isolated Linux VMs, execute commands, run code, manage files and volumes. Each machine has its own kernel with configurable CPU, memory, networking, and storage. **Verified:** yes ## Access **Run API:** `POST https://api.orthogonal.com/v1/run` **Auth:** `Authorization: Bearer $ORTHOGONAL_API_KEY` Get an API key at https://orthogonal.com/dashboard/settings/api-keys Every call goes through the unified Run API: send the API `slug`, the endpoint `path`, and the `query`/`body` parameters. The response is `{ "success": true, "price": "", "data": { ... } }`. ## Endpoints ### Download File Download a file from a machine `GET /v1/machines/{id}/files` **Cost:** Free | Field | Type | Required | Description | |-------|------|----------|-------------| | `id` | string | Yes | Path parameter — substitute directly into the endpoint `path`. | ```bash # Replace {id} in "path" with real values before sending curl -X POST 'https://api.orthogonal.com/v1/run' \ -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \ -H 'Content-Type: application/json' \ -d '{"api":"smolmachines","path":"/v1/machines/{id}/files","method":"GET"}' ``` ### Upload File Upload a file to a machine `POST /v1/machines/{id}/files` **Cost:** Free | Field | Type | Required | Description | |-------|------|----------|-------------| | `id` | string | Yes | Path parameter — substitute directly into the endpoint `path`. | ```bash # Replace {id} in "path" with real values before sending curl -X POST 'https://api.orthogonal.com/v1/run' \ -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \ -H 'Content-Type: application/json' \ -d '{"api":"smolmachines","path":"/v1/machines/{id}/files"}' ``` ### List Sessions List sessions for a machine `GET /v1/machines/{id}/sessions` **Cost:** Free | Field | Type | Required | Description | |-------|------|----------|-------------| | `id` | string | Yes | Path parameter — substitute directly into the endpoint `path`. | ```bash # Replace {id} in "path" with real values before sending curl -X POST 'https://api.orthogonal.com/v1/run' \ -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \ -H 'Content-Type: application/json' \ -d '{"api":"smolmachines","path":"/v1/machines/{id}/sessions","method":"GET"}' ``` ### Create Session Create a persistent session that preserves working directory and environment across exec calls `POST /v1/machines/{id}/sessions` **Cost:** Free | Field | Type | Required | Description | |-------|------|----------|-------------| | `id` | string | Yes | Path parameter — substitute directly into the endpoint `path`. | | `cwd` | string | No | | | `env` | object | No | | | `id` | string | No | | ```bash # Replace {id} in "path" with real values before sending curl -X POST 'https://api.orthogonal.com/v1/run' \ -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \ -H 'Content-Type: application/json' \ -d '{"api":"smolmachines","path":"/v1/machines/{id}/sessions","body":{"cwd":"","env":"","id":""}}' ``` ### Delete Session Delete a session `DELETE /v1/machines/{id}/sessions/{session_id}` **Cost:** Free | Field | Type | Required | Description | |-------|------|----------|-------------| | `id` | string | Yes | Path parameter — substitute directly into the endpoint `path`. | | `session_id` | string | Yes | Path parameter — substitute directly into the endpoint `path`. | ```bash # Replace {id}, {session_id} in "path" with real values before sending curl -X POST 'https://api.orthogonal.com/v1/run' \ -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \ -H 'Content-Type: application/json' \ -d '{"api":"smolmachines","path":"/v1/machines/{id}/sessions/{session_id}","method":"DELETE"}' ``` ### Run Code Run Python or JavaScript code directly in a machine `POST /v1/machines/{id}/code` **Cost:** Free | Field | Type | Required | Description | |-------|------|----------|-------------| | `id` | string | Yes | Path parameter — substitute directly into the endpoint `path`. | | `code` | string | Yes | | | `cwd` | string | No | | | `env` | object | No | | | `language` | string | Yes | | | `timeoutSeconds` | number | No | | ```bash # Replace {id} in "path" with real values before sending curl -X POST 'https://api.orthogonal.com/v1/run' \ -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \ -H 'Content-Type: application/json' \ -d '{"api":"smolmachines","path":"/v1/machines/{id}/code","body":{"code":"","cwd":"","env":"","language":"","timeoutSeconds":""}}' ``` ### Session Exec Execute a command within a persistent session. Session preserves working directory and environment across calls. `POST /v1/machines/{id}/sessions/{session_id}/exec` **Cost:** Free | Field | Type | Required | Description | |-------|------|----------|-------------| | `id` | string | Yes | Path parameter — substitute directly into the endpoint `path`. | | `session_id` | string | Yes | Path parameter — substitute directly into the endpoint `path`. | | `command` | string | Yes | Shell command string (e.g. "echo hello") or argv array (e.g. ["echo","hello"]) | | `cwd` | string | No | Working directory for the command | | `env` | object | No | Environment variables as key-value pairs | | `stdin` | string | No | String to pass as stdin to the command | | `stream` | boolean | No | If true, stream output as server-sent events | | `timeoutSeconds` | number | No | Max execution time in seconds | ```bash # Replace {id}, {session_id} in "path" with real values before sending curl -X POST 'https://api.orthogonal.com/v1/run' \ -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \ -H 'Content-Type: application/json' \ -d '{"api":"smolmachines","path":"/v1/machines/{id}/sessions/{session_id}/exec","body":{"command":"","cwd":"","env":"","stdin":"","stream":"","timeoutSeconds":""}}' ``` ### Create Machine Create a new microVM. Minimal example: {"source":{"type":"image","reference":"alpine:3.20"},"resources":{"cpus":1,"memoryMb":512},"ttlSeconds":3600}. Poll GET /v1/machines/{id} until ready is true before running commands. `POST /v1/machines` **Estimated cost:** Dynamic — use `"dryRun": true` in the Run API request to check the exact cost before calling. | Field | Type | Required | Description | |-------|------|----------|-------------| | `source` | object | Yes | Image source. Example: {"type":"image","reference":"alpine:3.20"} | | `resources` | object | Yes | CPU and memory allocation. Example: {"cpus":1,"memoryMb":512} | | `ttlSeconds` | number | Yes | Max machine lifetime in seconds (e.g. 3600 for 1 hour) | | `name` | string | No | Human-readable machine name | | `network` | object | No | Network policy. Example: {"mode":"open"} or {"mode":"blocked"} | | `env` | object | No | Environment variables as key-value pairs | | `workdir` | string | No | Working directory inside the VM | | `autoStopSeconds` | number | No | Seconds of inactivity before auto-stop | | `ephemeral` | boolean | No | If true, machine is automatically deleted when stopped. Machine boots into running state and is cleaned up after stop or TTL expiry. | | `mounts` | array | No | Volume mounts for persistent storage | ```bash curl -X POST 'https://api.orthogonal.com/v1/run' \ -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \ -H 'Content-Type: application/json' \ -d '{"api":"smolmachines","path":"/v1/machines","body":{"source":"","resources":"","ttlSeconds":"","name":"","network":"","env":"","workdir":"","autoStopSeconds":"","ephemeral":"","mounts":""}}' ``` ### Machine Events Get machine event log `GET /v1/machines/{id}/events` **Cost:** Free | Field | Type | Required | Description | |-------|------|----------|-------------| | `id` | string | Yes | Path parameter — substitute directly into the endpoint `path`. | ```bash # Replace {id} in "path" with real values before sending curl -X POST 'https://api.orthogonal.com/v1/run' \ -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \ -H 'Content-Type: application/json' \ -d '{"api":"smolmachines","path":"/v1/machines/{id}/events","method":"GET"}' ``` ### Execute Command Run a command inside a machine. Pass command as a shell string ("ls -la") or argv array (["ls","-la"]). Machine must be ready before calling. `POST /v1/machines/{id}/exec` **Cost:** Free | Field | Type | Required | Description | |-------|------|----------|-------------| | `id` | string | Yes | Path parameter — substitute directly into the endpoint `path`. | | `command` | string | Yes | Shell command string (e.g. "echo hello") or argv array (e.g. ["echo","hello"]) | | `cwd` | string | No | Working directory for the command | | `env` | object | No | Environment variables as key-value pairs | | `stdin` | string | No | String to pass as stdin to the command | | `stream` | boolean | No | If true, stream output as server-sent events | | `timeoutSeconds` | number | No | Max execution time in seconds | ```bash # Replace {id} in "path" with real values before sending curl -X POST 'https://api.orthogonal.com/v1/run' \ -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \ -H 'Content-Type: application/json' \ -d '{"api":"smolmachines","path":"/v1/machines/{id}/exec","body":{"command":"","cwd":"","env":"","stdin":"","stream":"","timeoutSeconds":""}}' ``` ### Get Machine Get machine details and status. Poll until ready is true before executing commands. `GET /v1/machines/{id}` **Cost:** Free | Field | Type | Required | Description | |-------|------|----------|-------------| | `id` | string | Yes | Path parameter — substitute directly into the endpoint `path`. | ```bash # Replace {id} in "path" with real values before sending curl -X POST 'https://api.orthogonal.com/v1/run' \ -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \ -H 'Content-Type: application/json' \ -d '{"api":"smolmachines","path":"/v1/machines/{id}","method":"GET"}' ``` ### Start Machine Start a stopped machine `POST /v1/machines/{id}/start` **Cost:** Free | Field | Type | Required | Description | |-------|------|----------|-------------| | `id` | string | Yes | Path parameter — substitute directly into the endpoint `path`. | ```bash # Replace {id} in "path" with real values before sending curl -X POST 'https://api.orthogonal.com/v1/run' \ -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \ -H 'Content-Type: application/json' \ -d '{"api":"smolmachines","path":"/v1/machines/{id}/start"}' ``` ### Delete Machine Permanently delete a machine and its storage `DELETE /v1/machines/{id}` **Cost:** Free | Field | Type | Required | Description | |-------|------|----------|-------------| | `id` | string | Yes | Path parameter — substitute directly into the endpoint `path`. | ```bash # Replace {id} in "path" with real values before sending curl -X POST 'https://api.orthogonal.com/v1/run' \ -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \ -H 'Content-Type: application/json' \ -d '{"api":"smolmachines","path":"/v1/machines/{id}","method":"DELETE"}' ``` ### Stop Machine Stop a running machine. Preserves disk state. `POST /v1/machines/{id}/stop` **Cost:** Free | Field | Type | Required | Description | |-------|------|----------|-------------| | `id` | string | Yes | Path parameter — substitute directly into the endpoint `path`. | ```bash # Replace {id} in "path" with real values before sending curl -X POST 'https://api.orthogonal.com/v1/run' \ -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \ -H 'Content-Type: application/json' \ -d '{"api":"smolmachines","path":"/v1/machines/{id}/stop"}' ``` ### List Machines List all machines. Use to discover existing machine IDs for recovery or cleanup. `GET /v1/machines` **Cost:** Free _No parameters required._ ```bash curl -X POST 'https://api.orthogonal.com/v1/run' \ -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \ -H 'Content-Type: application/json' \ -d '{"api":"smolmachines","path":"/v1/machines","method":"GET"}' ``` --- Full details and an interactive quickstart: https://orthogonal.com/discover/smolmachines