All of these need sandboxes:run and a running sandbox. Set SBX to your sandbox's ID in the examples.

Run a command

POST /v1/sandboxes/{sandbox_id}/exec runs a command and, by default, waits for it to exit:

bash
curl -s "https://beta-api.b3os.org/v1/sandboxes/$SBX/exec" \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"cmd": "python3 -c \"print(2 + 2)\""}'
json
{ "object": "exec_result", "exit_code": 0, "signal": null, "timed_out": false, "stdout": "4\n", "stderr": "", "stdout_truncated": false, "stderr_truncated": false, "duration_ms": 21.6}

The values are illustrative. cmd as a string runs through /bin/sh -c; as an array (["node", "--version"]) it runs directly. Other fields: cwd (default /workspace), env, stdin (written to the command, then closed), user (user or root) and timeout_ms. A buffered call waits at most 60 seconds and returns up to 1 MiB of each stream; stdout_truncated says when output was dropped. A command killed at its timeout returns timed_out: true and the signal, KILL.

Stream the output

Add ?stream=true (or send Accept: text/event-stream) to get output while the command runs, as exec.stdout and exec.stderr events, then exec.exit with the exit code. A streamed command may run up to an hour.

bash
curl -N -s "https://beta-api.b3os.org/v1/sandboxes/$SBX/exec?stream=true" \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"cmd": "for i in 1 2 3; do echo $i; sleep 1; done", "timeout_ms": 60000}'

Run in the background

background: true returns at once with the process, for servers and long jobs:

bash
curl -s "https://beta-api.b3os.org/v1/sandboxes/$SBX/exec" \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"cmd": "npm run dev", "cwd": "/workspace/app", "background": true}'# {"object": "process", "pid": 812, "cmd": "npm run dev", "status": "running", ...}
  • GET /v1/sandboxes/{sandbox_id}/processes lists background processes, running or exited.
  • GET /v1/sandboxes/{sandbox_id}/logs streams their output as log.stdout and log.stderr events, then process.exited. It starts with up to 1 MiB of buffered output per process; filter with pid, and pass follow=false to stop after the buffered output.
  • POST /v1/sandboxes/{sandbox_id}/processes/{pid}/kill sends TERM (or KILL, INT, HUP) to the process and its process group.

Run code in a kernel

Sandboxes from the code-interpreter template have a Jupyter kernel. POST /v1/sandboxes/{sandbox_id}/run_code runs code in it and returns rich results; state persists between calls, like cells in a notebook:

bash
curl -s "https://beta-api.b3os.org/v1/sandboxes/$SBX/run_code" \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"code": "import math\nmath.sqrt(2)\n"}'
json
{ "object": "run_code_result", "language": "python", "execution_count": 3, "results": [{ "mime_type": "text/plain", "data": "1.4142135623730951", "is_main_result": true }], "stdout": "", "stderr": "", "error": null, "duration_ms": 4.8}

language is python (the default) or javascript. Results carry their MIME type, so plots come back as images and data frames as HTML. A cell that raises returns the exception in error. Other templates answer kernel_unavailable.

Files

CallDoes
GET /v1/sandboxes/{sandbox_id}/files?path=/workspace/main.pyReturns the file's bytes
GET /v1/sandboxes/{sandbox_id}/files?path=/workspace&list=1Lists a directory as JSON: name, path, type, size, mode, modified time
PUT /v1/sandboxes/{sandbox_id}/files?path=/workspace/main.pyWrites the request body to the path, replacing any file; mkdir=1 creates parent directories, mode sets a new file's permissions
bash
curl -s -X PUT "https://beta-api.b3os.org/v1/sandboxes/$SBX/files?path=/workspace/data/input.csv&mkdir=1" \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/octet-stream" \ --data-binary @input.csv

Paths are absolute. A transfer carries at most 64 MiB; for larger files, fetch them from inside the sandbox.

Open a terminal

GET /v1/sandboxes/{sandbox_id}/pty upgrades to a WebSocket attached to a new pseudo-terminal running the login shell, or cmd. Binary frames carry terminal bytes both ways. Text frames carry JSON control messages: send {"type": "resize", "cols": 120, "rows": 40}; the server sends {"type": "exit", "code": 0} before it closes. Pass cols, rows, cmd and cwd as query parameters.

From a browser, get a stream ticket with POST /v1/sandboxes/{sandbox_id}/ticket and open the socket within 30 seconds:

js
const { ticket } = await (await fetch(`/api/my-backend/ticket?sandbox=${sandboxId}`)).json();const socket = new WebSocket( `wss://beta-api.b3os.org/v1/sandboxes/${sandboxId}/pty?cols=120&rows=40`, ["b3os.v1", `b3os.ticket.${ticket}`],);socket.binaryType = "arraybuffer";

Mint the ticket on your server with your key, never in the browser. The CLI opens the same terminal with b3os sandbox shell.

Ask a question... ⌘I