Skip to content

Sandboxes API

sandbox 是平台的核心资源,代表一个完全隔离的运行环境。

所有端点需要 developer 角色(GET 只读端点需要 viewer 及以上)。

POST /v1/sandboxes

创建 sandbox。

需要 developer 角色

http
POST /v1/sandboxes
Authorization: Bearer ask_X_...
Content-Type: application/json

请求体(v2 推荐)

json
{
  "image": "node:20-bookworm",
  "resources": {
    "cpu": 2,
    "memory": "4GiB",
    "disk": "10GiB"
  },
  "timeout": "30m",
  "ttl": "6h",
  "network": "allowlist",
  "env": { "NODE_ENV": "development" },
  "labels": { "project": "agent-x" },
  "secrets": [
    {
      "secret_id": "sec_xxx",
      "mount_type": "env",
      "target": "OPENAI_API_KEY"
    }
  ]
}
字段类型必填说明
imagestring镜像标签(如 node:20-bookworm);空 → worker 默认
resources.cpunumberCPU 核数,支持小数(如 0.5);0 = worker 默认
resources.memorystring内存上限,字符串单位(512MiB / 4GiB / 2GB);空 = worker 默认
resources.diskstring磁盘上限,字符串单位;空 = worker 默认
timeoutstring无操作自动 pause(30s / 5m / 2h / 1d);空 = 禁用
ttlstring绝对生存时间,同 duration 格式;空 = 禁用
networkstringsealed / allowlist / open(别名,见下);空 = 默认
envobject环境变量 dict
labelsobject自定义标签 dict
secretsarray注入的凭证列表(见下方说明)

network 别名:

别名含义
sealed完全断网,只有 lo
allowlistDNS + 配置好的白名单域(生产推荐)
open允许所有出站(开发调试)

duration 字符串30s / 5m / 2h / 1d / 1w,扩展 Go ParseDuration 加 d / w 单位。

size 字符串512KiB / 4GiB / 2GB / 1TiB,binary(KiB/MiB/GiB) 和 decimal(KB/MB/GB)都接受,大小写不敏感。

secrets 元素字段:

字段说明
secret_id已创建的 secret ID
mount_typefile(挂载为 tmpfs 文件)或 env(注入为环境变量)
targetfile 模式:/run/secrets/<target>env 模式:环境变量名

响应

201 Created

响应体始终用规范化后的字段(v2 风格):

json
{
  "id": "sbx_xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "state": "created",
  "image": "node:20-bookworm",
  "resources": {
    "cpu": 2,
    "memory": "4GiB",
    "disk": "10GiB"
  },
  "timeout": "30m",
  "ttl": "6h",
  "network": "allowlist",
  "created_at": 1716480000
}

调用方便利

请求时也支持 ?wait=running(Spec 45)— 服务端 block 到 sandbox 进入 running 再返回,省一轮 polling。SDK Sandbox.create() 默认带上这个 query。


GET /v1/sandboxes

列出当前租户所有 sandbox。

需要 viewer 角色

http
GET /v1/sandboxes
Authorization: Bearer ask_X_...

响应

200 OK

json
{
  "sandboxes": [
    {
      "id": "sbx_xxx",
      "state": "running",
      "profile": "code-lite",
      "created_at": 1716480000
    }
  ]
}

GET /v1/sandboxes/

获取单个 sandbox 详情。

需要 viewer 角色

http
GET /v1/sandboxes/{id}
Authorization: Bearer ask_X_...

响应

200 OK — 返回 SandboxDTO(字段同 POST 响应)

404 Not Found

json
{ "error": "sandbox: not found" }

POST /v1/sandboxes//start

启动 sandbox(created / stoppedrunning)。

需要 developer 角色

http
POST /v1/sandboxes/{id}/start
Authorization: Bearer ask_X_...

响应

200 OK

json
{ "id": "sbx_xxx", "state": "running", ... }

409 Conflict — 状态不允许 start

json
{ "error": "sandbox: invalid state transition" }

POST /v1/sandboxes//stop

停止 sandbox(runningstopped)。所有进程会被 kill。

需要 developer 角色

http
POST /v1/sandboxes/{id}/stop
Authorization: Bearer ask_X_...

响应

200 OK

json
{ "id": "sbx_xxx", "state": "stopped", ... }

POST /v1/sandboxes//pause

暂停 sandbox(runningpaused)。进程被冻结,内存保留。

需要 developer 角色

http
POST /v1/sandboxes/{id}/pause
Authorization: Bearer ask_X_...

响应

200 OK

json
{ "id": "sbx_xxx", "state": "paused", ... }

POST /v1/sandboxes//resume

恢复 sandbox(pausedrunning)。毫秒级恢复。

需要 developer 角色

http
POST /v1/sandboxes/{id}/resume
Authorization: Bearer ask_X_...

响应

200 OK

json
{ "id": "sbx_xxx", "state": "running", ... }

POST /v1/sandboxes//exec

在 sandbox 内执行一次性命令(同步,等待完成返回结果)。

