On this page

Sandboxes are persistent-by-default isolated microVM workspaces that restore from pre-seeded snapshots, accept exec and file operations, expose previews, and are billed by compute/runtime usage. They are designed for AI-agent code execution workloads, artifact generation, and app previews.

Base path: /api/v1/sandboxes

For higher-level access, use the official SDKs: Python, TypeScript, Go, Java, Elixir.


List sandbox templates and sizes

GET /api/v1/templates

This is the canonical catalog for sandbox template IDs, template defaults, per-template size support, readiness, and exact versioned resource contracts. Clients need no secondary catalog endpoint to discover or admit a sandbox configuration.

curl https://api.miosa.ai/api/v1/templates

Response - 200 OK

{
  "data": [
    {
      "id": "miosa-sandbox",
      "name": "MIOSA Sandbox",
      "product": "sandbox",
      "default_size": "small",
      "primitive": "sandbox",
      "sdk_name": "miosa-sandbox",
      "cli_name": "miosa-sandbox",
      "readiness": "fast_ready",
      "sizes": [
        {
          "size": "small",
          "state": "fast_ready",
          "resource_contract": {
            "contract_id": "sandbox/small@v1",
            "contract_version": "v1",
            "product": "sandbox",
            "size": "small",
            "vcpus": 2,
            "memory_mb": 4096,
            "disk_size_mb": 10240
          }
        }
      ]
    }
  ],
  "templates": [
    {
      "id": "miosa-sandbox",
      "name": "MIOSA Sandbox",
      "product": "sandbox",
      "default_size": "small",
      "primitive": "sandbox",
      "sdk_name": "miosa-sandbox",
      "cli_name": "miosa-sandbox",
      "readiness": "fast_ready",
      "sizes": [
        {
          "size": "small",
          "state": "fast_ready"
        }
      ]
    }
  ],
  "shape_contracts": {
    "sandbox": [],
    "computer": []
  },
  "readiness_states": ["fast_ready", "cold_boot_only", "missing"]
}

fast_ready sizes are creatable through the fast start path. cold_boot_only sizes are also creatable but start more slowly. missing means unavailable and must not be submitted. Use that template’s default_size when the caller does not have a stronger requirement. Do not combine a size advertised by one template with another template.


Custom templates

The canonical public V1 contract exposes only promoted templates returned by GET /api/v1/templates. Standalone custom-template build, validation, log, retry, and cancellation endpoints are not part of that contract. Do not make a public integration depend on those operations.


Configuration and request parameters

GET /api/v1/templates returns platform configuration: available templates, the default size, readiness, and versioned resource contracts. Applications select that configuration with sandbox parameters; they do not send internal host, provider, network, or placement fields.

Prefer size for create requests. The default small contract is 2 vCPU, 4096 MiB RAM, and 10240 MiB disk. xs is selectable when the catalog reports it as available. Compatibility resource fields must include cpu_count, memory_mb, and disk_size_mb together and exactly match one published contract.

Responses include the resolved contract under resource_contract. Contract IDs are versioned, for example sandbox/small@v1; persist that identity when usage or audit records must remain reproducible.

Create a Sandbox

POST /api/v1/sandboxes

Spawns a new sandbox VM. The API returns the sandbox record immediately after the create request is accepted; poll GET /api/v1/sandboxes/{id} or subscribe to events until state is running and ready is true.

The production alias miosa-sandbox resolves to a certified immutable artifact generation. See Benchmarks for guarded production evidence and methodology.

Auth

Bearer token required.

Request Body

