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#