Skip to content

Template API

SandBase provides an E2B-compatible Template API. There are two parts:

  • Reading templates — list templates, get details, and resolve aliases. Public, used when creating sandboxes.
  • Building custom templates (v3) — create and build custom templates. Used internally by the SandBase team / E2B CLI; not required for everyday sandbox usage.

Which do I need?

If you only create sandboxes from existing templates (e.g. Sandbox.create("hermes")), you only need the read endpoints below. The build flow is for producing new custom templates and aligns with the E2B v3 build pipeline.

Base URL

https://api.sandbase.ai

Authentication

All template endpoints require authentication:

Authorization: Bearer sk-sb-YOUR_KEY

Or E2B SDK compatible:

X-API-Key: sk-sb-YOUR_KEY

The read endpoints are org-scoped: GET /templates returns all public (platform) templates plus your organization's own custom templates. A custom template owned by another organization returns 404 (its existence is not revealed).


Read Endpoints

List Templates

GET/templates

List templates accessible to your organization: all public (platform) templates plus your org's own custom templates.

Response:

json
[
  {
    "templateID": "hermes",
    "buildID": "build_abc123",
    "cpuCount": 4,
    "memoryMB": 8192,
    "diskSizeMB": 10240,
    "public": true,
    "aliases": ["hermes"],
    "names": ["hermes"],
    "createdAt": "2026-05-27T10:00:00Z",
    "updatedAt": "2026-05-27T10:00:00Z",
    "createdBy": null,
    "lastSpawnedAt": null,
    "spawnCount": 0,
    "buildCount": 1,
    "buildStatus": "ready"
  }
]

Each template object includes:

FieldTypeDescription
templateIDstringTemplate identifier
buildIDstringLast successful build ID
cpuCount / memoryMB / diskSizeMBintegerResource allocation
publicbooleanWhether the template is public
aliases (deprecated) / namesstring[]Template names
createdAt / updatedAtstringRFC 3339 timestamps
createdByobject | nullCreator (id, email), null for platform templates
lastSpawnedAtstring | nullLast time a sandbox used this template
spawnCount / buildCountintegerUsage and build counters
buildStatusstringbuilding, waiting, ready, error, uploaded

Get Template

GET/templates/:templateID

Get template details, including its build history.

Response:

json
{
  "templateID": "my-template",
  "buildID": "build_xyz789",
  "cpuCount": 2,
  "memoryMB": 2048,
  "diskSizeMB": 10240,
  "public": false,
  "aliases": ["my-template"],
  "names": ["my-template"],
  "createdAt": "2026-05-27T10:00:00Z",
  "updatedAt": "2026-05-27T10:05:00Z",
  "builds": [
    {
      "buildID": "build_xyz789",
      "templateID": "my-template",
      "status": "ready",
      "cpuCount": 2,
      "memoryMB": 2048,
      "startedAt": "2026-05-27T10:00:00Z",
      "finishedAt": "2026-05-27T10:03:00Z"
    }
  ]
}

Check Alias

GET/templates/aliases/:alias

Check whether a template alias exists.

Response (200):

json
{ "templateID": "my-template" }

Response (404): Template not found.


Build a Custom Template (v3)

The v3 build flow aligns with the E2B CLI/SDK build pipeline. It separates template creation, layer upload, and build execution:

1. POST   /v3/templates                              create template (name + tags)
2. GET    /templates/:id/files/:hash                 get upload link for each build layer
3. POST   /v2/templates/:id/builds/:buildID          start the build (fromImage / steps)
4. GET    /templates/:id/builds/:buildID/status      poll status until ready
   GET    /templates/:id/builds/:buildID/logs        (optional) stream build logs

Use the E2B CLI

The simplest way to build is the E2B CLI pointed at SandBase — it orchestrates all four steps for you:

bash
export E2B_API_URL=https://api.sandbase.ai
export E2B_API_KEY=sk-sb-YOUR_KEY
e2b template build --name my-agent --dockerfile ./Dockerfile

