# Sandboxes (/docs/sandboxes)

A sandbox is a hardware-isolated virtual machine with its own kernel, filesystem, network stack, and allocated vCPU, RAM, and disk, with isolation enforced by the hypervisor.

Sandboxes run as [Linux](#linux-sandboxes) (default), [Windows](#windows-sandboxes), [macOS](#macos-sandboxes), or [GPU](#gpu-sandboxes)-accelerated virtual machines. Every sandbox moves through a lifecycle and can have several different states. While the sandbox is running, it exposes a toolbox for code, command, and process execution, sessions, filesystem and git operations, computer use, language server protocol support, and log streaming.

Use sandboxes to run code written by an agent, build and test software, train or serve a model on a dedicated GPU, drive desktop through screenshots and input events, or spin up thousands of identical environments for autonomous, evaluation, and reinforcement learning workflows.

<SandboxesVisual />

| **Concept**     | **Description**                                                                                                                                          |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Sandbox**     | An isolated, dedicated virtual machine.                                                                                                                  |
| **Image**       | The OCI image, Dockerfile build, or snapshot the sandbox boots  from.                                                                                    |
| **Resources**   | The vCPU, memory, and disk allocated to the sandbox.                                                                                                     |
| **Lifecycle**   | The states a sandbox can be in and the transitions between them.                                                                                         |
| **Persistence** | Deleting a sandbox discards its filesystem. Persistent macOS sandboxes can stop/start, pause/resume, and fork.                                                 |
| **Toolbox**     | A set of features for code, command, and process execution, sessions, filesystem and git operations, computer use, and language server protocol support. |

## Create sandboxes [#create-sandboxes]

Daytona provides methods to create sandboxes from the dashboard or programmatically.

1. Go to [Daytona Sandboxes ↗](https://app.daytona.com/dashboard/sandboxes)
2. Click <Button>Create</Button>
3. Select <Button>[Linux sandbox](#linux-sandboxes)</Button>, <Button>[Windows sandbox](/docs/windows-sandboxes)</Button>, <Button>[GPU sandbox](/docs/gpu-sandboxes)</Button>, or <Button>[macOS sandbox](/docs/macos-sandboxes)</Button>
4. Click <Button>Create</Button>

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona

daytona = Daytona()
sandbox = daytona.v2.create()
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()
const sandbox = await daytona.v2.create()
```

</TabItem>
<TabItem label="CLI" icon="seti:shell">

```bash
daytona sandbox create
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://api.daytona.com/sandboxes' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{}'
```

</TabItem>
</Tabs>

### Linux sandboxes [#linux-sandboxes]

[Linux sandboxes](/docs/linux-sandboxes) are Firecracker microVMs that run their own Linux kernel, and they are the default sandbox type. A Linux sandbox boots from an image that you import from a container registry, build from a Dockerfile, or capture from another sandbox. It can also start from a snapshot of another Linux sandbox. Each sandbox runs on an amd64 or arm64 CPU.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona

daytona = Daytona()
sandbox = daytona.v2.create()
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()
const sandbox = await daytona.v2.create()
```

</TabItem>
<TabItem label="CLI" icon="seti:shell">

```bash
daytona sandbox create
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://api.daytona.com/sandboxes' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{}'
```

</TabItem>
</Tabs>

### Windows sandboxes [#windows-sandboxes]

[Windows sandboxes](/docs/windows-sandboxes) are virtual machines running Windows Server 2022. A Windows sandbox starts from a prepared Windows base image, or from an image captured from another Windows sandbox. Commands run in PowerShell, and the desktop is reached over the remote desktop protocol.

### macOS sandboxes [#macos-sandboxes]

[macOS sandboxes](/docs/macos-sandboxes) are virtual machines running macOS on Apple silicon Mac computers. A macOS sandbox starts from a macOS image. A create can set the sandbox's cores, memory and disk, up to the whole Mac. By default it gets half of the Mac's cores, memory and sandbox disk, so two sandboxes can share one Mac.

### GPU sandboxes [#gpu-sandboxes]

[GPU sandboxes](/docs/gpu-sandboxes) have one or more dedicated NVIDIA or AMD GPUs attached for workloads that require GPU acceleration, model inference, training, fine-tuning, and reinforcement learning. A GPU sandbox is ephemeral and can be saved as a checkpoint that includes its processes, memory, and GPU memory, and resumed in a new GPU sandbox.

- **NVIDIA H100**
- **NVIDIA H200**
- **NVIDIA B200**
- **NVIDIA B300**
- **NVIDIA RTX Pro 6000**
- **NVIDIA RTX 4090**
- **NVIDIA RTX 5090**
- **NVIDIA L40S**
- **AMD Instinct MI355X**

## Resources [#resources]

Linux sandboxes have **0.5 cores**, **1024MiB memory**, and **512MiB disk** by default. A Linux sandbox may guarantee at most **16 cores**, **32GiB memory**, and **256GiB disk**. A macOS sandbox takes its [size](/docs/macos-sandboxes#sizes) from its Mac reservation.

CPU is measured and billed in cores, from fractions of a core up to many cores. One core is **2 vCPUs** where simultaneous multithreading (SMT, also called hyperthreading) is available and enabled, and **1 vCPU** otherwise. Each resource has a guarantee and a limit. A sandbox can always use its guarantee and takes more as its workload needs it, up to the limit, with no manual resize.

The **guarantee** is the CPU, memory, and disk that Daytona reserves for the sandbox on its host. It is billed as a minimum, whether the sandbox uses it or not. The CPU guarantee is at least **1 core** for every **8GiB** of guaranteed memory. When a create guarantees more memory than its CPU guarantee covers, Daytona raises the CPU guarantee to that floor, so a sandbox that guarantees **16GiB** memory reserves and is billed for at least **2 cores**.

| **Resource** | **Unit** | **Default guarantee** | **Minimum guarantee**             | **Maximum guarantee** |
| ------------ | -------- | --------------------- | --------------------------------- | --------------------- |
| CPU          | Cores    | `0.5`                 | **`0.125`** (when set explicitly) | **`16`**              |
| Memory       | MiB      | `1024`                | **`512`** (when set explicitly)   | **`32768`**           |
| Disk         | MiB      | `512`                 | **`10240`** (when set explicitly) | **`262144`**          |

The **limit** is the most the sandbox can use. You set it when you create the sandbox. When a create sets no limit, the limit is the platform maximum or the cap of the organization's [plan](/docs/limits#sandbox-limits), whichever is lower. A limit equal to its guarantee gives the sandbox a fixed size that does not grow.

| **Resource** | **Unit** | **Default limit**            | **Minimum limit**               | **Maximum limit** |
| ------------ | -------- | ---------------------------- | ------------------------------- | ----------------- |
| CPU          | Cores    | Platform maximum or plan cap | **`0.5`** (a multiple of `0.5`) | **`16`**          |
| Memory       | MiB      | Platform maximum or plan cap | **`256`**                       | **`32768`**       |
| Disk         | MiB      | Platform maximum             | **`512`**                       | **`262144`**      |

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona
from daytona.v2 import Resources

daytona = Daytona()
sandbox = daytona.v2.create(
    # memory and disk are GiB: 2 maps to memory_mib=2048, 20 to disk_mib=20480
    resources=Resources(cpu=1, memory=2, disk=20, cpu_max=2, memory_max=4, disk_max=40),
)
```

| **Parameter** | **Type** | **Description**                                                     |
| ------------- | -------- | ------------------------------------------------------------------- |
| `cpu`         | float    | Sets the guaranteed CPU in cores.                                   |
| `memory`      | int      | Sets the guaranteed memory in GiB.                                  |
| `disk`        | int      | Sets the guaranteed disk in GiB.                                    |
| `cpu_max`     | float    | Sets the CPU limit in cores, a multiple of `0.5`.                   |
| `memory_max`  | float    | Sets the memory limit in GiB.                                       |
| `disk_max`    | float    | Sets the disk limit in GiB.                                         |

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()
const sandbox = await daytona.v2.create({
  // memory and disk are GiB: 2 maps to memory_mib=2048, 20 to disk_mib=20480
  resources: { cpu: 1, memory: 2, disk: 20, cpuMax: 2, memoryMax: 4, diskMax: 40 },
})
```

| **Parameter** | **Type** | **Description**                                                     |
| ------------- | -------- | ------------------------------------------------------------------- |
| `cpu`         | number   | Sets the guaranteed CPU in cores.                                   |
| `memory`      | number   | Sets the guaranteed memory in GiB.                                  |
| `disk`        | number   | Sets the guaranteed disk in GiB.                                    |
| `cpuMax`      | number   | Sets the CPU limit in cores, a multiple of `0.5`.                   |
| `memoryMax`   | number   | Sets the memory limit in GiB.                                       |
| `diskMax`     | number   | Sets the disk limit in GiB.                                         |

</TabItem>
<TabItem label="CLI" icon="seti:shell">

```bash
# --memory, --disk, --memory-max, and --disk-max are MiB
daytona sandbox create --cpu 1 --memory 2048 --disk 20480 \
  --cpu-max 2 --memory-max 4096 --disk-max 40960
```

| **Flag**       | **Type** | **Description**                                                     |
| -------------- | -------- | ------------------------------------------------------------------- |
| `--cpu`        | float    | Sets the guaranteed CPU in cores.                                   |
| `--memory`     | int      | Sets the guaranteed memory in MiB.                                  |
| `--disk`       | int      | Sets the guaranteed disk in MiB.                                    |
| `--cpu-max`    | float    | Sets the CPU limit in cores, a multiple of `0.5`.                   |
| `--memory-max` | int      | Sets the memory limit in MiB.                                       |
| `--disk-max`   | int      | Sets the disk limit in MiB.                                         |

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://api.daytona.com/sandboxes' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
  "cpu": 1,
  "memory_mib": 2048,
  "disk_mib": 20480,
  "cores_max": 2,
  "memory_max_mib": 4096,
  "disk_max_mib": 40960
}'
```

| **Field**        | **Type** | **Description**                                                  |
| ---------------- | -------- | ---------------------------------------------------------------- |
| `cpu`            | number   | Sets the guaranteed CPU in cores.                                |
| `memory_mib`     | integer  | Sets the guaranteed memory in MiB.                               |
| `disk_mib`       | integer  | Sets the guaranteed disk in MiB.                                 |
| `cores_max`      | number   | Sets the CPU limit in cores, a multiple of `0.5`.                |
| `memory_max_mib` | integer  | Sets the memory limit in MiB.                                    |
| `disk_max_mib`   | integer  | Sets the disk limit in MiB.                                      |

</TabItem>
</Tabs>

## Regions [#regions]

Every sandbox runs in a [region](/docs/regions), a geographic or logical group of compute infrastructure. A create request can name a region, and Daytona places the sandbox on available capacity inside it.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona

daytona = Daytona()
sandbox = daytona.v2.create(region="earth")
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()
const sandbox = await daytona.v2.create({ region: 'earth' })
```

</TabItem>
<TabItem label="CLI" icon="seti:shell">

```bash
daytona sandbox create --region earth
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://api.daytona.com/sandboxes' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
  "region_id": "earth"
}'
```

</TabItem>
</Tabs>

## Hardware virtualization [#hardware-virtualization]

Server processors include instructions for running virtual machines directly on the hardware. A virtual machine monitor uses these instructions to create a guest with its own virtual processors, memory, and devices. The processor rejects any access from a guest to host memory or to another guest's memory. Linux, Windows, and macOS sandboxes run as virtual machines, each on the virtual machine monitor that its operating system needs.

| **Sandbox**                               | **Host**               | **Runtime**                              |
| ----------------------------------------- | ---------------------- | ---------------------------------------- |
| [**Linux**](/docs/linux-sandboxes)     | Linux with KVM         | Firecracker virtual machine              |
| [**Windows**](/docs/windows-sandboxes) | Linux with KVM         | Cloud Hypervisor virtual machine         |
| [**macOS**](/docs/macos-sandboxes)     | Mac with Apple silicon | Virtualization framework virtual machine |

**Linux** exposes the processor's virtualization through the Kernel-based Virtual Machine (KVM). Linux sandboxes run on Firecracker, a virtual machine monitor built to run many small, short-lived virtual machines on one host. Firecracker provides only the devices a server needs: virtual disks, a network card, and a serial console. Each Linux sandbox runs as one Firecracker process on a host, in its own network namespace, with its own virtual processors and memory.

**Windows** sandboxes also use KVM, but Firecracker does not support Windows guests. Windows sandboxes run on **Cloud Hypervisor**, a virtual machine monitor that also keeps its device model small but can start an operating system from firmware. Each Windows sandbox runs as one Cloud Hypervisor process on a host, in its own network namespace, with its own virtual processors and memory.

Cloud Hypervisor provides each Windows sandbox with the following:

- UEFI firmware, which loads the Windows boot manager from the sandbox's disk
- Hyper-V enlightenments: interfaces Windows uses to run efficiently as a guest
- Virtual disks and a virtual network card, for which the base image carries Windows drivers
- A serial console for management, and no graphics card

**macOS sandboxes** run on Macs, because Apple's license allows macOS virtual machines only on Apple hardware. Apple silicon includes hardware support for virtual machines, which macOS exposes through Apple's Virtualization framework. Each macOS sandbox runs as its own virtual machine on its Mac, with its own virtual processors, memory, disk, and network card.

## Sandbox lifecycle [#sandbox-lifecycle]

Every sandbox moves through a lifecycle. A sandbox can have several different states. Each state reflects the status of your sandbox. A sandbox transitions between states in response to user actions, or automatically when one of its timeouts elapses.

See the lifecycle of [Linux](/docs/linux-sandboxes#lifecycle), [Windows](/docs/windows-sandboxes), [GPU](/docs/gpu-sandboxes), and [macOS](/docs/macos-sandboxes#lifecycle) sandboxes.

<SandboxDiagram />

| **Feature**                | **Linux**       | **Windows**      | **macOS**        | **GPU**      |
| -------------------------- | --------------- | ---------------- | ---------------- | ------------ |
| **Stop and start**         | ✗               | ✓ persistent     | ✓ persistent     | ✗            |
| **Pause and resume**       | ✗               | ✗                | ✓ persistent     | ✗            |
| **Fork**                   | ✗               | ✗                | ✓ persistent     | ✗            |
| **Delete**                 | ✓               | ✓                | ✓                | ✓            |
| **Filesystem persistence** | ✗               | ✓                | ✓                | ✗            |
| **Memory persistence**     | ✗               | ✗                | ✓ persistent     | ✗            |
| **Memory snapshot**        | ✓ warm template | ✗                | ✗                | ✓ checkpoint |
| **Filesystem snapshot**    | ✓               | ✓ block snapshot | ✓ persistent     | ✗            |
| **Spot (Preemption)**      | ✓               | ✓                | ✗                | ✗            |
| **Network policy**         | ✓               | ✗                | ✓                | ✗            |
| **Desktop**                | ✓               | ✓ RDP            | ✓ Screen Sharing | ✗            |

The following tables list the states of a Linux sandbox and the transitions between them. The SDKs report the states in the **State** column. The CLI and API report the more detailed status in the **API status** column.

<Collapsible title="Sandbox states">

| **State**        | **API status**                 | **Description**                                                                 |
| ---------------- | ------------------------------ | ------------------------------------------------------------------------------- |
| **`queued`**     | **`queued`**                   | The create request is recorded and waits to be published for placement.         |
| **`creating`**   | **`pending`**, **`assigned`**  | The create request is accepted, and the sandbox is queued for and placed on a host. |
| **`starting`**   | **`booting`**                  | The microVM is booting and will be ready to use.                                |
| **`started`**    | **`running`**                  | The sandbox is running and ready to accept requests.                            |
| **`destroying`** | **`deleting`**                 | The sandbox is being deleted.                                                   |
| **`destroyed`**  | **`deleted`**                  | The sandbox and its storage are removed.                                        |
| **`error`**      | **`failed`**, **`lost`**       | The sandbox could not boot, hit an unrecoverable error, or its host was lost.   |
| **`unknown`**    |                                | The SDK does not recognize the status the API reports.                          |

</Collapsible>

A sandbox can transition between states in response to various actions. The following table lists the initial state, target state, and trigger for the transition.

<Collapsible title="State transitions">

| **Initial state** | **Target state** | **Trigger**                                                                        |
| ----------------- | ---------------- | ---------------------------------------------------------------------------------- |
| **`queued`**      | **`creating`**   | The create request is published for placement.                                     |
| **`creating`**    | **`starting`**   | The sandbox is placed on a host, the host prepares its image, and the microVM boots. |
| **`starting`**    | **`started`**    | The sandbox finishes booting and accepts requests.                                 |
| any state         | **`destroying`** | A delete is requested, a timeout elapses, or the platform reclaims a spot sandbox. |
| **`destroying`**  | **`destroyed`**  | The sandbox is removed and its resources are released.                             |
| any active state  | **`error`**      | The sandbox fails to boot, hits an unrecoverable error, or its host is lost.       |

</Collapsible>

## Sandbox operations [#sandbox-operations]

Daytona provides methods to manage existing sandboxes. Sandbox operations find sandboxes, read their current state and configuration, and update their metadata. They do not change the state of a sandbox or touch anything running inside it. To stop, pause, fork, or delete a sandbox, see [lifecycle](#sandbox-lifecycle). To run commands or work with files inside a sandbox, use the toolbox.

### List sandboxes [#list-sandboxes]

List sandboxes in the project, page by page. Unfiltered lists read the region-local database, so new sandboxes appear at once. To filter by name, state, labels, or resources, use [search](#search-sandboxes).

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona

daytona = Daytona()
page = daytona.v2.list()
for sandbox in page.items:
    print(sandbox.id, sandbox.name, sandbox.state)
```

<Callout type="note" title="Notes">
- The request requires the `read:sandboxes` permission.
- `page.next_cursor` is `None` on the last page.
- Pass `next_cursor` back as `cursor` for the next page.
</Callout>

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()
const page = await daytona.v2.list()
for (const sandbox of page.items) {
  console.log(sandbox.id, sandbox.name, sandbox.state)
}
```

<Callout type="note" title="Notes">
- The request requires the `read:sandboxes` permission.
- `page.nextCursor` is unset on the last page.
- Pass `nextCursor` back as `cursor` for the next page.
</Callout>

</TabItem>
<TabItem label="CLI" icon="seti:shell">

```bash
daytona sandbox list
```

| **Flag**   | **Type** | **Description**                     |
| ---------- | -------- | ----------------------------------- |
| `--limit` | int | Sets the page size. The default is `100`. |
| `--cursor` | string | Continues from a previous page.     |

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://api.daytona.com/sandboxes' \
  --header 'Authorization: Bearer YOUR_API_KEY'
```

| **Field** | **Type** | **Description**                                                                                                                                      |
| --------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `limit`   | integer | Sets the page size, from `1` to `200`. The default is `100`. |

<Callout type="note" title="Notes">
- The request requires the `read:sandboxes` permission.
- Pass `next_cursor` from the response as `cursor` to read the next page.
</Callout>

</TabItem>
</Tabs>

##### Iterate over all sandboxes [#iterate-over-all-sandboxes]

Iterate over every sandbox in the project without handling page cursors. The iterator fetches the next page when the current one is exhausted and stops when the server returns no cursor.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona

daytona = Daytona()
for sandbox in daytona.v2.iter():
    print(sandbox.id, sandbox.name, sandbox.state)
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()
for await (const sandbox of daytona.v2.iter()) {
  console.log(sandbox.id, sandbox.name, sandbox.state)
}
```

</TabItem>
<TabItem label="CLI" icon="seti:shell">

```bash
# Follow every page until the server returns no cursor
daytona sandbox list --all
```

</TabItem>
</Tabs>

### Search sandboxes [#search-sandboxes]

Search sandboxes across every region. Search reads a central index that is eventually consistent: a create, update, or delete becomes searchable about 2 to 3 seconds after it is committed, so a sandbox created a moment ago may be missing. To read your own writes, use [list](#list-sandboxes) without filters or [get](#get-a-sandbox). Filters combine with AND, and deleted sandboxes are left out of the results.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona

daytona = Daytona()

# Free text over name and image, or an exact sandbox id
page = daytona.v2.search(q="my-sandbox")
for sandbox in page.items:
    print(sandbox.id, sandbox.name, sandbox.state)
```

| **Parameter** | **Type**        | **Description**                                                                         |
| ------------- | --------------- | --------------------------------------------------------------------------------------- |
| `status`      | Sequence\[str\] | Filters by state. Pass API state names such as `running`, not the SDK names returned in `sandbox.state`. |

The response has the following fields:

| **Field**         | **Description**                                                                          |
| ----------------- | ---------------------------------------------------------------------------------------- |
| `next_cursor`     | The cursor is tied to the filters and sort of its call.                                  |
| `partial_regions` | Lists the regions that are backfilling. Results from these regions can be incomplete.    |

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()

// Free text over name and image, or an exact sandbox id
const page = await daytona.v2.search({ q: 'my-sandbox' })
for (const sandbox of page.items) {
  console.log(sandbox.id, sandbox.name, sandbox.state)
}
```

| **Parameter** | **Type**                       | **Description**                                                                   |
| ------------- | ------------------------------ | --------------------------------------------------------------------------------- |
| `status`      | string \| readonly string\[\] | Filters by state. Pass API state names such as `running`, not the SDK names returned in `sandbox.state`. |

The response has the following fields:

| **Field**        | **Description**                                                                          |
| ---------------- | ---------------------------------------------------------------------------------------- |
| `nextCursor`     | The cursor is tied to the filters and sort of its call.                                  |
| `partialRegions` | Lists the regions that are backfilling. Results from these regions can be incomplete.    |

</TabItem>
<TabItem label="CLI" icon="seti:shell">

```bash
# Free text over name and image, or an exact sandbox id
daytona sandbox search my-sandbox
```

| **Flag**   | **Type** | **Description**                                            |
| ---------- | -------- | ---------------------------------------------------------- |
| `--status` | string | Repeatable or comma-separated. Matches any listed value. |
| `--class`  | string | Repeatable or comma-separated. Matches any listed value. |

<Callout type="note" title="Notes">
- The request requires the `read:sandboxes` permission.
- The query is optional.
- Filter flags such as `--status`, `--class`, `--name-prefix`, and `--labels` select sandboxes on their own or narrow the query.
</Callout>

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
# Free text over name and image, or an exact sandbox id
curl 'https://api.daytona.com/sandboxes/search?q=my-sandbox' \
  --header 'Authorization: Bearer YOUR_API_KEY'
```

| **Field** | **Type**  | **Description**                       |
| --------- | --------- | ------------------------------------- |
| `limit` | integer | Sets the page size, from `1` to `200`. The default is `100`. |
| `sort` | string | Sets the sort field. The default is `created_at`. |
| `order` | string | Sets the sort order. The default is `desc`. |

<Callout type="note" title="Notes">
- The request requires the `read:sandboxes` permission.
- A `cursor` is tied to the filters and sort of its request.
</Callout>

</TabItem>
</Tabs>

### Get a sandbox [#get-a-sandbox]

Get a sandbox by its ID. The response includes the current state, resources, labels, and lifecycle settings. Get reads the control plane directly, so it reflects changes immediately, unlike [search](#search-sandboxes).

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona

daytona = Daytona()

# Fetch the sandbox from the control plane
sandbox = daytona.v2.get("{sandboxId}")
print(sandbox.state, sandbox.cpu, sandbox.memory, sandbox.disk)

# Store the sandbox data as JSON; it carries no URL or credential
saved = sandbox.to_json()  # {"sandboxId": "...", "name": "...", "state": "...", ...}

# Later, get the sandbox again by its ID
sandbox = daytona.v2.get(saved["sandboxId"])
```

The response has the following fields:

| **Field** | **Description**                                                                             |
| --------- | ------------------------------------------------------------------------------------------- |
| `memory`  | Gives the memory in GiB, rounded up to a whole GiB. The API reports memory in MiB as `memory_mib`. |
| `disk`    | Gives the disk in GiB, rounded up to a whole GiB. The API reports disk in MiB as `disk_mib`. |

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()

// Fetch the sandbox from the control plane
const sandbox = await daytona.v2.get('{sandboxId}')
console.log(sandbox.state, sandbox.cpu, sandbox.memory, sandbox.disk)

// Store the sandbox data as JSON; it carries no URL or credential
const saved = sandbox.toJSON() // { sandboxId: '...', name: '...', state: '...', ... }

// Later, get the sandbox again by its ID
const again = await daytona.v2.get(saved.sandboxId)
```

The response has the following fields:

| **Field** | **Description**                                                                             |
| --------- | ------------------------------------------------------------------------------------------- |
| `memory`  | Gives the memory in GiB, rounded up to a whole GiB. The API reports memory in MiB as `memory_mib`. |
| `disk`    | Gives the disk in GiB, rounded up to a whole GiB. The API reports disk in MiB as `disk_mib`. |

</TabItem>
<TabItem label="CLI" icon="seti:shell">

```bash
daytona sandbox get {sandboxId}
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://api.daytona.com/sandboxes/{sandboxId}' \
  --header 'Authorization: Bearer YOUR_API_KEY'
```

</TabItem>
</Tabs>

##### Refresh a sandbox [#refresh-a-sandbox]

Refresh a sandbox object with its current data. A sandbox object keeps the fields from the request that returned it, so its state, resources, and labels can be out of date after a change made by another client. Refresh reads the sandbox from the control plane and updates the object in place. Lifecycle operations such as start and stop refresh the object when they finish.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
# Re-read the sandbox from the control plane
sandbox.refresh_data()
print(sandbox.state, sandbox.labels)
```

| **Parameter** | **Type**  | **Description**                                                                    |
| ------------- | --------- | ---------------------------------------------------------------------------------- |
| `timeout`     | float   | Sets the request timeout in seconds. By default, the client request timeout applies. |

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
// Re-read the sandbox from the control plane
await sandbox.refreshData()
console.log(sandbox.state, sandbox.labels)
```

</TabItem>
</Tabs>

### Find sandboxes by name [#find-sandboxes-by-name]

Find sandboxes by the name they were created with. Names are not unique, so the result is a list, newest first, and it is empty when no sandbox matches. The lookup reads the [search](#search-sandboxes) index, so a sandbox created a moment ago can be missing.

The name is stored as the name label. Replacing a sandbox's labels without it removes the sandbox from name lookups.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona

daytona = Daytona()

# Reuse a named sandbox, or create it when none exists
found = daytona.v2.find_by_name("my-sandbox")
sandbox = found[0] if found else daytona.v2.create(name="my-sandbox")
```

| **Parameter** | **Type** | **Description**                                                                                     |
| ------------- | -------- | --------------------------------------------------------------------------------------------------- |
| `name`        | str    | Matches the sandbox name exactly. This parameter is required. A blank name raises `BadRequestError` before the request is sent.            |
| `region` | str | Sets the region to search. `"local"` or omitting it means the region of the API host. |

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()

// Reuse a named sandbox, or create it when none exists
const found = await daytona.v2.findByName('my-sandbox')
const sandbox = found[0] ?? (await daytona.v2.create({ name: 'my-sandbox' }))
```

| **Parameter**    | **Type** | **Description**                                                                                     |
| ---------------- | -------- | --------------------------------------------------------------------------------------------------- |
| `name`           | string | Required. Exact match. A blank name throws `DaytonaError` before the request is sent.               |
| `options.region` | string | Sets the region to search. `'local'` or omitting it means the region of the API host. |

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
# Search by the name label: labels={"name":"my-sandbox"}
curl 'https://api.daytona.com/sandboxes/search?labels=%7B%22name%22%3A%22my-sandbox%22%7D' \
  --header 'Authorization: Bearer YOUR_API_KEY'
```

</TabItem>
</Tabs>

### Create an access token [#create-an-access-token]

Create a short-lived access token for one sandbox. The token reaches the sandbox toolbox, SSH, desktop, and private preview ports, and can stop, pause, or delete the sandbox, limited to the operations and ports you grant. Give it to a collaborator, a CI job, or a browser instead of a project API key.

The token lasts one hour by default and at most 24 hours. It cannot be refreshed, revoked, or used to create other credentials. Create a new token when it expires.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
# Grant file system and SSH access for 15 minutes
token = sandbox.create_access_token(operations=["toolbox:fs", "ssh"], ttl_seconds=900)
print(token.access_token, token.expires_at)
```

| **Parameter** | **Type**        | **Description**                                                                                                                                                                                       |
| ------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `operations`  | Sequence\[str\] | Lists the operations the token grants. Each operation is one of `toolbox`, `toolbox:exec`, `toolbox:fs`, `toolbox:git`, `toolbox:lsp`, `desktop`, `ssh`, `sandbox:stop`, `sandbox:pause`, or `sandbox:delete`. `[]` grants preview ports only. The default is every operation the API key can grant. Granting `sandbox:delete` requires the `delete:sandboxes` permission. |
| `ports` | Sequence\[int\] | Sets the private preview ports that the token can reach. `[]` grants none. The default is all ports. |
| `ttl_seconds` | int | Sets the token lifetime in seconds, at most `86400`. The default is `3600`. |

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
// Grant file system and SSH access for 15 minutes
const token = await sandbox.createAccessToken({ operations: ['toolbox:fs', 'ssh'], ttlSeconds: 900 })
console.log(token.accessToken, token.expiresAt)
```

| **Parameter** | **Type**   | **Description**                                                                                                                                                                                       |
| ------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `operations`  | string\[\] | Lists the operations the token grants. Each operation is one of `toolbox`, `toolbox:exec`, `toolbox:fs`, `toolbox:git`, `toolbox:lsp`, `desktop`, `ssh`, `sandbox:stop`, `sandbox:pause`, or `sandbox:delete`. `[]` grants preview ports only. The default is every operation the API key can grant. Granting `sandbox:delete` requires the `delete:sandboxes` permission. |
| `ports` | number\[\] | Sets the private preview ports that the token can reach. `[]` grants none. The default is all ports. |
| `ttlSeconds` | number | Sets the token lifetime in seconds, at most `86400`. The default is `3600`. |

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
# Grant file system and SSH access for 15 minutes
curl 'https://api.daytona.com/sandboxes/{sandboxId}/access-token' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{"operations": ["toolbox:fs", "ssh"], "ttl_seconds": 900}'
```

| **Field**    | **Type**    | **Description**                                                                                                                                                                                       |
| ------------ | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `operations` | string\[\] | Sets the operations that the token grants: any of `toolbox`, `toolbox:exec`, `toolbox:fs`, `toolbox:git`, `toolbox:lsp`, `desktop`, `ssh`, `sandbox:stop`, `sandbox:pause`, and `sandbox:delete`. `[]` grants preview ports only. The default is every operation that the API key can grant. |
| `ports` | integer\[\] | Sets the private preview ports that the token can reach, from `1` to `65535`, at most 128. `[]` grants none. The default is all ports. |
| `ttl_seconds` | integer | Sets the token lifetime in seconds, at most `86400`. The default is `3600`. |

The response has the following fields:

| **Field**      | **Description**                                                                                  |
| -------------- | ------------------------------------------------------------------------------------------------ |
| `access_token` | The access token.                                                                          |
| `token_type`   | The token type is `Bearer`.                                                                      |
| `expires_at`   | The time when the token expires.                                                           |
| `operations`   | The operations that the token grants.                                                           |
| `ports`        | Lists the private preview ports the token can reach. The value is `null` when every port is granted. |

</TabItem>
</Tabs>

### Label sandboxes [#label-sandboxes]

Update a sandbox's labels. Labels are key-value strings for organizing sandboxes, and you can filter by them when you [list](#list-sandboxes) or [search](#search-sandboxes). An update replaces the full label set; omitted labels are removed. A sandbox holds at most 100 labels, each key and value at most 512 bytes.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona

daytona = Daytona()
sandbox = daytona.v2.create()

# Replace the full label set
labels = sandbox.set_labels({"team": "research"})
print(labels)
```

| **Parameter** | **Type**         | **Description**                                         |
| ------------- | ---------------- | ------------------------------------------------------- |
| `labels`      | Mapping\[str, str\] | Replaces the full label set. `{}` removes all labels. This parameter is required and positional only.  |

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'

const daytona = new Daytona()
const sandbox = await daytona.v2.create()

// Replace the full label set
const labels = await sandbox.setLabels({ team: 'research' })
console.log(labels)
```

| **Parameter** | **Type**                 | **Description**                      |
| ------------- | ------------------------ | ------------------------------------ |
| `labels`      | Record\<string, string> | Replaces the full label set. `{}` removes all labels. This parameter is required.   |

</TabItem>
<TabItem label="CLI" icon="seti:shell">

```bash
# Replace the full label set
daytona sandbox update {sandboxId} --label team=research
```

| **Flag**         | **Type** | **Description**                              |
| ---------------- | -------- | -------------------------------------------- |
| `--label`        | string | Repeatable, one `key=value` pair per flag.   |
| `--clear-labels` | bool   | Removes all labels.                          |

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
# Replace the full label set
curl 'https://api.daytona.com/sandboxes/{sandboxId}/labels' \
  --request PUT \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{ "labels": { "team": "research" } }'
```

| **Field** | **Type** | **Description**             |
| --------- | -------- | --------------------------- |
| `labels`  | object | Replaces the full label set. `{}` removes all labels. A sandbox holds at most 100 labels. Each key and value is at most 512 bytes. |

</TabItem>
</Tabs>

### Metrics [#metrics]

Read the current CPU, memory, and disk usage of a running sandbox. The toolbox measures each value inside the sandbox and returns one snapshot per request. Memory in use excludes memory the operating system can reclaim on demand, such as the file cache. Disk usage is measured on the filesystem that holds the sandbox working directory.

CPU utilization is the share of total CPU capacity in use across all CPUs since the previous metrics request to the sandbox, from any client. The first request after the toolbox starts measures over about 100 milliseconds.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
metrics = sandbox.metrics()
print(metrics.cpu_utilization, metrics.memory_usage_bytes, metrics.disk_usage_bytes)
```

The response has the following fields:

| **Field**            | **Description**                                                          |
| -------------------- | ------------------------------------------------------------------------ |
| `timestamp`          | The time of the snapshot, as an RFC 3339 UTC timestamp.                  |
| `cpu_count`          | The number of logical CPUs visible inside the sandbox.                   |
| `cpu_utilization`    | The fraction of total CPU capacity in use, from `0` to `1`.              |
| `memory_usage_bytes` | The memory in use, in bytes.                                             |
| `memory_total_bytes` | The total memory, in bytes.                                              |
| `disk_usage_bytes`   | The used space on the working directory filesystem, in bytes.            |
| `disk_total_bytes`   | The total space on the working directory filesystem, in bytes.           |

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
const metrics = await sandbox.metrics()
console.log(metrics.cpuUtilization, metrics.memoryUsageBytes, metrics.diskUsageBytes)
```

The response has the following fields:

| **Field**          | **Description**                                                          |
| ------------------ | ------------------------------------------------------------------------ |
| `timestamp`        | The time of the snapshot, as an RFC 3339 UTC timestamp.                  |
| `cpuCount`         | The number of logical CPUs visible inside the sandbox.                   |
| `cpuUtilization`   | The fraction of total CPU capacity in use, from `0` to `1`.              |
| `memoryUsageBytes` | The memory in use, in bytes.                                             |
| `memoryTotalBytes` | The total memory, in bytes.                                              |
| `diskUsageBytes`   | The used space on the working directory filesystem, in bytes.            |
| `diskTotalBytes`   | The total space on the working directory filesystem, in bytes.           |

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl '{toolboxProxyUrl}/{sandboxId}/system/metrics' \
  --header 'Authorization: Bearer YOUR_API_KEY'
```

The response has the following fields:

| **Field**          | **Description**                                                          |
| ------------------ | ------------------------------------------------------------------------ |
| `timestamp`        | The time of the snapshot, as an RFC 3339 UTC timestamp.                  |
| `cpuCount`         | The number of logical CPUs visible inside the sandbox.                   |
| `cpuUtilization`   | The fraction of total CPU capacity in use, from `0` to `1`.              |
| `memoryUsageBytes` | The memory in use, in bytes.                                             |
| `memoryTotalBytes` | The total memory, in bytes.                                              |
| `diskUsageBytes`   | The used space on the working directory filesystem, in bytes.            |
| `diskTotalBytes`   | The total space on the working directory filesystem, in bytes.           |

<Callout type="note" title="Notes">
- The request requires the `write:sandboxes` permission.
- `{toolboxProxyUrl}` is the `toolbox_proxy_url` field of the [sandbox](/docs/sandboxes#get-a-sandbox).
</Callout>

</TabItem>
</Tabs>

### Logs [#logs]

Read the serial console log of a sandbox. For a running sandbox the log is read live from its runner; for a sandbox in any other state the persisted log is returned.

<Tabs syncKey="language">
<TabItem label="CLI" icon="seti:shell">

```bash
# Serial console log of the microVM
daytona sandbox logs {sandboxId}
```

| **Flag**       | **Type** | **Description**                                         |
| -------------- | -------- | ------------------------------------------------------- |
| `--follow`     | bool   | Polls for new log output until interrupted.             |
| `--entrypoint` | bool   | Reads the entrypoint logs instead of the serial console. |

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
# Serial console log of the microVM
curl 'https://api.daytona.com/sandboxes/{sandboxId}/console-logs' \
  --header 'Authorization: Bearer YOUR_API_KEY'
```

</TabItem>
</Tabs>

##### Entrypoint logs [#entrypoint-logs]

Read the log of the sandbox entrypoint process as text. For a running sandbox the log is read live; for a sandbox in any other state the persisted log is returned. To page through the log or follow it, read the [entrypoint process](/docs/process-execution#entrypoint-process) through the toolbox.

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
print(sandbox.entrypoint_logs())
```

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
console.log(await sandbox.entrypointLogs())
```

</TabItem>
<TabItem label="CLI" icon="seti:shell">

```bash
daytona sandbox logs {sandboxId} --entrypoint
```

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
curl 'https://api.daytona.com/sandboxes/{sandboxId}/logs' \
  --header 'Authorization: Bearer YOUR_API_KEY'
```

</TabItem>
</Tabs>

##### Build logs [#build-logs]

Read the output of the image build behind a sandbox. A sandbox has a build log when its image is built from a Dockerfile, including a build that failed before the sandbox was placed; a sandbox created from a registry image has none. When the sandbox reuses an image built earlier, the log is the output of that original build.

Following the log streams output while the build runs and ends when the build finishes. Stopping the reader does not stop the build. To read the log of an image without a sandbox, see [image build logs](/docs/images#build-logs).

<Tabs syncKey="language">
<TabItem label="Python" icon="seti:python">

```python
from daytona import Daytona
from daytona.v2 import ImageBuilder

daytona = Daytona()
sandbox = daytona.v2.create_from_build(ImageBuilder.from_dockerfile("FROM python:3.12-slim"))

# Output retained so far, as text
print(sandbox.build_logs())

# Stream output until the build finishes
result = sandbox.follow_build_logs(on_logs=lambda chunk: print(chunk, end=""))
print(result.status, result.reason)
```

| **Parameter** | **Type** | **Description**                                                     |
| ------------- | -------- | ------------------------------------------------------------------- |
| `on_logs` | Callable\[\[str\], None\] | Receives each chunk of decoded output. This parameter is required. |
| `cursor`      | str    | Resumes after the output a previous follow returned in `cursor`.    |
| `timeout` | float | Sets the follow limit in seconds. By default, there is no limit. |

The response has the following fields:

| **Field**         | **Description**                                                                         |
| ----------------- | --------------------------------------------------------------------------------------- |
| `status`          | The status of the build.                                                          |
| `reason`          | The value is `terminal`, `deadline`, `not_applicable`, or `resource_deleted`.           |
| `output_complete` | Whether the build output is complete.                                                   |
| `cursor`          | Pass this value as `cursor` to resume after this output.                                |

</TabItem>
<TabItem label="TypeScript" icon="seti:typescript">

```typescript
import { Daytona } from '@daytona/sdk'
import { ImageBuilder } from '@daytona/sdk/v2'

const daytona = new Daytona()
const sandbox = await daytona.v2.createFromBuild(ImageBuilder.fromDockerfile('FROM python:3.12-slim'))

// Output retained so far, as text
console.log(await sandbox.buildLogs())

// Stream output until the build finishes
const result = await sandbox.followBuildLogs({ onLogs: (chunk) => { process.stdout.write(chunk) } })
console.log(result.status, result.reason)
```

| **Parameter** | **Type** | **Description**                                                                                  |
| ------------- | -------- | ------------------------------------------------------------------------------------------------ |
| `onLogs`      | (chunk: string) => unknown | Receives each chunk of decoded output. This parameter is required.                             |
| `cursor`      | string | Resumes after the output a previous follow returned in `cursor`.                                 |
| `timeoutSeconds` | number | Sets the follow limit in seconds. By default, there is no limit. |

The response has the following fields:

| **Field**        | **Description**                                                                         |
| ---------------- | --------------------------------------------------------------------------------------- |
| `status`         | The status of the build.                                                          |
| `reason`         | The value is `terminal`, `deadline`, `not_applicable`, or `resource_deleted`.           |
| `outputComplete` | Whether the build output is complete.                                                   |
| `cursor`         | Pass this value as `cursor` to resume after this output.                                |

</TabItem>
<TabItem label="API" icon="seti:json">

```bash
BUILD_LOGS_URL=$(curl 'https://api.daytona.com/sandboxes/{sandboxId}/build-logs-url' \
  --header 'Authorization: Bearer YOUR_API_KEY' | jq -r '.url')

# Output retained so far, as text
curl "$BUILD_LOGS_URL?follow=false&format=text" \
  --header 'Authorization: Bearer YOUR_API_KEY'

# Stream output until the build finishes
curl --no-buffer "$BUILD_LOGS_URL?follow=true&format=sse" \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Accept: text/event-stream'
```

</TabItem>
</Tabs>

## Permissions [#permissions]

Sandboxes are scoped to a project. An API key reaches only the sandboxes of its own project. Access is governed by three permissions, which you can grant to an [organization role](/docs/organizations#roles) or an [API key](/docs/api-keys).

Setting, changing, or clearing a delete action in a lifecycle policy also requires the permission to delete sandboxes, and so does creating an access token that can delete the sandbox. Attaching secrets when creating a sandbox requires the permission to read secrets. The [audit logs](/docs/audit-logs) record sandbox creates, lifecycle changes, deletes, and access token creation.

| **Permission**         | **Grants**                                                                                                                              |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| **`read:sandboxes`**   | List, search, and get sandboxes, and read their logs, usage, and exposed ports                                                          |
| **`write:sandboxes`**  | Create, start, stop, pause, resume, fork, and label sandboxes, change their lifecycle policy, create access tokens, and use the toolbox |
| **`delete:sandboxes`** | Delete sandboxes                                                                                                                        |
