Banata

Sandboxes

Sandbox File System

Reading, writing, listing files, creating checkpoints, and downloading artifacts from Banata sandbox environments.

Every sandbox has a /workspace directory that serves as the root for your project files. The file system API lets you read, write, and list files remotely without needing a terminal session.


Reading Files

bash
curl "https://api.boxes.banata.dev/v1/sandboxes/fs/read?id=SANDBOX_ID&path=/workspace/output.json" \
  -H "Authorization: Bearer br_live_..."

Both id and path are required query parameters.


Writing Files

bash
curl -X POST "https://api.boxes.banata.dev/v1/sandboxes/fs/write" \
  -H "Authorization: Bearer br_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "id": "SANDBOX_ID",
    "path": "/workspace/config.json",
    "content": "{\"key\": \"value\"}"
  }'

All three fields (id, path, content) are required. If the file already exists, it is overwritten. Parent directories are created automatically.

Writing and executing code

A common pattern is writing a script file and then executing it:

typescript
// Write a script
await fetch("https://api.boxes.banata.dev/v1/sandboxes/fs/write", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${apiKey}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    id: sandboxId,
    path: "/workspace/scraper.ts",
    content: `
      const res = await fetch("https://api.example.com/data");
      const data = await res.json();
      await Bun.write("/workspace/output.json", JSON.stringify(data, null, 2));
      console.log("Done:", data.length, "records");
    `,
  }),
});
 
// Execute it
await fetch("https://api.boxes.banata.dev/v1/sandboxes/exec", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${apiKey}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    id: sandboxId,
    command: "cd /workspace && bun run scraper.ts",
  }),
});

Listing Directories

bash
curl "https://api.boxes.banata.dev/v1/sandboxes/fs/list?id=SANDBOX_ID&path=/workspace" \
  -H "Authorization: Bearer br_live_..."

id is required. path defaults to /workspace if omitted.


Checkpoints

Save a snapshot of the workspace and outputs to persistent storage:

bash
curl -X POST "https://api.boxes.banata.dev/v1/sandboxes/checkpoint" \
  -H "Authorization: Bearer br_live_..." \
  -H "Content-Type: application/json" \
  -d '{"id": "SANDBOX_ID"}'

Checkpoints capture the workspace state and upload it to cloud storage. This is useful for:

  • Preserving work before ending a sandbox
  • Creating restore points during long-running tasks
  • Saving outputs for later retrieval

To enable checkpointing, you can set capabilities.storage.workspace to "checkpointed" when creating the sandbox:

json
{
  "runtime": "bun",
  "capabilities": {
    "storage": { "workspace": "checkpointed" }
  }
}

Artifacts

Artifacts are files produced by a sandbox that are persisted to cloud storage independently of the workspace.

Listing artifacts

bash
curl "https://api.boxes.banata.dev/v1/sandboxes/artifacts?id=SANDBOX_ID" \
  -H "Authorization: Bearer br_live_..."

Response:

json
{
  "id": "SANDBOX_ID",
  "artifacts": {
    "workspaceKey": "workspaces/org123/sandbox456.tar.gz",
    "checkpointKey": "checkpoints/org123/sandbox456.tar.gz",
    "items": [
      {
        "key": "artifacts/org123/sandbox456/report.pdf",
        "path": "/workspace/output/report.pdf",
        "kind": "output",
        "createdAt": 1772078705353,
        "contentType": "application/pdf",
        "sizeBytes": 245760
      }
    ],
    "updatedAt": 1772078710000
  }
}

Downloading artifacts

Get a signed download URL for any artifact:

bash
curl "https://api.boxes.banata.dev/v1/sandboxes/artifacts/download?id=SANDBOX_ID&key=artifacts/org123/report.pdf&expiresIn=3600" \
  -H "Authorization: Bearer br_live_..."

Response:

json
{
  "id": "SANDBOX_ID",
  "key": "artifacts/org123/report.pdf",
  "url": "https://storage.example.com/signed-url...",
  "expiresInSeconds": 3600
}
ParameterTypeRequiredDescription
idstringYesSandbox session ID
keystringYesArtifact key from the artifacts list
expiresInnumberNoURL validity in seconds (1–86400, default: 3600)

The returned URL can be used to download the file directly. It is valid for the specified duration (default 1 hour, maximum 24 hours).

The artifact key must belong to the specified sandbox session — you cannot download artifacts from other sessions.


Setting an Artifact Prefix

When creating a sandbox, you can set a custom prefix for artifact storage:

json
{
  "runtime": "bun",
  "capabilities": {
    "storage": {
      "artifactPrefix": "my-project/batch-1/"
    }
  }
}

This organizes your artifacts under a predictable path structure.


Persistence Rules

LocationDuring SessionAcross Pause/ResumeAfter Ending
/workspacePersistsPersistsDestroyed (unless checkpointed)
/tmpPersistsMay not persistDestroyed
ArtifactsAvailable via APIAvailable via APIAvailable via API
CheckpointsAvailable via APIAvailable via APIAvailable via API

Error Responses

StatusBodyCause
400Missing required field: pathpath not provided on read/write
400Missing required field: contentcontent not provided on write
400Invalid expiresInValue not between 1–86400
403Artifact key is not associated with this sandboxTrying to download another session's artifact
404Sandbox session not foundInvalid session ID
409Sandbox has no assigned machineSession not yet assigned
429Rate limit exceededOver 300 file operations per minute

Next Steps