omg/docs
Sandbox API

Quickstart

Create a sandbox from your own app — key, create, poll, connect.

This walks the whole path: get a key, create a sandbox, wait for it to boot, and connect. Every call is a plain HTTPS request authenticated with your API key.

1. Get a key

Create one at omg.dev/sandbox/keys and copy the omg_sk_… secret (shown once). See Authentication. Put it in your environment:

export OMG_API_KEY="omg_sk_…"

Use the SDK

From TypeScript, @omg-dev/sandbox wraps the same API:

bun add @omg-dev/sandbox
import { SandboxClient } from "@omg-dev/sandbox"

const client = new SandboxClient({
  baseUrl: "https://infra.omg.dev",
  token: process.env.OMG_API_KEY!,
})

const sandbox = await client.create({ templateId: "react-ts", ports: [5173] })

await sandbox.exec("echo", ["hello from a microVM"])
// → { stdout: "hello from a microVM\n", stderr: "", exitCode: 0 }

await sandbox.shell("cd /home/user/project && bun run build")
await sandbox.snapshot()
await sandbox.stop()

Server-side only — the client holds your API key. The SDK also ships a typed template baker; see Templates. The rest of this page is the same flow over raw HTTP.

2. Create a sandbox

POST /v1/sandboxes with an empty body starts a default sandbox (medium — 2 vCPUs / 2 GB). It returns immediately with the new sandbox's id and status. Sandbox creation requires a Pro or Max plan (402 otherwise).

This create picks a machine size and starts from the react-ts template — a ready-to-run Vite + React + TypeScript app with dependencies preinstalled:

curl -X POST https://infra.omg.dev/v1/sandboxes \
  -H "Authorization: Bearer $OMG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "size": "medium", "ports": [5173], "templateId": "react-ts" }'

size is small (1 vCPU / 1 GB), medium (2/2 GB), or large (4/4 GB). Instead of a template you can pass a coding-agent preset like { "template": "claude" } — see Templates.

{
  "id": "abc123def456",
  "status": "running",
  "cwd": "/home/user",
  "vmIP": "10.10.0.2",
  "portMap": { "41000": 5173 },
  "createdAt": "2026-07-07T13:00:00Z",
  "nodeId": "box-1"
}

API-key creates are raw programmatic sandboxes and list with kind: "api". If you store nodeId, pin follow-up calls with X-Vibes-Node: <nodeId>.

3. Poll until it's running

The microVM boots asynchronously, so wait for status: "running" before you connect. Poll the single-sandbox endpoint:

curl https://infra.omg.dev/v1/sandboxes/$SANDBOX_ID \
  -H "Authorization: Bearer $OMG_API_KEY"

In JavaScript, poll with a small backoff:

const BASE = "https://infra.omg.dev"
const auth = { Authorization: `Bearer ${process.env.OMG_API_KEY}` }

async function createAndWait() {
  // create
  const created = await fetch(`${BASE}/v1/sandboxes`, {
    method: "POST",
    headers: { ...auth, "Content-Type": "application/json" },
    body: "{}",
  }).then((r) => r.json())

  // poll until running (or provisioning fails)
  for (let i = 0; i < 60; i++) {
    const sb = await fetch(`${BASE}/v1/sandboxes/${created.id}`, {
      headers: auth,
    }).then((r) => r.json())
    if (sb.status === "running") return sb
    if (sb.status === "stopped") throw new Error("sandbox failed to boot")
    await new Promise((r) => setTimeout(r, 1000))
  }
  throw new Error("timed out waiting for sandbox")
}

4. List what you've got

GET /v1/sandboxes returns every sandbox your key owns, with status and usage:

curl https://infra.omg.dev/v1/sandboxes \
  -H "Authorization: Bearer $OMG_API_KEY"

5. Connect

Once a sandbox is running, connect however your workload needs:

  • Interactive shell — run the first-party bridge script with OMG_API_KEY set, or open a WebSocket to wss://ssh-ws.omg.dev/<id> with subprotocol vibes.shell.v1 and your key as vibes.api_key.<base64url(key)> (or an Authorization: Bearer omg_sk_… header / ?access_token=). Frames are binary, tagged by a leading byte (0 data, 1 control, 2 ping, 3 pong). Full handshake in the Reference.
  • Its own services — a sandbox that serves HTTP is reachable at its preview URL; GET /v1/sandboxes/{id}/url/{port} returns it.

6. Clean up

Sandboxes hibernate on idle automatically, but you can pause or tear one down explicitly:

# hibernate (wakes again on resume, ~0.3s) — /pause is an alias
curl -X POST https://infra.omg.dev/v1/sandboxes/$SANDBOX_ID/hibernate \
  -H "Authorization: Bearer $OMG_API_KEY"

# stop and delete for good
curl -X DELETE https://infra.omg.dev/v1/sandboxes/$SANDBOX_ID \
  -H "Authorization: Bearer $OMG_API_KEY"

What's live today

  • Create, list, get, pause, resume, snapshot, fork, and stop are all live over the API — plus exec, file read/write, and preview URLs.
  • Sizes: small / medium / large (1/2/4 vCPUs, 1/2/4 GB) on every create; templates: baked snapshots (templateId) and coding-agent presets (template).
  • Idle sandboxes hibernate automatically and wake on connect — a paused sandbox resumes under the same id in about 0.3s.
  • The interactive shell is a WebSocket upgrade (not a REST call); see the reference for the exact handshake.

For every field and every endpoint, see the Reference.