FieldTypeRequiredDescription
template_idstringNoBoot template. Defaults to miosa-sandbox. See available templates below.
sizestringNoCanonical resource configuration. Defaults to small (2 vCPU, 4096 MiB, 10240 MiB disk).
cpu_countintegerNoExact vCPU compatibility input. Supply the full matching resource triple.
memory_mbintegerNoExact RAM override. It must match the selected canonical size.
disk_size_mbintegerNoExact disk override. It must match the selected canonical size. disk_mb is deprecated.
timeout_secintegerNoActive-session timeout. Defaults to 3600; minimum 1, maximum 86400.
always_onbooleanNoDisable timeout and idle-timeout enforcement until an explicit lifecycle action. Defaults to false and remains subject to policy.
persistentbooleanNoDefaults to true. Preserve filesystem state across stop/timeout and allow resume. Set false only for disposable one-off jobs.
idle_timeout_secintegerNoSeconds without activity before auto-stop. 0, the default, disables idle timeout.
envobjectNoKey-value env vars injected at boot.
metadataobjectNoArbitrary caller-supplied metadata stored on the record.
agent_runtime_profile_idUUID/stringNoForce a specific agent runtime profile for this sandbox. Alias: agent_profile_id.
skip_agent_runtime_profilebooleanNoIf true, do not apply the tenant/workspace default runtime profile.
auto_startbooleanNoIf true, MIOSA starts the selected template after the sandbox reaches running. Generated-app platforms usually keep this false, write files first, then call /template/start.
workspace_idUUIDNoExisting MIOSA workspace that owns the sandbox. Defaults to the organization default workspace.
workspace_slugstringNoExisting or auto-created workspace slug.
workspace_namestringNoWorkspace display name if auto-created.
project_idUUIDNoExisting MIOSA project that owns the sandbox. Defaults to the workspace default project.
project_slugstringNoExisting or auto-created project slug inside the workspace.
project_namestringNoProject display name if auto-created.
external_workspace_idstringNoYour customer/account/workspace ID.
external_user_idstringNoYour end-user ID.
external_project_idstringNoYour project/app/document ID.

If a default agent runtime profile exists for the workspace or tenant, MIOSA applies it automatically during create. Profile env vars are merged with request env vars, request env wins on conflict, profile metadata is recorded under metadata.agent_runtime_profile, and profile connectors are attached through egress placeholder tokens rather than copied as plaintext secrets.

Available templates:

template_idDescription
miosa-sandboxStable production alias for the current sandbox image.
nextjsNext.js app preview profile.
vite-reactVite React app preview profile.
pythonPython script/artifact generation profile.
streamlitStreamlit data app preview profile.
gradioGradio ML/demo app preview profile.
static-htmlStatic HTML/CSS/JS preview profile.

Request Headers

HeaderDescription
Idempotency-KeyClient-generated key (UUID recommended). Same key within 24 h returns the existing sandbox instead of creating a new one.

Response - 201 Created

{
  "id": "sbx_01j9xr2t4fk8me3n5q",
  "tenant_id": "tnt_abc123",
  "owner_id": "usr_def456",
  "workspace_id": "550e8400-e29b-41d4-a716-446655440000",
  "project_id": "660e8400-e29b-41d4-a716-446655440001",
  "external_workspace_id": "clinic_123",
  "external_user_id": "dr-smith-456",
  "external_project_id": "project_789",
  "template_id": "miosa-sandbox",
  "image_id": "miosa-sandbox",
  "state": "provisioning",
  "ready": false,
  "size": "small",
  "resource_contract": {
    "id": "sandbox/small@v1",
    "product": "sandbox",
    "size": "small",
    "version": "v1",
    "vcpus": 2,
    "memory_mb": 4096,
    "disk_size_mb": 10240
  },
  "cpu_count": 2,
  "memory_mb": 4096,
  "disk_size_mb": 10240,
  "preview_url": "https://sbx01j9x.sandbox.miosa.ai",
  "timeout_sec": 3600,
  "timeout_remaining_ms": null,
  "always_on": false,
  "persistent": true,
  "idle_timeout_sec": 0,
  "total_runtime_sec": null,
  "metadata": {},
  "created_at": "2026-04-25T10:00:00Z",
  "started_at": null,
  "ready_at": null,
  "destroyed_at": null
}

Errors

StatusCodeCause
400INVALID_TEMPLATEtemplate_id is not a recognized template.
402INSUFFICIENT_CREDITSNot enough credits to provision the VM.
409SANDBOX_LIMIT_EXCEEDEDTenant has reached the concurrent sandbox limit (default 10).
422VALIDATION_ERRORInvalid field values (for example, a resource request above the tenant’s plan cap).

Create and Run

POST /api/v1/sandboxes/run

