Skip to documentation
API + guides

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 supplies a default memory size, with CPU derived by platform policy, but does not reserve 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#

TypeDescriptionVisibility
BuiltinPlatform-provided templatesPublic to all teams
CustomTemplates created and owned by a teamPrivate to that team

A platform system identity manages builtin templates. Team identities cannot write public template state. When a team-owned template has the same ID as a builtin, get and claim prefer the team's template. Template IDs are scoped to the team or public namespace within a region.

Choose A Creation Method#

NeedPrefer
Reproducible image build or a different base imageCreate a template from an image
Reusable template ID from an initialized sandboxCreate a template from a sandbox
Reuse initialized RootFS state without a new templateCreate 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#

POST

/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
bash
s0 template create --id my-python-env --spec-file template.yaml

Replace <64-hex-digest> with the image's actual immutable digest before submitting the file.

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" } }, "envVars": {"PYTHONUNBUFFERED": "1"}, "network": {"mode": "block-all"} } }

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 initial RootFS capacity and immutable device geometry 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#

POST

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

FieldRequiredDescription
template_idYesNew team-owned template ID.
sandbox_idYesSource sandbox owned by the same team.
spec_overridesNoOnly description, displayName, and tags may be overridden.
bash
curl -fsS -X POST "$SANDBOX0_API_URL/api/v1/templates/from-sandbox" \ -H "Authorization: Bearer $SANDBOX0_API_KEY" \ -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. The retained RootFS still contains ordinary files written by the source, including any credentials or configuration saved there. The operation does not scrub those files.

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:

bash
s0 template get python-workspace

Creation states are:

StateStageMeaning
creatingcapturingExact source writer is being validated and captured.
creatingpublishingThe immutable block-COW generation is being bound to the template.
readypublishingThe regional template source is committed and claimable.
failedCurrent stageCreation 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#

GET

/api/v1/templates/{id}

GET

/api/v1/templates

bash
s0 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#

PUT

/api/v1/templates/{id}

Updates replace the template spec. They affect future claims and do not rewrite already-running sandbox generations.

bash
s0 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.

For a template created from a sandbox, keeping the same image retains its captured RootFS source. Changing mainContainer.image clears that source and queues its cleanup; future claims initialize from the new image import rather than the captured workspace. A resource change alone does not resize an already captured RootFS generation.

Delete#

DELETE

/api/v1/templates/{id}

bash
s0 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 fail when no template with that ID is visible. Deleting a private template that shadows a builtin exposes the builtin again, so subsequent claims with that ID use the builtin.

Next Steps#