#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.

Sandbox Model#

Key Identifiers#

FieldDescription
idUnique sandbox identifier (e.g., sb_abc123)
template_idTemplate used to create this sandbox
team_idTeam that owns this sandbox
user_idUser who claimed this sandbox
pod_nameKubernetes pod name (internal)
cluster_idCluster where sandbox runs (multi-cluster only)

Lifecycle States#

StatusDescription
startingSandbox is being initialized
runningSandbox is active and ready to use
pausedSandbox is paused (resources preserved)
failedSandbox encountered an error
completedSandbox has finished execution

Claim a Sandbox#

Claim a sandbox from a template. The sandbox is created from a pre-warmed pool for fast startup (<200ms cold start).

POST

/api/v1/sandboxes

Request Body#

FieldTypeDescription
templatestringTemplate ID to use
configobjectOptional sandbox configuration

Sandbox Configuration#

FieldTypeDescription
env_varsobjectEnvironment variables
ttlintegerTime to live in seconds (soft limit, triggers auto-pause; default: 0, disabled)
hard_ttlintegerMaximum lifetime in seconds (hard limit, triggers deletion; default: 0, disabled)
networkobjectNetwork policy configuration
webhookobjectWebhook configuration
auto_resumebooleanAuto-resume when accessed (default: true)
exposed_portsarrayPorts to expose publicly

TTL vs Hard TTL#

Sandbox0 uses two-tier TTL to balance resource efficiency and flexibility:

FieldBehaviorUse Case
ttlSoft 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_ttlHard delete: When expired, sandbox is permanently deleted regardless of pause state. Can also be extended via refresh API.Enforce maximum lifetime for security or cost control. The difference from ttl is the expiration behavior (delete vs pause).

The relationship: ttl <= hard_ttl. When ttl expires first, sandbox pauses but can be resumed. When hard_ttl expires, sandbox is deleted immediately. Both can be extended via the refresh API.

Example timeline (sandbox created with ttl=300 and hard_ttl=3600):

  • t=0: Sandbox created
  • t=300: TTL expires → sandbox auto-pauses
  • t=310: User calls refresh → TTL reset to 300, Hard TTL reset to 3600 (new hard deadline at t=3910)
  • t=610: TTL expires again → sandbox auto-pauses
  • t=3910: Hard TTL expires → sandbox deleted
go
ctx := 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.

GET

/api/v1/sandboxes/{id}

go
sb, 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).

GET

/api/v1/sandboxes/{id}/status

go
status, err := client.StatusSandbox(ctx, sandbox.ID) if err != nil { log.Fatal(err) } fmt.Printf("Status: %s\n", status.Status.Value)

List Sandboxes#

List all sandboxes with optional filters.

GET

/api/v1/sandboxes

Query Parameters#

ParameterTypeDescription
statusstringFilter by status (starting, running, paused, failed, completed)
template_idstringFilter by template ID
pausedbooleanFilter by paused state
limitintegerMax results per page (default: 50, max: 200)
offsetintegerPagination offset (default: 0)
go
limit := 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.

PUT

/api/v1/sandboxes/{id}

Updatable Fields#

Only the following fields can be updated at runtime:

FieldTypeDescription
ttlintegerTime to live in seconds (soft limit)
hard_ttlintegerMaximum lifetime in seconds (hard limit)
networkobjectNetwork policy configuration
auto_resumebooleanAuto-resume when accessed
exposed_portsarrayPorts to expose publicly

env_vars and webhook cannot be updated at runtime. These fields only take effect when the sandbox is created. To use different 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 Sandbox#

Pause a sandbox to save resources. The sandbox state is preserved.

POST

/api/v1/sandboxes/{id}/pause

When a sandbox is paused, all processes are stopped but memory state is preserved. Use auto_resume to automatically resume when accessed.

go
_, err = client.PauseSandbox(ctx, sandbox.ID) if err != nil { log.Fatal(err) } fmt.Println("Sandbox paused")

Resume Sandbox#

Resume a paused sandbox.

POST

/api/v1/sandboxes/{id}/resume

go
_, err = client.ResumeSandbox(ctx, sandbox.ID) if err != nil { log.Fatal(err) } fmt.Println("Sandbox resumed")

Refresh Sandbox TTL#

Extend the sandbox time-to-live. This resets both ttl and hard_ttl (if configured) from the current time.

POST

/api/v1/sandboxes/{id}/refresh

Request Body#

FieldTypeDescription
durationintegerDuration 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 minutes) 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.

DELETE

/api/v1/sandboxes/{id}

go
_, err = client.DeleteSandbox(ctx, sandbox.ID) if err != nil { log.Fatal(err) } fmt.Println("Sandbox deleted")

Next Steps#

Contexts

Run commands and manage processes (REPL and Cmd)

Files

Read, write, and manage files in sandboxes

Network Policy

Control network access and egress rules