Creates a sandbox, waits for it to become running, executes the first command, and returns the sandbox record plus the command result in one request. Use this for agent loops where the first useful action is “create a sandbox and run code now.”

This is the production fast path used by MIOSA’s sandbox benchmark. Performance claims are published only from guarded create-to-command cohorts that also hold the peak live set and prove zero-residue teardown.

curl -X POST https://api.miosa.ai/api/v1/sandboxes/run 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -H "Idempotency-Key: run-2026-06-09-001" 
  -d '{
    "template_id": "miosa-sandbox",
    "command": "python3 -c "print(1+1)"",
    "size": "small",
    "timeout_sec": 300,
    "wait_timeout_ms": 30000,
    "metadata": { "agent_run": "abc123" }
  }'

Request Body

/run accepts the same sandbox creation fields as POST /api/v1/sandboxes, plus:

FieldTypeRequiredDescription
commandstringYesFirst command to execute after the sandbox reaches running.
cwdstringNoWorking directory for the command. Defaults to /workspace.
timeoutintegerNoCommand timeout in milliseconds.
wait_timeout_msintegerNoMax time to wait for sandbox readiness before returning 504 SANDBOX_READY_TIMEOUT.

Response - 201 Created

{
  "data": {
    "id": "sbx_01j9xr2t4fk8me3n5q",
    "state": "running",
    "ready": true,
    "template_id": "miosa-sandbox",
    "cpu_count": 2,
    "memory_mb": 4096
  },
  "exec": {
    "stdout": "2\n",
    "stderr": "",
    "exit_code": 0
  },
  "timings": {
    "server_wait_and_exec_ms": 512
  }
}

Errors

StatusCodeCause
400MISSING_PARAMcommand is missing.
400INVALID_TEMPLATEtemplate_id is not recognized.
402INSUFFICIENT_CREDITSNot enough credits to provision the VM.
409SANDBOX_LIMIT_EXCEEDEDTenant has reached the concurrent sandbox limit.
409SANDBOX_NOT_RUNNINGThe sandbox failed to reach a running state for exec.
502SANDBOX_BOOT_FAILEDVM boot failed before the command could run.
502AGENT_UNAVAILABLEThe sandbox agent was not reachable for exec.
504SANDBOX_READY_TIMEOUTThe sandbox did not become ready before wait_timeout_ms.

Start a Template App

POST /api/v1/sandboxes/{id}/template/start

After your platform writes generated files into /workspace, call this endpoint to run the selected template lifecycle. MIOSA runs the template install command, launches the start command in the background, stores PID/log paths, and returns the preview URL.

curl -X POST https://api.miosa.ai/api/v1/sandboxes/{id}/template/start 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"install":true}'

Response:

{
  "data": {
    "status": "started",
    "template_id": "nextjs",
    "workdir": "/workspace",
    "preview_port": 3000,
    "preview_url": "https://abc12345.sandbox.miosa.ai",
    "logs_path": "/tmp/miosa-run/template.log",
    "pid_path": "/tmp/miosa-run/template.pid",
    "artifact_paths": ["/workspace"]
  }
}

You can override install_command, start_command, port, or workdir in the request body when your generated project needs a custom command.


Get Artifacts

GET /api/v1/sandboxes/{id}/artifacts

Returns the template artifact contract and current lifecycle metadata.

curl https://api.miosa.ai/api/v1/sandboxes/{id}/artifacts 
  -H "Authorization: Bearer $MIOSA_API_KEY"

The response includes preview.url, preview.port, artifact paths, and template lifecycle log/PID paths.

curl -X POST https://api.miosa.ai/api/v1/sandboxes 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{
    "template_id": "miosa-sandbox",
    "workspace_slug": "dr-smith-clinic",
    "workspace_name": "Dr. Smith Clinic",
    "project_slug": "lead-magnet",
    "project_name": "Lead Magnet",
    "external_workspace_id": "clinic_123",
    "external_user_id": "dr-smith-456",
    "external_project_id": "project_789",
    "size": "small",
    "env": {"MY_VAR": "hello"}
  }'

List Sandboxes

GET /api/v1/sandboxes

Returns all sandboxes belonging to the authenticated tenant.

Query Parameters