1. Create Template (v3)

POST/v3/templates

Request:

json
{
  "name": "my-template:v1",
  "tags": ["latest"],
  "cpuCount": 4,
  "memoryMB": 8192
}
FieldTypeRequiredDescription
namestringTemplate name, optionally name:tag
tagsstring[]Tags to assign to the build
cpuCountintegerCPU cores (default 2)
memoryMBintegerMemory in MB (default 512)
aliasstringDeprecated — use name

The name field supports name:tag format. If a tag is included in the name, it's treated as if it were passed in the tags array.

Response (202 Accepted):

json
{
  "templateID": "my-template",
  "buildID": "build_xyz789",
  "status": "waiting",
  "public": false,
  "aliases": ["my-template"]
}
GET/templates/:templateID/files/:hash

Get a pre-signed upload URL for a build layer (tar archive), keyed by content hash.

Response (200):

json
{
  "present": false,
  "url": "https://storage.e2b.dev/upload/..."
}

If present: true, the layer is already cached and no upload is needed.

3. Start Build

POST/v2/templates/:templateID/builds/:buildID

Start the build for the created template/build pair.

Request:

json
{
  "fromImage": "docker.e2b.dev/e2b/custom-envs/my-template:build_xyz",
  "startCmd": "/bin/bash",
  "readyCmd": "echo ready",
  "force": false
}
FieldTypeDescription
fromImagestringBase image for the build
fromTemplatestringBase template (alternative to fromImage)
startCmdstringCommand run when a sandbox starts
readyCmdstringCommand that must exit 0 for the template to be ready
forcebooleanRebuild regardless of cache (default false)

Response: 202 Accepted

4. Get Build Status

GET/templates/:templateID/builds/:buildID/status

Poll build progress.

Query Parameters:

ParamTypeDefaultDescription
logsOffsetinteger0Starting log index
limitinteger100Max logs to return (max 100)
levelstringFilter by level: debug, info, warn, error

Response:

json
{
  "templateID": "my-template",
  "buildID": "build_xyz789",
  "status": "building",
  "logs": ["Step 1/5: FROM python:3.11", "Step 2/5: RUN pip install numpy"],
  "logEntries": [
    {
      "timestamp": "2026-05-27T10:00:01Z",
      "message": "Step 1/5: FROM python:3.11",
      "level": "info"
    }
  ]
}

Build statuses: building, waiting, ready, error, uploaded

On error, a reason object with a message is included.

(Optional) Get Build Logs

GET/templates/:templateID/builds/:buildID/logs

Get paginated structured build logs.

ParamTypeDefaultDescription
cursorinteger0Starting timestamp (ms)
limitinteger100Max entries (max 100)
directionstringforwardforward or backward
levelstringFilter by level

Manage Templates

Update Template

PATCH/templates/:templateID

Update template metadata (e.g. visibility).

json
{ "public": true }

Delete Template

DELETE/templates/:templateID

Delete a template and all its builds. Returns 204 No Content.

Tags

GET    /templates/:templateID/tags    list tags
POST   /templates/tags                assign tags
DELETE /templates/tags                delete tags

Assign tags:

json
{ "target": "my-template:build_xyz789", "tags": ["latest", "v2.0"] }

Delete tags:

json
{ "name": "my-template", "tags": ["v1.0"] }

Using Templates

Python (E2B SDK)

python
from e2b import Sandbox

# Create a sandbox from any template
sandbox = Sandbox("hermes", api_url="https://api.sandbase.ai")

JavaScript (E2B SDK)

javascript
import { Sandbox } from 'e2b'

const sandbox = await Sandbox.create('hermes', {
  apiUrl: 'https://api.sandbase.ai',
})

Legacy build flows

Earlier E2B build flows — the v1 POST /templates (inline Dockerfile) and the standalone v2 POST /v2/templates create — still exist on the backend for backward compatibility but are not part of the recommended path. New builds should use the v3 flow above, which is what the current E2B CLI/SDK uses.