Skip to content
OpenRelay is in early access, and the /v1 API is stable. New capabilities ship in the changelog.
Skip to Content
API ReferenceComputeSandboxes

Create a sandbox

Starts a sandbox from a template, optionally running a first command. Collect the result as JSON or stream output as NDJSON. With run set, application/json waits for the command to exit and answers the sandbox with its result; application/x-ndjson streams one SandboxEvent per line, the first naming the sandbox. Send an Idempotency-Key on every create. A repeat with the same key and body answers the same sandbox with Idempotent-Replayed: true, and a repeat with X-Resume-From skips the output it already read. A refusal (429 or 503) keeps nothing, so the next attempt runs again.

Required permission

Requires the sandboxes.create permission. See Permissions for the roles and API key permissions that include it.

Command line

The orl CLI wraps this endpoint:

Guided workflow: orl sandbox create

orl sandbox create --template <template>
POST
/v1/sandboxes

Authorization

apiKey
headerAuthorizationBearer <token>

OpenRelay API key. Send it as Authorization: Bearer or_… (legacy vl_… keys still work).

Header Parameters

Idempotency-Key?string

Makes a retried create safe. Choose one value per create you mean to make, 1 to 512 bytes (bytes, not characters), such as a UUID, and send it again on every retry of that create. The first request with a key runs, and a 2xx answer is kept for 24 hours: a repeat with the same key and the same body gets that answer back, with the same status and the header Idempotent-Replayed: true, and creates nothing. A batch create compares the body byte for byte; a VM or pod create compares the fields it decodes, so whitespace and key order do not count. A repeat while the first request is still running answers 409; repeat it a second later. The same key with a different body answers 422. An answer other than a 2xx is not kept, so a retry after a 4xx or a 5xx runs again. A 2xx too large to keep holds the key without it: every repeat answers 409 and creates nothing. Keys are scoped to the organization and the operation.

Length1 <= length
X-Resume-From?integer

On a replayed create, the seq of the last line already read. The stream resumes after it.

Range0 <= value

Request Body

application/json
  1. body
template*string

A template id from GET /v1/sandbox-templates: a built-in or one of the organization's.

run?
cpu?integer

The sandbox's vCPUs, its cgroup's limit. Every sandbox is restored from its template's snapshot and has the template's machine: absent, the sandbox gets the template's vCPUs, and more than the template's is refused with RESOURCES_EXCEED_TEMPLATE.

Range1 <= value
memoryMiB?integer

The sandbox's memory in MiB, its cgroup's limit. Absent, the template's; more than the template's is refused with RESOURCES_EXCEED_TEMPLATE, as for cpu.

cpuRequest?number

The vCPUs a shared sandbox is counted and billed for at least, to the thousandth, at most cpu. cpu stays its limit. A pinned sandbox's request is its cpu. Ignored unless the organization has requests.

Range0.25 <= value
Default0.25
memoryRequestMiB?integer

The memory a shared sandbox is counted and billed for at least, at most memoryMiB, which stays its limit: the guest may grow past its request to its limit. A pinned sandbox's request is its memoryMiB. Ignored unless the organization has requests.

Range128 <= value
Default128
timeoutSeconds?integer
Rangevalue <= 86400
Default300
placement?string
Default"shared"
Value in"shared""pinned"
env?
egress?
network?

The sandbox's network policy layer, a ceiling under the organization's, its user's and its key's. Not with egress. Absent, and with no egress, the organization's defaults apply. Refused (400) unless the organization has sandbox network policy.

metadata?
ephemeral?boolean

Omit customer history when the sandbox ends. Running commands keep their normal lifetime; completing a command does not stop the sandbox.

Defaultfalse
waitSeconds?integer

How long the request may wait for capacity before it answers 503 CAPACITY_EXHAUSTED. A longer wait is cut to the maximum.

Range0 <= value <= 120
Default10
autoPause?boolean

Consent to be snapshotted to disk when the host needs the memory, and woken by the next operation on the sandbox. Its processes stop for that long and its TCP connections end; the time on disk is not charged. Ignored unless the organization has auto-pause.

Defaultfalse

Response Body

The sandbox. With run set, application/json waits for the command to exit and carries its result; application/x-ndjson streams it.

  1. response
id*string

Opaque; do not parse it.

template*string
state*string

paused is a sandbox its owner paused, until it is resumed. Its timeout counts on.

Value in"running""paused""exited"
createdAt*string
Formatdate-time
expiresAt*string
Formatdate-time
endedAt?string
Formatdate-time
exitReason?string

Why the sandbox ended. Absent while it runs.

Value in"killed""timeout""guest_exit""host_drain""error""lost""host_lost"
groupId?string

The group it was created in, if any.

metadata?
ephemeral?boolean

True when this sandbox leaves no customer history after it ends.

result?
Example Request
curl -X POST 'https://api.openrelay.inc/v1/sandboxes' \  -H 'Content-Type: application/json' \  -d '{  "template": "python",  "run": {    "cmd": "python -c '\''print(6*7)'\''"  }}'
Example Response
{  "id": "string",  "template": "string",  "state": "running",  "createdAt": "2019-08-24T14:15:22Z",  "expiresAt": "2019-08-24T14:15:22Z",  "endedAt": "2019-08-24T14:15:22Z",  "exitReason": "killed",  "groupId": "string",  "metadata": {    "property1": "string",    "property2": "string"  },  "ephemeral": true,  "result": {    "execId": "string",    "exitCode": 0,    "stdout": "string",    "stderr": "string",    "truncated": true,    "error": {      "error": "string",      "code": "string",      "permission": "string",      "deniedBy": "string",      "policies": [        "string"      ],      "requestId": "string"    }  }}