ParameterTypeDescription
workspace_idUUIDFilter to one MIOSA workspace
project_idUUIDFilter to one MIOSA project
external_workspace_idstringFilter by your customer/account ID
external_user_idstringFilter by your end-user ID
external_project_idstringFilter by your project/app/document ID
statestringFilter by lifecycle state: provisioning, running, paused, destroyed, error.

Auth

Bearer token required.

Response - 200 OK

{
  "data": [
    {
      "id": "sbx_01j9xr2t4fk8me3n5q",
      "template_id": "miosa-sandbox",
      "state": "running",
      "cpu_count": 2,
      "memory_mb": 4096,
      "created_at": "2026-04-25T10:00:00Z"
    }
  ]
}
curl "https://api.miosa.ai/api/v1/sandboxes?state=running" 
  -H "Authorization: Bearer $MIOSA_API_KEY"

Get a Sandbox

GET /api/v1/sandboxes/{id}

Auth

Bearer token required.

Path Parameters

ParameterTypeDescription
idstringSandbox ID.

Response - 200 OK

Full sandbox object (same shape as the create response with current state).

Errors

StatusCodeCause
404NOT_FOUNDSandbox does not exist or belongs to a different tenant.
curl https://api.miosa.ai/api/v1/sandboxes/sbx_01j9xr2t4fk8me3n5q 
  -H "Authorization: Bearer $MIOSA_API_KEY"

Destroy a Sandbox

DELETE /api/v1/sandboxes/{id}

Permanently deletes the sandbox, removes saved state, and settles billing. Use POST /pause when the user is done for now but may resume later.

Auth

Bearer token required.

Path Parameters

ParameterTypeDescription
idstringSandbox ID.

Response - 200 OK

{
  "id": "sbx_01j9xr2t4fk8me3n5q",
  "state": "destroyed",
  "total_runtime_sec": 42
}

Errors

StatusCodeCause
404NOT_FOUNDSandbox does not exist or belongs to a different tenant.
curl -X DELETE https://api.miosa.ai/api/v1/sandboxes/sbx_01j9xr2t4fk8me3n5q 
  -H "Authorization: Bearer $MIOSA_API_KEY"

Execute a Command

POST /api/v1/sandboxes/{id}/exec

Runs a shell command inside the sandbox. Blocks until the process exits.

Auth

Bearer token required.

Path Parameters

ParameterTypeDescription
idstringSandbox ID. Must be in running state.

Request Body

FieldTypeRequiredDescription
commandstringYesShell command to execute.
timeoutintegerNoPer-command timeout in seconds. Default 30, max 300.
working_dirstringNoWorking directory inside the VM. Default /root.
envobjectNoEnv vars for this invocation only.

Response - 200 OK

{
  "data": {
    "sandbox_id": "sbx_01j9xr2t4fk8me3n5q",
    "stdout": "2\n",
    "stderr": "",
    "exit_code": 0
  }
}

Errors

StatusCodeCause
409SANDBOX_NOT_RUNNINGSandbox is not in running state.
504-Command timed out.
curl -X POST https://api.miosa.ai/api/v1/sandboxes/sbx_01j9xr2t4fk8me3n5q/exec 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"command": "python3 -c "print(1+1)"", "timeout": 30}'

Stream Command Output

POST /api/v1/sandboxes/{id}/exec/stream

Runs a command and streams stdout/stderr events as Server-Sent Events. Use this for installer output, long-running agent tasks, and build logs that should show progress before the command exits.

Request body is the same as /exec.

curl -N -X POST https://api.miosa.ai/api/v1/sandboxes/sbx_01j9xr2t4fk8me3n5q/exec/stream 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Accept: text/event-stream" 
  -H "Content-Type: application/json" 
  -d '{"command":"npm install && npm run build","working_dir":"/workspace","timeout":300}'

Example events:

event: stdout
data: {"line":"added 342 packages"}

event: exit
data: {"exit_code":0}

Open a Terminal Session

POST /api/v1/sandboxes/{id}/terminal

Creates a PTY session inside a running sandbox and returns a short-lived stream token for browser WebSocket clients.

Request Body

FieldTypeRequiredDescription
colsintegerNoInitial terminal width. Defaults to 80.
rowsintegerNoInitial terminal height. Defaults to 24.
shellstringNoShell command. Defaults to login bash when available.

