#Sandbox
A Sandbox is an isolated execution environment where you can run code, manage files, and control network access. Each sandbox is created from a Template and provides a secure, ephemeral workspace.
For shell access and file copy over standard SSH clients, see SSH.
Sandbox0 Cloud clients should use https://api.sandbox0.ai. Set SANDBOX0_BASE_URL only when you are connecting to a self-hosted or private deployment.
Sandbox Model#
Key Identifiers#
| Field | Description |
|---|---|
id | Unique sandbox identifier (e.g., sb_abc123) |
template_id | Template used to create this sandbox |
team_id | Team that owns this sandbox |
user_id | User who claimed this sandbox |
pod_name | Kubernetes pod name (internal) |
cluster_id | Cluster where sandbox runs in multi-cluster deployments. Present on claim and list responses, not on sandbox detail responses. |
Lifecycle States#
| Status | Description |
|---|---|
starting | Sandbox is being initialized |
running | Sandbox is active and ready to use |
failed | Sandbox encountered an error |
completed | Sandbox has finished execution |
Pause state is modeled separately from status. Use the paused boolean when you need to distinguish a paused sandbox from a running one. For async pause/resume flows, use power_state to inspect desired vs observed state plus generation counters.
Claim a Sandbox#
Claim a sandbox from a template. The sandbox is created from a pre-warmed pool for fast startup (<200ms cold start).
/api/v1/sandboxes
Request Body#
| Field | Type | Description |
|---|---|---|
template | string | Template ID to use |
config | object | Optional sandbox configuration |
Sandbox Configuration#
| Field | Type | Description |
|---|---|---|
env_vars | object | Sandbox-level default environment variables for new procd-managed processes |
ttl | integer | Time to live in seconds (soft limit, triggers auto-pause; default: 0, disabled) |
hard_ttl | integer | Hard runtime lifetime in seconds (cleans compute while preserving sandbox identity and services; default: 0, disabled) |
network | object | SandboxNetworkPolicy. Controls traffic rules, protocol controls, credential bindings, and destination-scoped egress auth |
webhook | object | Webhook configuration |
auto_resume | boolean | Auto-resume when accessed (default: true) |
services | array | Sandbox Services for public HTTP routes, including Sandbox Functions |
See Network and Protocol Controls for outbound control, Sandbox Services for public HTTP controls, Sandbox Functions for inline public handlers, and Credential for outbound auth and secret handling.
Sandbox env_vars override template/container environment variables for new contexts, command services, and function executions. Per-context, per-command, service runtime, and function env_vars override sandbox env_vars for that narrower scope. Warm processes start before the sandbox is claimed, so they do not receive claim-time sandbox env_vars.
TTL vs Hard TTL#
Sandbox0 uses two-tier TTL to balance resource efficiency and flexibility:
| Field | Behavior | Use Case |
|---|---|---|
ttl | Soft pause: When expired, sandbox is automatically paused. Processes stop but state is preserved. Can be extended via refresh API. | Keep sandboxes alive during active use while freeing compute resources during idle periods. |
hard_ttl | Hard clean: When expired, Sandbox0 deletes the runtime pod and marks the sandbox cleaned. Identity, configuration, services, and public URLs remain available until explicit delete. | Enforce compute cost limits while keeping a durable sandbox service that can be restored on demand. |
The relationship: ttl <= hard_ttl. When ttl expires first, sandbox pauses but can be resumed.
When hard_ttl expires, sandbox compute is cleaned and the sandbox can be restored by resume-capable access. Both can be extended via the refresh API.
Example timeline (sandbox created with ttl=300 and hard_ttl=3600):
t=0: Sandbox createdt=300: TTL expires → sandbox auto-pausest=310: User calls refresh → TTL reset to 300, Hard TTL reset to 3600 (new hard deadline att=3910)t=610: TTL expires again → sandbox auto-pausest=3910: Hard TTL expires → runtime pod cleaned, sandbox status becomescleaned
goctx := context.Background() client, err := sandbox0.NewClient( sandbox0.WithToken(os.Getenv("SANDBOX0_TOKEN")), sandbox0.WithBaseURL(os.Getenv("SANDBOX0_BASE_URL")), ) if err != nil { log.Fatal(err) } // Claim a sandbox from the "default" template sandbox, err := client.ClaimSandbox(ctx, "default", sandbox0.WithSandboxHardTTL(300), sandbox0.WithSandboxEnvVars(map[string]string{ "APP_ENV": "development", }), ) if err != nil { log.Fatal(err) } fmt.Printf("Sandbox ID: %s\n", sandbox.ID) defer client.DeleteSandbox(ctx, sandbox.ID)
Get Sandbox Details#
Retrieve full details about a sandbox.
/api/v1/sandboxes/{id}
gosb, err := client.GetSandbox(ctx, sandbox.ID) if err != nil { log.Fatal(err) } fmt.Printf("Status: %s\n", sb.Status) fmt.Printf("Template: %s\n", sb.TemplateID) fmt.Printf("Expires at: %s\n", sb.ExpiresAt)
Get Sandbox Status#
Get the current status of a sandbox (lighter weight than full details).
/api/v1/sandboxes/{id}/status
gostatus, err := client.StatusSandbox(ctx, sandbox.ID) if err != nil { log.Fatal(err) } fmt.Printf("Status: %s\n", status.Status.Value)
Get Sandbox Logs#
Read sandbox process output. Procd service logs are filtered out of this API and remain available from Kubernetes pod logs. Snapshot and streaming requests return text/plain.
/api/v1/sandboxes/{id}/logs
Query Parameters#
| Parameter | Type | Description |
|---|---|---|
container | string | Pod container name (default: procd) |
tail_lines | integer | Number of Kubernetes log lines read from the end of the log before procd service log filtering (default: 200, max: 5000) |
limit_bytes | integer | Maximum Kubernetes log bytes read before procd service log filtering (default: 1048576 for snapshot responses, max: 8388608) |
follow | boolean | Stream logs as text/plain until the client disconnects |
previous | boolean | Return logs from the previously terminated container instance |
timestamps | boolean | Include Kubernetes log timestamps when available |
since_seconds | integer | Return logs newer than this many seconds |
gotailLines := int64(200) logs, err := sandbox.GetLogs(ctx, &sandbox0.SandboxLogsOptions{ TailLines: &tailLines, }) if err != nil { log.Fatal(err) } fmt.Print(logs.Logs)
For live streaming, use sandbox.StreamLogs(...), sandbox.stream_logs(...), sandbox.streamLogs(...), or s0 sandbox logs --follow.
List Sandboxes#
List all sandboxes with optional filters.
/api/v1/sandboxes
Query Parameters#
| Parameter | Type | Description |
|---|---|---|
status | string | Filter by status (starting, running, failed, completed, terminating) |
template_id | string | Filter by template ID |
paused | boolean | Filter by paused state independently of status |
limit | integer | Max results per page (default: 50, max: 200) |
offset | integer | Pagination offset (default: 0) |
golimit := 10 sandboxes, err := client.ListSandboxes(ctx, &sandbox0.ListSandboxesOptions{ Status: "running", TemplateID: "default", Limit: &limit, }) if err != nil { log.Fatal(err) } for _, sb := range sandboxes.Sandboxes { fmt.Printf("- %s (status: %s)\n", sb.ID, sb.Status) }
Update Sandbox#
Update sandbox configuration at runtime without restarting the sandbox.
/api/v1/sandboxes/{id}
Updatable Fields#
Only the following fields can be updated at runtime:
| Field | Type | Description |
|---|---|---|
ttl | integer | Time to live in seconds (soft limit) |
hard_ttl | integer | Hard runtime lifetime in seconds |
network | object | Network policy configuration |
auto_resume | boolean | Auto-resume when accessed |
services | array | Sandbox Services for public HTTP routes, including Sandbox Functions |
env_vars and webhook cannot be updated at runtime. These fields only take effect when the sandbox is created. To use different sandbox-level environment variables, create a new sandbox.
go_, err = client.UpdateSandbox(ctx, sandbox.ID, apispec.SandboxUpdateRequest{ Config: apispec.NewOptSandboxUpdateConfig(apispec.SandboxUpdateConfig{ TTL: apispec.NewOptInt32(600), AutoResume: apispec.NewOptBool(false), }), }) if err != nil { log.Fatal(err) }
Pause And Resume#
Pause and resume is covered in a dedicated page because it affects TTL, auto_resume, service routes, SSH, and webhook behavior.
See Pause And Resume for explicit pause, state inspection, resume, and auto-resume behavior.
Refresh Sandbox TTL#
Extend the sandbox time-to-live. This resets both ttl and hard_ttl (if configured) from the current time while the sandbox has a runtime.
/api/v1/sandboxes/{id}/refresh
Request Body#
| Field | Type | Description |
|---|---|---|
duration | integer | Duration to extend TTL in seconds (optional, defaults to original TTL) |
If duration is not specified, both ttl and hard_ttl are reset to their original configured values. Use this to keep a sandbox alive as long as the user is actively using it.
go// Refresh with default duration (original TTL) resp, err := client.RefreshSandbox(ctx, sandbox.ID, nil) if err != nil { log.Fatal(err) } fmt.Printf("New expires at: %s\n", resp.ExpiresAt) // Refresh with custom duration (e.g., 1 minute) resp, err = client.RefreshSandbox(ctx, sandbox.ID, &apispec.SandboxRefreshRequest{ Duration: apispec.NewOptInt32(60), }) if err != nil { log.Fatal(err) } fmt.Printf("New expires at: %s\n", resp.ExpiresAt)
Delete Sandbox#
Terminate and delete a sandbox. This action is irreversible.
/api/v1/sandboxes/{id}
go_, err = client.DeleteSandbox(ctx, sandbox.ID) if err != nil { log.Fatal(err) } fmt.Println("Sandbox deleted")
Next Steps#
Pause And Resume
Control sandbox power state and resume behavior before wiring long-lived workflows.
Contexts
Run REPL and command contexts inside a sandbox and stream process output.