Create Sandbox
Creates a sandbox from an environment in the same namespace and starts its pod. Resolves the workload command (request argv, then the environment's default_argv, then the image ENTRYPOINT/CMD; exec_only runs nothing), creates any ephemeral workspace mounts, and applies the base egress policy (deny-all when none is given; the egress bootstrap defaults to 24h when max_lifetime_sec is 0). Rejects an environment in another namespace (PermissionDenied), platform-owned env names (InvalidArgument), both workspace_id and workspaces set, more than 8 mounts, a non-absolute or unclean working_dir, and a durable workspace already attached to another live sandbox (FailedPrecondition). Unimplemented without cluster access.
Access: namespace OPERATOR or above (write)
Authorization
BearerAuth A namespace-scoped API key (cpk_…) for machines, or a Xeonr Auth OIDC
token for humans. The key's namespace and role are pinned server-side.
In: header
Header Parameters
Define the version of the Connect protocol
Define the timeout, in ms
Request Body
application/json
1 <= length <= 641 <= length <= 64Deprecated: use workspaces. Treated as a single read-write mount at
/workspace when set. Setting both is an error rather than a merge.
length <= 128steady-state; usually MODE_NONE
0 = never; validate:skip the server accepts any value (no bound applied)
0 = none; validate:skip the server accepts any value (no bound applied)
user-defined display name (console-required)
length <= 4096Workload env — same contract as RunJobRequest.env: pod-spec visible, not a secret channel, platform-owned names rejected.
properties <= 4096The filesystems this sandbox should see. Each is durable, an immutable snapshot, or ephemeral — see WorkspaceMount. Empty is legal: a sandbox with no mounts starts in its image's own WORKDIR with only /tmp writable. At most 8 mounts.
items <= 8Where the workload starts. Absolute; empty selects the default, which differs by primitive on purpose:
sandbox the first read-write mount — an interactive user has to land somewhere writable job the first read-write mount — inputs are already staged there app the IMAGE'S OWN WORKDIR. An App runs an image built elsewhere and that WORKDIR is part of its contract, so the platform does not override it just because the version happens to declare a writable mount.
Set it explicitly when the default is wrong: a monorepo mounted at /workspace whose build runs in /workspace/apps/web has no other way to say so, and relying on the default couples the working directory to the ORDER of the mount list, which is not something a caller expects to matter.
length <= 4096The command to run in this sandbox. Empty selects the environment's
default_argv, then the image's own ENTRYPOINT/CMD — so a sandbox built on
an image that starts a dev server starts it, rather than starting nothing.
BEHAVIOUR CHANGE: sandboxes previously ran a keepalive INSTEAD of the image's
entrypoint, so an existing sandbox that was only ever exec'd into may now
start running something. Set exec_only to keep the old behaviour.
items <= 4096Run nothing: no default_argv, no image entrypoint, just a sandbox to exec
into. This is the opt-out from the resolution above, and is NOT the same as
an empty argv — empty means "resolve one", this means "there is none". validate:skip a bool has no bounds
What to do with the COMMAND when it exits. Default NEVER. enum.defined_only = true
"SANDBOX_RESTART_UNSPECIFIED" | "SANDBOX_RESTART_NEVER" | "SANDBOX_RESTART_ON_FAILURE" | "SANDBOX_RESTART_ALWAYS"What to do with the SANDBOX once the run has ended and is not being restarted. Default SUSPEND_ON_SUCCESS. enum.defined_only = true
"SANDBOX_ON_EXIT_UNSPECIFIED" | "SANDBOX_ON_EXIT_SUSPEND_ON_SUCCESS" | "SANDBOX_ON_EXIT_KEEP" | "SANDBOX_ON_EXIT_SUSPEND"Response Body
application/json
application/json
curl -X POST "https://containers.xeonr.io/containers.api.v1.SandboxService/CreateSandbox" \ -H "Connect-Protocol-Version: 1" \ -H "Connect-Timeout-Ms: 1000" \ -H "Content-Type: application/json" \ -d '{}'{
"sandbox": {
"sandboxId": "string",
"namespace": "string",
"environmentId": "string",
"workspaceId": "string",
"state": "SANDBOX_STATE_UNSPECIFIED",
"ports": [
{
"port": 0,
"url": "string",
"accessToken": "string",
"auth": "AUTH_UNSPECIFIED"
}
],
"createdAtUnix": "string",
"resources": {
"cpuMillis": 0,
"memoryMb": 0,
"ephemeralMb": 0,
"pids": 0
},
"idleSuspendSec": 0,
"maxLifetimeSec": 0,
"workspaceCache": {
"policy": "POLICY_UNSPECIFIED",
"writebackSec": 0
},
"egressGrant": {
"mode": "MODE_UNSPECIFIED",
"expiresAtUnix": "string",
"reason": "string",
"policy": {
"mode": "MODE_UNSPECIFIED",
"allow": [
{
"hostPattern": "string",
"ports": [
0
],
"mode": "RULE_MODE_UNSPECIFIED",
"pathPrefixes": [
"string"
],
"methods": [
"string"
],
"maxResponseBytes": "string",
"allowPlainHttp": true
}
],
"presets": [
"string"
],
"allowPlainHttp": true
},
"id": "string"
},
"runtimeEgress": {
"mode": "MODE_UNSPECIFIED",
"allow": [
{
"hostPattern": "string",
"ports": [
0
],
"mode": "RULE_MODE_UNSPECIFIED",
"pathPrefixes": [
"string"
],
"methods": [
"string"
],
"maxResponseBytes": "string",
"allowPlainHttp": true
}
],
"presets": [
"string"
],
"allowPlainHttp": true
},
"label": "string",
"egressGrants": [
{
"mode": "MODE_UNSPECIFIED",
"expiresAtUnix": "string",
"reason": "string",
"policy": {
"mode": "MODE_UNSPECIFIED",
"allow": [
{
"hostPattern": "string",
"ports": [
0
],
"mode": "RULE_MODE_UNSPECIFIED",
"pathPrefixes": [
"string"
],
"methods": [
"string"
],
"maxResponseBytes": "string",
"allowPlainHttp": true
}
],
"presets": [
"string"
],
"allowPlainHttp": true
},
"id": "string"
}
],
"env": {
"property1": "string",
"property2": "string"
},
"workspaces": [
{
"snapshotId": "string",
"mountPath": "string",
"readOnly": true,
"workspaceId": "string",
"ephemeral": true,
"ephemeralFromSnapshotId": "string",
"volume": {
"sizeMb": "string",
"seedSnapshotId": "string",
"cacheKey": "string"
}
}
],
"workingDir": "string",
"argv": [
"string"
],
"restart": "SANDBOX_RESTART_UNSPECIFIED",
"onExit": "SANDBOX_ON_EXIT_UNSPECIFIED",
"runState": "RUN_STATE_UNSPECIFIED",
"run": 0,
"lastExitCode": 0
}
}{
"code": "not_found",
"message": "string",
"details": [
{
"type": "string",
"value": "string",
"debug": {}
}
]
}Sandboxes
Long-lived interactive sessions — exec, suspend/resume, live egress grants and preview URLs.
Delete Sandbox POST
Deletes a sandbox: hard-kills its pod, revokes its agent key, drops its egress binding, console sessions and preview exposures, removes the record, then deletes any ephemeral workspaces it owned. No flush and no snapshot: snapshot first to keep content. **Access:** namespace OPERATOR or above (write)