Response - 201 Created

{
  "session_id": "52d1df5a0a3a0018",
  "ws_url": "wss://api.miosa.ai/api/v1/sandboxes/sbx_01j9xr2t4fk8me3n5q/terminal/stream",
  "stream_auth": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9...",
  "stream_auth_expires_at": "2026-05-13T12:30:00Z"
}

Open the WebSocket with:

wss://api.miosa.ai/api/v1/sandboxes/{id}/terminal/stream?session_id={session_id}&cols=120&rows=32&token={stream_auth}

Clients should send raw terminal input as binary frames. Resize events are sent as JSON text frames:

{"type":"resize","cols":120,"rows":32}

Delete the session when finished:

curl -X DELETE https://api.miosa.ai/api/v1/sandboxes/{id}/terminal/{session_id} 
  -H "Authorization: Bearer $MIOSA_API_KEY"

Export Files

Exports are for files an agent created inside the sandbox that your product needs to show or download: static HTML, PDFs, CSVs, screenshots, generated reports, ZIPs, and build folders.

POST /api/v1/sandboxes/{id}/exports

Creates a ready export descriptor. This does not move the file out of the sandbox; it returns download URLs backed by the sandbox filesystem.

Request Body

FieldTypeRequiredDescription
pathstringYes, unless paths is setSingle file path inside the sandbox.
pathsarrayYes, unless path is setMultiple file paths to package as a tar.gz archive.
labelstringNoHuman-readable export label.
filenamestringNoSuggested filename for download responses.

Response - 200 OK

{
  "data": {
    "id": "exp_01j9xr2t4fk8me3n5q",
    "sandbox_id": "sbx_01j9xr2t4fk8me3n5q",
    "label": "homepage build",
    "status": "ready",
    "files": [
      {
        "path": "/workspace/dist/index.html",
        "filename": "index.html",
        "download_url": "https://api.miosa.ai/api/v1/sandboxes/sbx_.../exports/download?path=..."
      }
    ],
    "archive_download_url": "https://api.miosa.ai/api/v1/sandboxes/sbx_.../exports/download?paths%5B%5D=...",
    "created_at": "2026-06-14T21:00:00Z"
  }
}

GET /api/v1/sandboxes/{id}/exports/download?path=/workspace/report.pdf

Downloads one file as binary.

GET /api/v1/sandboxes/{id}/exports/download?paths[]=/workspace/dist/index.html&paths[]=/workspace/dist/app.js

Downloads multiple paths as a tar.gz archive.

curl -X POST https://api.miosa.ai/api/v1/sandboxes/$SBX/exports 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"paths":["/workspace/dist/index.html","/workspace/dist/app.js"],"label":"build"}'

curl "https://api.miosa.ai/api/v1/sandboxes/$SBX/exports/download?path=/workspace/report.pdf" 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -o report.pdf

Expose a Preview Port

POST /api/v1/sandboxes/{id}/expose

Returns a public, tenant-aware preview URL for a server running inside the sandbox. Use this when an agent generated a Vite/Next/FastAPI/Flask app and started it on a local port.

Inside the sandbox, bind dev servers to 0.0.0.0, not localhost:

npm run dev -- --host 0.0.0.0 --port 5173
python -m http.server 8000 --bind 0.0.0.0

Request Body

FieldTypeRequiredDescription
portintegerNoPort inside the sandbox to expose. If omitted, MIOSA uses the template lifecycle preview port when available. Must be 1 through 65535 when provided.

Response - 200 OK

{
  "url": "https://5173-sbx01j9x.sandbox.miosa.ai"
}

If the tenant has a white-label preview domain configured, the same endpoint returns that domain instead of the platform default. Default app ports such as 3000, 5173, 8080, 8000, and 80 may be returned as https://{slug}.sandbox.{domain}; non-default ports use https://{port}-{slug}.sandbox.{domain}.

Errors

StatusCodeCause
400MISSING_PARAMport was omitted and the sandbox template has no default preview port.
409SANDBOX_NOT_RUNNINGSandbox is not in running state.
422INVALID_PORTPort is outside 1 through 65535.
curl -X POST https://api.miosa.ai/api/v1/sandboxes/sbx_01j9xr2t4fk8me3n5q/expose 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"port": 5173}'

