NodeOps
UK

Execution & Files

Run commands inside a sandbox and transfer files in and out.


At a glance

  • Base URL: https://api.sb.createos.sh
  • Auth: X-Api-Key: <token> header — get a token
  • Response envelope: JSend — {"status": "...", "data": ...}

POST /v1/sandboxes/{id}/exec

Run a command inside a running sandbox, either buffered (default) or as a live NDJSON stream.

Auth required: Yes

Path parameters

ParameterDescription
idSandbox id

Query parameters

ParameterTypeDefaultDescription
streambooleanfalseWhen true, response is application/x-ndjson (one ExecStreamEvent per line). Equivalent to setting stream: true in the request body.

Request body

FieldTypeRequiredDescription
cmdstringYesProgram to execute (absolute path or PATH-resolved).
argsstring[]NoArgument list.
stdinstringNoOptional stdin passed to the process.
envobjectNoPer-exec environment variable overrides. Every key must have been declared in the sandbox's envs at create time — you can override a value, but cannot introduce new keys. Undeclared keys return 400.
streambooleanNoEquivalent to ?stream=true query parameter.

Note: Background processes must detach (redirect stdio + &) or the exec blocks until they exit.


Buffered mode (default)

Returns after the command exits. Response is a standard JSend success envelope with data.result.

Example request

Bash
1curl -X POST https://api.sb.createos.sh/v1/sandboxes/sb_01K.../exec \
2 -H "X-Api-Key: $CREATEOS_API_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{"cmd": "/usr/bin/python3", "args": ["-c", "print(1+1)"]}'

Example response

JSON
1{
2 "status": "success",
3 "data": {
4 "result": {
5 "stdout": "2\n",
6 "stderr": "",
7 "exit_code": 0
8 },
9 "exec_ms": 124.7
10 }
11}

Streaming mode (?stream=true)

The server emits one JSON object per line over Content-Type: application/x-ndjson (HTTP/1.1 chunked). The terminal frame carries exit_code. Heartbeat lines ({"hb":true}) are emitted every 5 seconds so a dead client is detected and the in-VM command killed within ~5 s of disconnect.

Each line is an ExecStreamEvent:

FieldDescription
stdoutstdout chunk (string)
stderrstderr chunk (string)
hbHeartbeat marker; clients should ignore
exit_codeTerminal frame — last event sent
errorAgent-level failure (couldn't start command)

In any one event, exactly one field is meaningful; the rest are zero/absent.

Example request

Bash
1curl -X POST "https://api.sb.createos.sh/v1/sandboxes/sb_01K.../exec?stream=true" \
2 -H "X-Api-Key: $CREATEOS_API_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{"cmd": "/bin/bash", "args": ["-c", "for i in 1 2 3; do echo $i; sleep 1; done"]}'

Example stream output

{"stdout":"1\n"}
{"hb":true}
{"stdout":"2\n"}
{"stdout":"3\n"}
{"exit_code":0}

Notable errors: 404 sandbox not found or not running, 400 undeclared env key.


PUT /v1/sandboxes/{id}/files

Upload a file into the sandbox.

Auth required: Yes

Path parameters

ParameterDescription
idSandbox id

Query parameters

ParameterTypeRequiredDescription
pathstringYesAbsolute path inside the VM. .. is rejected. Parent directories are auto-created.

Request body

Raw file bytes. Content-Type: application/octet-stream. Maximum size: 500 MiB.

Example request

Bash
1curl -X PUT "https://api.sb.createos.sh/v1/sandboxes/sb_01K.../files?path=/workspace/main.py" \
2 -H "X-Api-Key: $CREATEOS_API_KEY" \
3 -H "Content-Type: application/octet-stream" \
4 --data-binary @main.py

Example response

JSON
1{
2 "status": "success",
3 "data": {}
4}

Path rules: Path must be absolute (start with /). Relative paths like script.py are rejected with 400.

Notable errors: 400 invalid path or file too large, 404 sandbox not found.


GET /v1/sandboxes/{id}/files

Download a file from the sandbox.

Auth required: Yes

Path parameters

ParameterDescription
idSandbox id

Query parameters

ParameterTypeRequiredDescription
pathstringYesAbsolute path inside the VM. .. is rejected.

Example request

Bash
1curl -o result.csv \
2 "https://api.sb.createos.sh/v1/sandboxes/sb_01K.../files?path=/workspace/result.csv" \
3 -H "X-Api-Key: $CREATEOS_API_KEY"

The response body is the raw file bytes (Content-Type: application/octet-stream).

Notable errors: 404 sandbox or file not found.


Tip: tarball directory transfer

To move a whole directory, tar it on the client, upload the bundle, then unpack inside the sandbox:

Bash
1# Upload directory
2tar -c mydir | curl -X PUT \
3 "https://api.sb.createos.sh/v1/sandboxes/sb_01K.../files?path=/tmp/bundle.tar" \
4 -H "X-Api-Key: $CREATEOS_API_KEY" \
5 -H "Content-Type: application/octet-stream" \
6 --data-binary @-
7
8# Unpack inside sandbox
9curl -X POST https://api.sb.createos.sh/v1/sandboxes/sb_01K.../exec \
10 -H "X-Api-Key: $CREATEOS_API_KEY" \
11 -H "Content-Type: application/json" \
12 -d '{"cmd": "tar", "args": ["-C", "/workspace", "-xf", "/tmp/bundle.tar"]}'

100,000+ Builders. One Workspace.

Get product updates, builder stories, and early access to features that help you ship faster.

CreateOS is a unified intelligent workspace where ideas move seamlessly from concept to live deployment, eliminating context-switching across tools, infrastructure, and workflows with the opportunity to monetize ideas immediately on the CreateOS Marketplace.