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

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.

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

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#

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 -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:

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.

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 by the deleted template ID are rejected.

Next Steps#