For static artifacts such as PDFs, images, Markdown, CSV, or ZIP files, write them under /workspace and download them through the files API. For web apps, start a server and expose the port.


Publish a Sandbox

POST /api/v1/sandboxes/{id}/publish

Freezes sandbox source, creates an immutable release and deployment version, verifies the candidate, and promotes it behind a stable deployment URL. Use this endpoint for production publishing.

The CLI is the recommended happy path:

miosa sandbox publish <sandbox-id> 
  --app <deployment-id> 
  --docker-deploy 
  --wait 
  --json

Omit --app for the first publish. Include it for updates so MIOSA preserves the deployment ID and canonical URL.

See Publishing for request options, proof, and failure behavior.

Promote a Sandbox Runtime to a Deployment

POST /api/v1/sandboxes/{id}/deploy

This compatibility bridge routes a persistent deployment URL directly to a running sandbox. The sandbox remains the runtime behind the route and its auto-destroy timer is cancelled.

Use it only when the sandbox itself must remain the runtime. For immutable production versions and App Engine, use /publish.

Request Body

FieldTypeRequiredDescription
namestringYesHuman-readable deployment name. Used to create the deployment slug.
portintegerNoRuntime port to route. Defaults to the template lifecycle preview port, then 80.
domainstringNoCustom domain to attach.
custom_domainstringNoAlias for domain, used by frontend clients.

Response - 201 Created

{
  "deployment_id": "dep_01j9xr2t4fk8me3n5q",
  "url": "https://my-app-a1b2c3.acme.miosa.app",
  "state": "running"
}

Managed deployment URLs are tenant-scoped: https://{deployment-slug}.{tenant-slug}.miosa.app. MIOSA persists the sandbox runtime target on the deployment and reconciles running routes, so a temporary proxy restart or admin API outage can be repaired from the database.

Errors

StatusCodeCause
400MISSING_PARAMname was omitted.
409SANDBOX_NOT_RUNNINGSandbox is not in running state.
409SANDBOX_RUNTIME_UNAVAILABLESandbox is marked running but has no VM IP yet.
422INVALID_PORTPort is outside 1 through 65535.
422VALIDATION_ERRORDeployment record validation failed.
curl -X POST https://api.miosa.ai/api/v1/sandboxes/sbx_01j9xr2t4fk8me3n5q/deploy 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"name":"my-app","port":8000}'

Upload a File

POST /api/v1/sandboxes/{id}/files

Writes a file to the sandbox filesystem. Two request formats are accepted.

Auth

Bearer token required.

Path Parameters

ParameterTypeDescription
idstringSandbox ID. Must be in running state.

Request Body - JSON

FieldTypeRequiredDescription
pathstringYesAbsolute destination path inside the sandbox.
contentstringYesBase64-encoded file content.
{
  "path": "/workspace/script.py",
  "content": "cHJpbnQoJ2hlbGxvJyk="
}

Request Body - Multipart

Alternatively, send multipart/form-data with fields:

FieldDescription
pathAbsolute destination path.
fileFile part containing the raw content.

Response - 200 OK

{
  "data": {
    "sandbox_id": "sbx_01j9xr2t4fk8me3n5q",
    "path": "/workspace/script.py",
    "size": 16
  }
}

Errors

StatusCodeCause
409SANDBOX_NOT_RUNNINGSandbox is not in running state.
413-File exceeds the 100 MB upload limit.
# JSON (base64-encoded content)
curl -X POST https://api.miosa.ai/api/v1/sandboxes/sbx_01j9xr2t4fk8me3n5q/files 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d "{"path": "/workspace/script.py", "content": "$(base64 -w0 script.py)"}"

# Multipart
curl -X POST https://api.miosa.ai/api/v1/sandboxes/sbx_01j9xr2t4fk8me3n5q/files 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -F "path=/workspace/script.py" 
  -F "file=@script.py"

Download a File

GET /api/v1/sandboxes/{id}/files/{path}

Downloads a file from the sandbox filesystem.

Auth

Bearer token required.

