Templates
Templates let you build a custom container image from a Dockerfile and use it as the rootfs for any sandbox. You submit a Dockerfile, the system builds it asynchronously, and once the template reaches ready status you can reference it by name when creating sandboxes.
Get your API key from https://createos.nodeops.network/profile. Pass it as X-Api-Key: <token> on every request.
Base URL: https://api.sb.createos.sh
At a glance
- Base URL:
https://api.sb.createos.sh - Auth:
X-Api-Key: <token>header — get a token - Response envelope: JSend —
{"status": "...", "data": ...}
Dockerfile restrictions
Submitted Dockerfiles must:
- Be single-stage (exactly one
FROM). - Use a
FROMbase that is in the operator allowlist (e.g.nodeops/sandbox:debian,nodeops/sandbox:alpine). - Not contain
COPYorADDinstructions. - Not use
ARG-substitutedFROM(e.g.FROM ${BASE}). - Be at most 64 KiB.
Violations are rejected at submit time with a 400 response.
GET /v1/templates
List all templates owned by the caller.
Auth required: Yes
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 50 | Max items to return (maximum 500). |
offset | integer | 0 | Pagination offset. |
Example
Bash1curl https://api.sb.createos.sh/v1/templates \2 -H "X-Api-Key: $CREATEOS_API_KEY"
Success response 200
JSON1{2 "status": "success",3 "data": {4 "templates": [5 {6 "id": "tpl_01K…",7 "name": "my-python-env",8 "base": "nodeops/sandbox:debian",9 "status": "ready",10 "ext4_size_bytes": 536870912,11 "created_at": "2024-01-15T10:00:00Z",12 "built_at": "2024-01-15T10:01:30Z"13 }14 ]15 }16}
status values
| Value | Meaning |
|---|---|
pending | Queued, not yet picked up by a builder. |
building | Build in progress. |
ready | Build succeeded; usable as rootfs in sandbox create. |
failed | Build failed; check logs. |
POST /v1/templates
Submit a Dockerfile for async build. Returns immediately with the new template in pending status. Poll GET /v1/templates/{id} or stream GET /v1/templates/{id}/logs to follow progress.
Per-user concurrent build limit defaults to 2. Exceeding it returns 429.
Auth required: Yes
Request body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Friendly alias used when spawning sandboxes (rootfs=<name> resolves to the latest ready template with this name). 1–63 chars, lowercase alphanumeric and dash. |
dockerfile | string | Yes | Raw Dockerfile contents. Max 64 KiB. Must pass Dockerfile restrictions above. |
Example
Bash1curl -X POST https://api.sb.createos.sh/v1/templates \2 -H "X-Api-Key: $CREATEOS_API_KEY" \3 -H "Content-Type: application/json" \4 -d '{5 "name": "my-python-env",6 "dockerfile": "FROM nodeops/sandbox:debian\nRUN apt-get update && apt-get install -y python3 python3-pip"7 }'
Success response 200
JSON1{2 "status": "success",3 "data": {4 "id": "tpl_01K…",5 "name": "my-python-env",6 "base": "nodeops/sandbox:debian",7 "status": "pending",8 "ext4_size_bytes": 0,9 "created_at": "2024-01-15T10:00:00Z",10 "built_at": null11 }12}
Notable errors:
| Status | Cause |
|---|---|
400 | Invalid Dockerfile (multi-stage, disallowed base, COPY/ADD, ARG-substituted FROM, too large), or invalid name. |
429 | Concurrent build limit exceeded. |
GET /v1/templates/{id}
Get details for a single template. Resolves a friendly name to the latest ready template with that name.
Auth required: Yes
Path parameters
| Parameter | Description |
|---|---|
id | tpl_<ulid> id or friendly name. |
Query parameters
| Parameter | Type | Description |
|---|---|---|
include | string | Set to dockerfile to include the original Dockerfile source in the response. |
Example
Bash1curl "https://api.sb.createos.sh/v1/templates/my-python-env?include=dockerfile" \2 -H "X-Api-Key: $CREATEOS_API_KEY"
Success response 200 — same shape as the object in GET /v1/templates. When ?include=dockerfile is set, a dockerfile field is added to the data object containing the original Dockerfile source.
Notable errors: 404 — template not found.
GET /v1/templates/{id}/logs
Stream the build log for a template as NDJSON. Each line is one JSON object.
Auth required: Yes
Path parameters
| Parameter | Description |
|---|---|
id | tpl_<ulid> id. |
Response format
The response body is a stream of newline-delimited JSON objects (Content-Type: application/x-ndjson). Each line has this shape:
JSON1{"stream": "Step 1/3 : FROM nodeops/sandbox:debian\n"}
The stream field contains the raw build log output from the builder. The stream ends when the build completes (success or failure).
Example
Bash1curl https://api.sb.createos.sh/v1/templates/tpl_01K.../logs \2 -H "X-Api-Key: $CREATEOS_API_KEY"
Example output
{"stream":"Step 1/3 : FROM nodeops/sandbox:debian\n"}
{"stream":" ---> a1b2c3d4e5f6\n"}
{"stream":"Step 2/3 : RUN apt-get update\n"}
{"stream":" ---> Running in f1e2d3c4b5a6\n"}
{"stream":"Step 3/3 : RUN apt-get install -y python3\n"}
{"stream":"Successfully built 9a8b7c6d5e4f\n"}
Notable errors: 404 — template not found.
DELETE /v1/templates/{id}
Delete a template.
Auth required: Yes
Path parameters
| Parameter | Description |
|---|---|
id | tpl_<ulid> id or friendly name. |
Example
Bash1curl -X DELETE https://api.sb.createos.sh/v1/templates/tpl_01K... \2 -H "X-Api-Key: $CREATEOS_API_KEY"
Success response 200
JSON1{2 "status": "success",3 "data": {4 "id": "tpl_01K…",5 "status": "destroyed"6 }7}
Notable errors: 404 — template not found.
Using a template
Once a template reaches ready status, pass its name as the rootfs field when creating a sandbox:
Bash1curl -X POST https://api.sb.createos.sh/v1/sandboxes \2 -H "X-Api-Key: $CREATEOS_API_KEY" \3 -H "Content-Type: application/json" \4 -d '{"shape": "s-1vcpu-1gb", "rootfs": "my-python-env"}'
The name resolves to the latest ready template with that name, so you can rebuild (re-submit with the same name) and new sandboxes automatically pick up the latest version.