Skip to main content
A sandbox is the resource everything else in the API is scoped to — sessions, exec, files, and previews all operate on a sandbox identified by its sandbox_id.

Identity

A sandbox is created from a template_id and gets a server-assigned sandbox_id, which is the only identifier every other operation (sessions, exec, files, previews) accepts. A sandbox can also have a name, but names are a display label, not an identifier:
  • name is optional on create. If you omit it (or send a blank one), the service generates a friendly one.
  • name is not unique. The name query filter on list is an exact match, and because names aren’t unique it can match more than one sandbox.
  • Sandboxes created before names existed as a field may have no name at all; every sandbox returned afterward carries one.
Always key off sandbox_id in code you write against this API. Treat name as something to show a human, not something to look a sandbox up by.

Lifecycle states

A sandbox’s state is one of: Suspension is automatic — there is no endpoint to request it. The only lifecycle transition you invoke explicitly is resume:
There’s no bonya resume CLI command — the CLI only resumes implicitly (for example, bonya console resumes a suspended sandbox before attaching). MCP: sandbox_keepalive wakes a paused sandbox, and sandbox_pause pauses one. This synchronously resumes a suspended sandbox back to RUNNING. The response is a SandboxResume object with sandbox_id and already_running: if the sandbox was already running, the call is a no-op and already_running is true, but it still returns 200.
There is no start, stop, wake, fork, or restore endpoint. Resume is the only explicit lifecycle verb this API exposes; every other transition happens on its own.

Creating a sandbox

MCP: the sandbox_create tool exposes this to any connected agent. The request body (SandboxCreate) can omit template_id when the deployment has a configured default template. Otherwise, template_id is required. Optional fields:
  • template_version — pins a specific template version; requires template_id.
  • name — display label, up to 80 characters. Not unique (see above).
  • network — a NetworkPolicy controlling egress (see below).
By default, create returns 202 Accepted with the sandbox in CREATING (or whatever state it’s already reached) — it does not wait for the sandbox to be ready. Pass ?wait=ready to block until the sandbox reaches a ready state, in which case the same call returns 201 Created instead. Both responses share the same body shape: { "sandbox": { ...Sandbox } }.
The REST default is non-blocking, but every SDK’s createSandbox/create_sandbox/CreateSandbox defaults the other way — to Wait.READY/blocking — matching the CLI’s own --wait ready default. Pass wait: "none" (or the SDK’s Wait.NONE equivalent) explicitly to get the REST default’s immediate return instead.
Create also accepts an Idempotency-Key header — see Idempotency for exactly what that does and doesn’t protect against.

Getting and listing sandboxes

GET /v1/sandbox/{sandbox_id} returns a single sandbox as { "sandbox": { ...Sandbox } }. GET /v1/sandbox returns a page of sandboxes:
  • page_size — 1 to 100, default 50.
  • page_token — opaque cursor from a previous page’s next_page_token.
  • states — filter by one or more SandboxState values (repeat the query parameter for multiple states).
  • name — exact-match filter; can match more than one sandbox since names aren’t unique.
The response (SandboxPage) is { "sandboxes": [...], "next_page_token": "..." }.
DELETED is not a filterable state. A deleted sandbox is a tombstone, not a listable state — you can’t ask the list endpoint for deleted sandboxes.

Deleting a sandbox

MCP: the sandbox_delete tool tears down a sandbox the same way, and is likewise idempotent. Deletion is a synchronous teardown — it doesn’t return until the sandbox is gone. Deleting an already-deleted (tombstoned) sandbox again returns 204, the same as the first successful delete. An unknown sandbox_id, or one that belongs to a different organization than the caller’s context, returns 404.

Network policy

A sandbox can carry a network policy (NetworkPolicy) that controls outbound network egress. Its mode is one of:
  • standard (default) — the platform’s normal egress behavior.
  • deny_all — no outbound network access.
  • custom — egress is restricted to an explicit allowlist.
When mode is custom, the policy must include an allow list of at least one NetworkRule, each with a cidr and an optional list of ports (1–65535). The allow list is capped at 64 rules. For any mode other than custom, allow must be empty. Sandboxes are the scope for everything else in the API:
  • Exec — run one-off commands directly against a sandbox.
  • Sessions — long-lived, named command sessions inside a sandbox.
  • Files — read, write, and manage files on a sandbox’s filesystem.
  • Jobs — a managed, tracked run of a command or script, optionally on a sandbox created just for it.
  • Previews — expose a port running inside a sandbox as an HTTPS URL.