Path Parameters

ParameterTypeDescription
idstringSandbox ID. Must be in running state.
pathstringURL-encoded path to the file inside the sandbox (leading / stripped).

Response - 200 OK

Raw file bytes with Content-Type: application/octet-stream.

Errors

StatusCodeCause
404FILE_NOT_FOUNDPath does not exist inside the sandbox.
409SANDBOX_NOT_RUNNINGSandbox is not in running state.
curl -o output.json 
  "https://api.miosa.ai/api/v1/sandboxes/sbx_01j9xr2t4fk8me3n5q/files/workspace%2Foutput.json" 
  -H "Authorization: Bearer $MIOSA_API_KEY"

List Files

GET /api/v1/sandboxes/{id}/files?path=/workspace

Lists files and directories in a sandbox directory.

curl "https://api.miosa.ai/api/v1/sandboxes/{id}/files?path=/workspace" 
  -H "Authorization: Bearer $MIOSA_API_KEY"

Response:

{
  "data": {
    "path": "/workspace",
    "entries": [
      {"name": "index.html", "path": "/workspace/index.html", "is_dir": false, "size": 128}
    ]
  }
}

Stat a File

POST /api/v1/sandboxes/{id}/files/stat

Returns metadata for one file or directory.

curl -X POST https://api.miosa.ai/api/v1/sandboxes/{id}/files/stat 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"path":"/workspace/index.html"}'

Read Logs

GET /api/v1/sandboxes/{id}/logs

Returns recent sandbox/template lifecycle logs. Pass lines to control the tail length.

curl "https://api.miosa.ai/api/v1/sandboxes/{id}/logs?lines=200" 
  -H "Authorization: Bearer $MIOSA_API_KEY"

Stream logs with SSE:

curl -N "https://api.miosa.ai/api/v1/sandboxes/{id}/logs/stream" 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Accept: text/event-stream"

Extend the Timeout

POST /api/v1/sandboxes/{id}/extend

Replaces the active-session timeout with timeout_sec from 1 through 86400. The operation does not add duration to the old value. Omitting the body preserves the current timeout.

curl -X POST https://api.miosa.ai/api/v1/sandboxes/{id}/extend 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{"timeout_sec":7200}'

Get Sandbox Usage

GET /api/v1/sandboxes/{id}/usage

Returns measured runtime, provisioned vCPU time, active CPU, network traffic, estimated cost, and timeout visibility.

{
  "data": {
    "sandbox_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "state": "running",
    "runtime_sec": 47,
    "provisioned_vcpu_ms": 94000,
    "active_cpu_ms": 12000,
    "network_ingress_bytes": 2048,
    "network_egress_bytes": 4096,
    "measurement_status": {
      "active_cpu": "measured",
      "network": "measured",
      "provisioned_resources": "measured"
    },
    "estimated_cost_cents": 1,
    "timeout_sec": 3600,
    "timeout_remaining_ms": 3553000
  }
}

Interpret nullable measurements through measurement_status. unavailable means no trustworthy value exists and the related field is null, not zero. stale means the retained value is not current and must be labeled as such. timeout_remaining_ms can be null before start or when timeout enforcement is disabled.


Pause and Resume

POST /api/v1/sandboxes/{id}/pause suspends guest vCPU execution for a running persistent sandbox while preserving its workspace. It returns 409 if the sandbox is not running.

POST /api/v1/sandboxes/{id}/resume transitions a paused sandbox back to running and returns 409 if it is not paused. Command and file operations can automatically resume a paused persistent sandbox before dispatch.

curl -X POST https://api.miosa.ai/api/v1/sandboxes/{id}/pause 
  -H "Authorization: Bearer $MIOSA_API_KEY"

curl -X POST https://api.miosa.ai/api/v1/sandboxes/{id}/resume 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Idempotency-Key: resume-session-001"

Fork a Sandbox

POST /api/v1/sandboxes/{id}/fork creates a new sandbox from a copy-on-write snapshot of a running sandbox. The optional body accepts timeout_sec and template_id for the new sandbox.

curl -X POST https://api.miosa.ai/api/v1/sandboxes/{id}/fork 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Content-Type: application/json" 
  -H "Idempotency-Key: fork-experiment-001" 
  -d '{"timeout_sec":3600}'

