> ## Documentation Index
> Fetch the complete documentation index at: https://porter-mintlify-f913b760.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Python Sandbox SDK reference

> Core classes and methods in the porter-sandbox Python Sandbox SDK

Import the top-level client from `porter_sandbox`:

```python theme={null}
from porter_sandbox import Porter, AsyncPorter
```

## `Porter`

`Porter` is the top-level sync client. It exposes resource namespaces for sandboxes, volumes, health, and readiness.

```python theme={null}
from porter_sandbox import Porter

with Porter() as porter:
    sandbox = porter.sandboxes.create(
        image="python:3.12-slim",
        name="my-sandbox",
    )
```

Constructor options:

| Option     | Type            | Description                                                                                                                                                                                                                |
| ---------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `api_key`  | `str \| None`   | Optional API key. Only required when invoking the Sandbox API from outside the sandbox-enabled cluster. Create one from **Settings > API tokens** in the Porter Dashboard. Creating API tokens requires admin permissions. |
| `base_url` | `str \| None`   | Optional API base URL override. In-cluster Porter Applications use the in-cluster Sandbox API URL by default.                                                                                                              |
| `timeout`  | `float \| None` | Request timeout in seconds. Defaults to 30 seconds.                                                                                                                                                                        |

## `porter.sandboxes`

### `create`

```python theme={null}
sandbox = porter.sandboxes.create(
    image="python:3.12-slim",
    name="my-sandbox",
    command=None,
    args=None,
    env=None,
    tags={"workflow": "demo"},
    volume_mounts=None,
)
```

Arguments:

| Argument        | Type                     | Description                                                                                                                                                                         |
| --------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `image`         | `str`                    | Container image to run.                                                                                                                                                             |
| `name`          | `str \| None`            | Optional cluster-unique sandbox name. Use lowercase letters, numbers, and hyphens; start and end with a letter or number. Names currently cannot be reused, even after termination. |
| `command`       | `list[str] \| None`      | Optional entrypoint override.                                                                                                                                                       |
| `args`          | `list[str] \| None`      | Optional arguments passed to the command.                                                                                                                                           |
| `env`           | `dict[str, str] \| None` | Environment variables to set in the sandbox.                                                                                                                                        |
| `tags`          | `dict[str, str] \| None` | Key-value labels for finding related sandboxes.                                                                                                                                     |
| `volume_mounts` | `dict[str, str] \| None` | Volume IDs keyed by absolute mount path inside the sandbox.                                                                                                                         |

Returns a `Sandbox` handle.

### `get`

```python theme={null}
sandbox = porter.sandboxes.get("my-sandbox")
```

Looks up a sandbox by name and returns a `Sandbox` handle. Use names as the canonical reference for sandboxes you need to operate on later.

### `list`

```python theme={null}
sandboxes = porter.sandboxes.list(tags={"workflow": "demo"}, page=1)
```

Lists sandboxes, optionally filtered by tags and page.

## `Sandbox`

`Sandbox` is the handle returned by `porter.sandboxes`.

Properties:

| Property | Type                          | Description                 |
| -------- | ----------------------------- | --------------------------- |
| `id`     | `str`                         | Sandbox identifier.         |
| `phase`  | `StatusResponsePhase \| None` | Last-known lifecycle phase. |
| `tags`   | `dict[str, str] \| None`      | Last-known tags.            |

Methods:

```python theme={null}
status = sandbox.refresh()
result = sandbox.exec(["python", "-c", "print('hi')"])
logs = sandbox.logs(limit=100)
sandbox.terminate()
```

| Method                         | Description                                                              |
| ------------------------------ | ------------------------------------------------------------------------ |
| `refresh()`                    | Refetches status and updates `phase` and `tags`.                         |
| `exec(command)`                | Runs a command in the sandbox and returns stdout, stderr, and exit code. |
| `logs(since=None, limit=None)` | Fetches structured log lines.                                            |
| `terminate()`                  | Terminates the sandbox.                                                  |

## Volumes

Volumes are persistent storage that can be mounted into sandboxes.

```python theme={null}
volume = porter.volumes.create(name="my-data")

sandbox = porter.sandboxes.create(
    image="python:3.12-slim",
    volume_mounts={"/mnt/data": volume.id},
)
```

Sandbox and volume names may contain lowercase letters, numbers, and hyphens, and must start and end with a letter or number. Sandbox names currently cannot be reused, even after termination. Volume names must be unique for the lifetime of the volume and can be reused after deletion.

Volume methods:

| Method                             | Description                                                      |
| ---------------------------------- | ---------------------------------------------------------------- |
| `porter.volumes.list()`            | Lists volumes.                                                   |
| `porter.volumes.create(name=None)` | Creates a volume. Pass a name when you need stable lookup later. |
| `porter.volumes.get(name)`         | Fetches a volume by name.                                        |
| `porter.volumes.delete(name)`      | Deletes a volume by name.                                        |

## Async client

`AsyncPorter` mirrors `Porter` with awaitable methods:

```python theme={null}
from porter_sandbox import AsyncPorter

async with AsyncPorter() as porter:
    sandbox = await porter.sandboxes.create(
        image="python:3.12-slim",
        name="async-sandbox",
    )
    result = await sandbox.exec(["python", "-c", "print('hi')"])
    await sandbox.terminate()
```

## Low-level client

The top-level client exposes generated low-level clients through `.raw`:

```python theme={null}
raw_client = porter.raw
raw_sandboxes = porter.sandboxes.raw
```

Use these only when you need an endpoint that is not wrapped by the ergonomic SDK surface yet.

## Next steps

* [Python Sandbox SDK volumes](/sandbox/sdk/python/volumes)
* [Python Sandbox SDK errors](/sandbox/sdk/python/errors)