需要 developer 角色

sandbox 必须处于 running 状态。

http
POST /v1/sandboxes/{id}/exec
Authorization: Bearer ask_X_...
Content-Type: application/json
json
{
  "command": ["bash", "-c", "echo $HOME && ls /workspace"]
}

响应

200 OK

json
{
  "stdout": "/root\napp.py\npackage.json\n",
  "stderr": "",
  "exit_code": 0
}

同步阻塞

exec 是同步接口,会等待命令完成才返回。不适合长时间运行的命令(如服务器启动)——那类用 processes 端点。


DELETE /v1/sandboxes/

销毁 sandbox(任意 alive 状态 → destroyed)。所有数据永久删除。

需要 developer 角色

http
DELETE /v1/sandboxes/{id}
Authorization: Bearer ask_X_...

响应

204 No Content — 销毁成功

404 Not Found — sandbox 不存在


POST /v1/sandboxes//expose

显式暴露 sandbox 内一个端口,返回 preview URL(Spec 50)。

需要 developer 角色

http
POST /v1/sandboxes/{id}/expose
Authorization: Bearer ask_X_...
Content-Type: application/json

请求体

json
{
  "port": 5173,
  "subdomain": "my-app",
  "sign": true,
  "ttl": "1h"
}
字段类型必填说明
portint容器端口(1–65535)
subdomainstring自定义 subdomain;空 → 用 sb-{id}-{port}
signbool是否生成签名 token(Spec 48);默认 false
ttlstring签名 token 有效期(duration string);默认 1h,最大 24h

响应

201 Created

json
{
  "port": 5173,
  "url": "http://sb-xxx-5173.preview.example.com",
  "source": "explicit",
  "signed": false
}

签名时 URL 带 ?token= query:

json
{
  "port": 5173,
  "url": "http://sb-xxx-5173.preview.example.com/?token=eyJ...",
  "source": "explicit",
  "signed": true,
  "expires_at": "2026-05-24T15:04:05Z"
}

DELETE /v1/sandboxes//expose/{port}

取消显式暴露。注意:动态发现源(Spec 39)暴露的端口无法 unexpose,要关掉 端口需要 kill 持有该端口的进程。

需要 developer 角色

http
DELETE /v1/sandboxes/{id}/expose/{port}
Authorization: Bearer ask_X_...

响应

  • 204 No Content — 取消成功
  • 404 Not Found — 该端口没被显式 expose 过

GET /v1/sandboxes//expose

列出 sandbox 当前所有暴露的端口(显式 + 动态发现)。

需要 viewer 角色

http
GET /v1/sandboxes/{id}/expose
Authorization: Bearer ask_X_...

响应

200 OK

json
{
  "ports": [
    {
      "port": 5173,
      "url": "http://sb-xxx-5173.preview.example.com",
      "source": "explicit",
      "signed": false
    },
    {
      "port": 3000,
      "url": "http://sb-xxx-3000.preview.example.com",
      "source": "dynamic",
      "signed": false
    }
  ]
}
字段说明
sourceexplicit(通过 POST /expose 显式注册)或 dynamic(port-watcher sidecar 自动发现,Spec 39)
signed是否带签名 token

详见 端口暴露概念


Sandbox DTO 字段说明(响应)

字段类型说明
idstringsandbox ID(sbx_ + 24 hex)
statestring当前状态,见生命周期
imagestring镜像标签
resources.cpunumberCPU 核数
resources.memorystring内存上限(如 4GiB
resources.diskstring磁盘上限
resources.pids_limitint64PID 数量上限
timeoutstring空闲自动 pause(duration string)
ttlstring绝对生存时间(duration string)
networkstring网络策略别名(sealed / allowlist / open
envobject环境变量 dict
labelsobject自定义标签 dict
last_active_atint64最后活跃时间(Unix 秒)
created_atint64创建时间(Unix 秒)
secretsarray绑定的凭证(元数据,不含 value)

Signed Preview Token

Issue a short-lived token that lets anyone holding it access the preview proxy for a specific port — no account required.

See Signed Preview URL for the full guide.

POST /v1/sandboxes/{id}/preview-token

Requires developer or owner role

http
POST /v1/sandboxes/{id}/preview-token
Authorization: Bearer ask_X_...
Content-Type: application/json

{
  "port": 5173,
  "ttl_seconds": 3600
}

Request body

FieldTypeRequiredDescription
portintyesContainer port to authorise (1–65535)
ttl_secondsint64noToken lifetime in seconds (default 3600, max 86400)

Response — 201 Created

json
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expires_at": "2026-05-24T15:04:05Z"
}

Use the token by appending ?token=<value> to the preview URL:

https://api.example.com/v1/sandboxes/sbx_xxx/preview/5173/?token=eyJ...

The token is stripped before forwarding to the upstream app and cannot be used on any other endpoint.

Error responses

CodeMeaning
400port out of range or request body invalid
401Not authenticated
403Insufficient role (viewer)
404Sandbox not found

基于 MIT License 发布