# Create a sandbox

Create a sandbox and request its first start.

POST `/v1/customer/tenants/{tenantId}/sandboxes`

Base URL: `https://api.runzivo.dev`

## Authentication

Send `Authorization: Bearer <token>` with a customer access token or workspace API key.

API key permission: `sandboxes:write`. These are permissions, not legacy scopes. A key with the `all:all` scope also works, limited by its creator's current workspace permissions.

## Parameters

| Field | Description |
| --- | --- |
| `tenantId` string · path Required | Your workspace's tenant ID. Replace the placeholder with an ID your token can access. |

## Request body

Send `Content-Type: application/json`.

| Field | Description |
| --- | --- |
| `name` string Required | 1–80 characters after trimming. A live sandbox name must be unique in the workspace. |
| `size` string Required | 2vcpu-8gb, 4vcpu-16gb, 8vcpu-32gb or 16vcpu-64gb. Choose a size from the list response's sizes field. |
| `disk_gib` integer Optional | 5–64 GiB; default 20. |
| `client_operation_id` string Optional | 8–200 characters. Reusing this value returns the sandbox first created for it. |

## Behavior and limits

- Send application/json. Request body limit: 4 KiB. Unknown JSON fields are rejected.
- A successful request returns 201 and a bare Sandbox object. Poll its status; a response is not proof that the VM is ready.
- Conflicts include sandbox_limit_reached, credit_exhausted, sandbox_name_taken, size_unavailable and workspace_blocked. The eight-hour lifetime runs from the first start, not from the browser or CLI opening.

## Responses

| Status | Meaning |
| --- | --- |
| 201 Created | application/json |
| 400 Invalid request | Malformed JSON, unknown fields or invalid values. Terminal upgrades also reject malformed handshakes. |
| 401 Unauthorized | Missing or invalid bearer token. A ticketed terminal request can instead return ticket_invalid. |
| 403 Forbidden | The caller lacks workspace membership or permission, or the API key is not allowed. Codes include tenant_membership_required, permission_required and api_key_scope_required. |
| 409 Conflict | Creation was refused by the workspace limit, credit, name, size or workspace controls. Codes include sandbox_limit_reached, credit_exhausted, sandbox_name_taken, size_unavailable and workspace_blocked. |
| 500 Internal error | The server could not complete the request. |
| 503 Unavailable | Sandbox service is unavailable. Exec and terminal operations can also return sandbox_exec_unavailable. |

Examples use synthetic IDs, dates and values. Read the actual response and status in your workspace.

## Sandbox response fields

Success returns a Sandbox object directly, with these fields.

| Field | Description |
| --- | --- |
| `id` string Required | Sandbox ID: sbx\_ followed by 24 lowercase hexadecimal characters. |
| `name` string Required | Workspace sandbox name. |
| `size` string Required | The selected size identifier. |
| `disk_gib` integer Required | Workspace disk size in GiB. |
| `status` string Required | pending, starting, running, stopping, stopped, deleting, deleted, expired or failed. |
| `error` object \| null Required | null, or {code, message} explaining a failed sandbox. |
| `created_at` date-time Required | When the sandbox was created. |
| `started_at` date-time \| null Required | First start; null until it starts. |
| `expires_at` date-time \| null Required | First start plus eight hours. Stopping does not pause the lifetime. |
| `remaining_seconds` integer Required | Lifetime left; 28800 before first start, 0 once expired or deleted. |
| `runtime_seconds` integer Required | Seconds the VM has been up; excludes stopped time. |
| `credits_used` number Required | Unit-minutes charged at the size's multiplier. |

[Sandbox limits and billing](https://runzivo.dev/docs/sandboxes-limits/)

Page tools

[View as Markdown](https://runzivo.dev/docs/reference/sandboxes/create.md)

Ask AI about this page

[Open in ChatGPT](https://chatgpt.com/?q=Read%20this%20Runzivo%20documentation%20page%2C%20then%20help%20me%20with%20it%3A%0A%0Ahttps%3A%2F%2Frunzivo.dev%2Fdocs%2Freference%2Fsandboxes%2Fcreate.md) [Open in Claude](https://claude.ai/new?q=Read%20this%20Runzivo%20documentation%20page%2C%20then%20help%20me%20with%20it%3A%0A%0Ahttps%3A%2F%2Frunzivo.dev%2Fdocs%2Freference%2Fsandboxes%2Fcreate.md) [Open in Cursor](https://cursor.com/link/prompt?text=Read%20this%20Runzivo%20documentation%20page%2C%20then%20help%20me%20with%20it%3A%0A%0Ahttps%3A%2F%2Frunzivo.dev%2Fdocs%2Freference%2Fsandboxes%2Fcreate.md)

Claude shows a caution banner on any prefilled prompt. That is expected: review the prompt, then send it.

## Request example

Illustrative request. Set RUNZIVO_TOKEN and TENANT_ID in your shell. Replace placeholders with your own values. This page does not send requests.

cURL

```
curl --request POST \
  "https://api.runzivo.dev/v1/customer/tenants/${TENANT_ID}/sandboxes" \
  --header "Authorization: Bearer ${RUNZIVO_TOKEN}" \
  --header "Content-Type: application/json" \
  --data '{
  "name": "docs-example",
  "size": "2vcpu-8gb",
  "disk_gib": 20,
  "client_operation_id": "docs-create-example-01"
}'
```

## Response example

application/json · Illustrative response; values and timing vary in your workspace.

201 · application/json

```
{
  "id": "sbx_000000000000000000000001",
  "name": "docs-example",
  "size": "2vcpu-8gb",
  "disk_gib": 20,
  "status": "pending",
  "error": null,
  "created_at": "2026-10-31T12:00:00Z",
  "started_at": null,
  "expires_at": null,
  "remaining_seconds": 28800,
  "runtime_seconds": 0,
  "credits_used": 0
}
```

All response examples (also available without JavaScript)

### 201 Created

Illustrative response; values and timing vary in your workspace.

application/json

```
{
  "id": "sbx_000000000000000000000001",
  "name": "docs-example",
  "size": "2vcpu-8gb",
  "disk_gib": 20,
  "status": "pending",
  "error": null,
  "created_at": "2026-10-31T12:00:00Z",
  "started_at": null,
  "expires_at": null,
  "remaining_seconds": 28800,
  "runtime_seconds": 0,
  "credits_used": 0
}
```

### 400 Invalid request

Malformed JSON, unknown fields or invalid values. Terminal upgrades also reject malformed handshakes.

application/json

```
{
  "error": {
    "code": "invalid_request"
  }
}
```

### 401 Unauthorized

Missing or invalid bearer token. A ticketed terminal request can instead return ticket_invalid.

application/json

```
{
  "error": {
    "code": "unauthorized"
  }
}
```

### 403 Forbidden

The caller lacks workspace membership or permission, or the API key is not allowed. Codes include tenant_membership_required, permission_required and api_key_scope_required.

application/json

```
{
  "error": {
    "code": "permission_required"
  }
}
```

### 409 Conflict

Creation was refused by the workspace limit, credit, name, size or workspace controls. Codes include sandbox_limit_reached, credit_exhausted, sandbox_name_taken, size_unavailable and workspace_blocked.

application/json

```
{
  "error": {
    "code": "sandbox_limit_reached"
  }
}
```

### 500 Internal error

The server could not complete the request.

application/json

```
{
  "error": {
    "code": "internal_error"
  }
}
```

### 503 Unavailable

Sandbox service is unavailable. Exec and terminal operations can also return sandbox_exec_unavailable.

application/json

```
{
  "error": {
    "code": "sandboxes_unavailable"
  }
}
```
