01Documentation
Template
A template is the reusable blueprint for a sandbox. It defines the image, default resources, environment, metadata, and default network policy. Every sandbox is claimed from a template.
Warm capacity is shared across templates. A template does not own a CPU/memory profile or a private idle pool; see Unified Warm Pool.
Creating, updating, and deleting team-owned templates requires team admin
permissions. developer and builder roles can read templates.
Template Types#
| Type | Description | Visibility |
|---|---|---|
| Builtin | Platform-provided templates | Public to all teams |
| Custom | Templates created and owned by a team | Private to that team |
A platform system identity manages builtin templates. Team identities cannot write public template state.
Choose A Creation Method#
| Need | Prefer |
|---|---|
| Reproducible image build or a different base image | Create a template from an image |
| Reusable template ID from an initialized sandbox | Create a template from a sandbox |
| Reuse initialized RootFS state without a new template | Create a RootFS snapshot and claim with snapshot_id |
A template created from a sandbox retains an immutable regional block-COW RootFS generation. It does not republish the writable workspace as an OCI layer. The source template's digest-pinned base image and platform remain the runtime identity for the retained generation.
A RootFS snapshot is often better when the existing image, resource defaults, and network policy already fit. Snapshots do not appear in the template list; they can initialize new sandboxes claimed from a compatible template.
See Snapshot And Restore for snapshot, restore, fork, and rebase behavior.
Create From An Image#
/api/v1/templates
yaml# template.yaml spec: mainContainer: image: docker.io/library/python@sha256:<64-hex-digest> resources: memory: 4Gi ephemeralStorage: 8Gi envVars: PYTHONUNBUFFERED: "1" network: mode: block-all
bashs0 template create --id my-python-env --spec-file template.yaml
The request shape is:
json{ "template_id": "my-python-env", "spec": { "mainContainer": { "image": "docker.io/library/python@sha256:<64-hex-digest>", "resources": { "memory": "4Gi", "ephemeralStorage": "8Gi" } } } }
Image-based template creation returns 201 Created after validating the
canonical digest-pinned source. Manager then idempotently discovers every
required runtime platform and imports the exact image, procd identity, and
RootFS size into the regional block store. A claim returns data-plane-not-ready
until that durable import reaches ready. Template IDs are canonical within
their scope and cannot be renamed.
The public template API accepts memory but not CPU. CPU is derived by platform
policy. Scheduling class and warm-capacity configuration are platform-level
inputs rather than template fields. Image tags are mutable and are rejected;
use a normalized OCI reference ending in @sha256: and 64 lowercase hex
characters.
Create From A Sandbox#
/api/v1/templates/from-sandbox
This operation accepts a running or paused source and returns 202 Accepted.
It is asynchronous because Sandbox0 must capture and retain an immutable RootFS
generation.
| Field | Required | Description |
|---|---|---|
template_id | Yes | New team-owned template ID. |
sandbox_id | Yes | Source sandbox owned by the same team. |
spec_overrides | No | Only description, displayName, and tags may be overridden. |
bashcurl -X POST "$SANDBOX0_BASE_URL/api/v1/templates/from-sandbox" \ -H "Authorization: Bearer $SANDBOX0_TOKEN" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: python-workspace-v1" \ -d '{ "template_id": "python-workspace", "sandbox_id": "SOURCE_SANDBOX_ID", "spec_overrides": { "displayName": "Python workspace", "tags": ["python", "initialized"] } }'
The new template inherits safe runtime inputs from the source template. It does not copy sandbox identity, processes, memory, sessions, claim-time environment or network overrides, or services.
For a running source, ctld briefly barriers the exact active writer and
publishes a committed RootFS checkpoint. Concurrent writes can continue after
the short barrier. Request acceptance is not the capture point:
status.creation.capturedAt records the committed capture time.
Keep the source available while the status stage is capturing. Poll the
returned Location until status.creation.state becomes ready or failed:
bashs0 template get python-workspace
Creation states are:
| State | Stage | Meaning |
|---|---|---|
creating | capturing | Exact source writer is being validated and captured. |
creating | publishing | The immutable block-COW generation is being bound to the template. |
ready | publishing | The regional template source is committed and claimable. |
failed | Current stage | Creation failed closed; inspect reason and message. |
ready does not mean the RootFS is already attached on every node. A claim
still needs a compatible carrier, node capacity, and RootFS attachment.
Use the same Idempotency-Key and body to retry after an uncertain client
response. Reusing a key with a different body returns a conflict.
Get And List#
/api/v1/templates/{id}
/api/v1/templates
bashs0 template get my-python-env s0 template list
Lists include builtin templates and team-owned templates visible to the current identity. Internal RootFS attestation, build lease, and idempotency state are not exposed in the public representation.
Update#
/api/v1/templates/{id}
Updates replace the template spec. They affect future claims and do not rewrite already-running sandbox generations.
bashs0 template update my-python-env --spec-file template.yaml
A template still being created, or one whose asynchronous creation failed,
cannot be updated and returns 409 Conflict. CPU and scheduling fields remain
platform-controlled on update.
Delete#
/api/v1/templates/{id}
bashs0 template delete my-python-env
Deletion removes the logical template and durably queues cleanup of an internal RootFS generation, when present. Existing sandboxes keep their own lifecycle and RootFS state; new claims by the deleted template ID are rejected.