Canonical public V1 exposes standalone snapshot create, list, inspect, delete, and restore operations. Use fork when a customer needs an independent branch of current running state without managing the intermediate snapshot directly.


Subscribe to Events (SSE)

GET /api/v1/sandboxes/{id}/events

Opens a Server-Sent Events (SSE) stream that emits sandbox lifecycle events. The connection closes automatically when the sandbox reaches destroyed or error.

Auth

Bearer token required (sent as Authorization: Bearer <key> header).

Path Parameters

ParameterTypeDescription
idstringSandbox ID.

Response - 200 OK (event stream)

Content-Type: text/event-stream

Event: state_changed


event: state_changed
data: {"state":"running","previous_state":"provisioning","timestamp":"2026-04-25T10:00:07Z"}

Event: exec_output


event: exec_output
data: {"exec_id":"exec_abc","stream":"stdout","data":"2\n","timestamp":"2026-04-25T10:00:10Z"}

Event: error


event: error
data: {"message":"VM terminated unexpectedly","timestamp":"2026-04-25T10:05:00Z"}
curl -N "https://api.miosa.ai/api/v1/sandboxes/sbx_01j9xr2t4fk8me3n5q/events" 
  -H "Authorization: Bearer $MIOSA_API_KEY" 
  -H "Accept: text/event-stream"

Sandbox Object

The full sandbox object returned by create, get, and list endpoints:

FieldTypeDescription
idstringUnique sandbox identifier.
tenant_idstringOwning tenant ID.
owner_idstringCreating user ID.
template_idstringBoot template name.
statestringCurrent lifecycle state.
sizestringCanonical named size: xs, small, medium, large, or xl.
resource_contractobjectVersioned resolved contract with ID, product, size, vCPU, memory, and disk.
cpu_countintegerAllocated vCPUs.
memory_mbintegerAllocated RAM in MB.
disk_size_mbintegerAllocated root disk in MB.
readybooleanWhether command and readiness checks are accepting work.
ready_atstring/nullISO timestamp when ready became true.
preview_urlstring/nullTenant-aware base preview URL for the sandbox slug. Use /expose for a specific port.
timeout_secintegerMax seconds for the active session. Persistent timeout pauses; non-persistent timeout destroys.
timeout_remaining_msinteger | nullRemaining active-session time; null before start or when timeout enforcement is disabled.
always_onbooleanWhether timeout and idle-timeout enforcement are disabled.
persistentbooleanWhether the sandbox preserves filesystem state across stop/timeout.
idle_timeout_secintegerSeconds without activity before auto-stop; zero disables it.
total_runtime_secinteger | nullBilled seconds. Set only after destruction.
metadataobjectCaller-supplied metadata.
created_atstringISO-8601 creation timestamp.
started_atstring | nullISO-8601 timestamp when VM entered running.
destroyed_atstring | nullISO-8601 timestamp when VM was destroyed.

Lifecycle States


provisioning → running → paused
running → paused → running
running → destroyed
* → error  (terminal)
StateDescription
provisioningVM is booting. Exec and file operations are not yet available.
runningVM is reachable. All operations allowed.
pausedCompute is stopped and filesystem state is preserved. Can be resumed.
destroyedTerminal. VM is gone, billing is settled.
errorTerminal failure. Destroy and create a new sandbox.

Error Response Format

All error responses use this shape:

{
  "error": {
    "code": "NOT_FOUND",
    "message": "sandbox not found",
    "details": null
  }
}

The x-request-id response header is set on every request. Include it in support requests.


Rate Limits

LimitValue
Request rateReturned through X-RateLimit-* headers; varies by key and policy
Concurrent sandboxes per tenant10 (contact support to increase)
timeout_sec1-86400 seconds; default 3600
Default resource shapesmall: 2 vCPU, 4 GiB RAM, 10 GiB disk
Named resource schemaxs through xl; actual availability comes from GET /templates and tenant policy
Max exec timeout300 s (5 minutes)
Max file upload size100 MB

Rate-limited responses return HTTP 429 with a Retry-After header indicating seconds to wait.


See also

Was this helpful?