# Sandboxes SDK for Python — Usage and symbol reference


> *Render Sandboxes is in early access.*
>
> APIs, defaults, and limits might change during the early access period. Before using sandboxes in production workloads, discuss your use case with your Render contact.

## Setup

### 1. Install the SDK

From your Python project directory:

```shell
pip install render
```

*If you already have the SDK installed,* make sure you're using version `1.2` or later:

```shell
pip install --upgrade render
```

After installing, make sure to add `render>=1.2` as a dependency in your application's `requirements.txt`, `pyproject.toml`, or equivalent.

### 2. Import the client (sync or async)

The Python SDK provides separate classes for synchronous (`Render`) and asynchronous (`RenderAsync`) usage. Both clients support all methods and types defined in this reference.

**Tab: Sync client**

```python
from render import Render # highlight-line

sandboxes = Render().experimental.sandboxes # highlight-line
sandbox = sandboxes.create()

for event in sandboxes.exec(sandbox.id, "echo hello"):
    print(event)
```

The `Render` client constructor accepts the following optional parameters:

###### `Render(*, token=None, owner_id=None, region=None)`

Initializes a synchronous Render SDK client.

| Argument | Description |
| --- | --- |
| `token` | The API key to use for authentication. Defaults to the `RENDER_API_KEY` environment variable. |
| `owner_id` | The default workspace ID for sandbox operations. Defaults to the `RENDER_WORKSPACE_ID` environment variable. |
| `region` | *During the early access period, all sandboxes run in the Oregon region, regardless of which region you provide.* The default region for sandbox operations. Defaults to the `RENDER_REGION` environment variable. |

**Tab: Async client**

```python
import asyncio
from render import RenderAsync # highlight-line

async def main():
    sandboxes = RenderAsync().experimental.sandboxes # highlight-line
    sandbox = await sandboxes.create()

    async for event in sandboxes.exec(sandbox.id, "echo hello"):
        print(event)


asyncio.run(main())
```

The `RenderAsync` client constructor accepts the following optional parameters:

###### `RenderAsync(*, token=None, owner_id=None, region=None)`

Initializes an asynchronous Render SDK client.

| Argument | Description |
| --- | --- |
| `token` | The API key to use for authentication. Defaults to the `RENDER_API_KEY` environment variable. |
| `owner_id` | The default workspace ID for sandbox operations. Defaults to the `RENDER_WORKSPACE_ID` environment variable. |
| `region` | *During the early access period, all sandboxes run in the Oregon region, regardless of which region you provide.* The default region for sandbox operations. Defaults to the `RENDER_REGION` environment variable. |

## Sandbox lifecycle

###### `create(*, owner_id=None, plan=None, timeout_seconds=None, network_policy=None, region=None, env=None, snapshot_id=None, snapshot_name=None) -> Sandbox`

Provisions a sandbox and returns immediately, usually with a status of `creating`. Pass either `snapshot_id` or `snapshot_name` to restore from an available snapshot. Wait for the sandbox to reach `running` before your first `exec`.

*On success:* Returns a [`Sandbox`](#sandbox) representing the initial state of the new sandbox.

*Raises:* [`SnapshotNotFoundError`](#snapshotnotfounderror), [`SnapshotNotReadyError`](#snapshotnotreadyerror), [`SnapshotPlanMismatchError`](#snapshotplanmismatcherror), [`RateLimitError`](#ratelimiterror), [`ClientError`](#clienterror), [`ServerError`](#servererror), `ValueError`

| Argument | Description |
| --- | --- |
| `owner_id` | The ID of the workspace that owns the sandbox. Defaults to the client configuration. If this value is not set here, it _must_ be set in the [client configuration](#2-import-the-client-sync-or-async). Otherwise, this method raises `RenderError`. |
| `plan` | *During the early access period, this parameter has no effect.* All sandbox instances have 2 CPU and 4 GB RAM. The compute plan to use for the sandbox. |
| `timeout_seconds` | The maximum sandbox lifetime, in seconds. The sandbox terminates when this time elapses. |
| `network_policy` | The default policy for the sandbox's outbound network traffic. |
| `region` | *During the early access period, all sandboxes run in the Oregon region, regardless of which region you provide.* The Render region to create the sandbox in. Defaults to the client configuration, then the workspace default. |
| `env` | A dictionary of environment variables to inject into the sandbox at creation. |
| `snapshot_id` | The ID of an available snapshot to restore from. If you provide this value, do not provide `snapshot_name`. |
| `snapshot_name` | The name of an available snapshot to restore from (case-sensitive). Resolves to the most recently available snapshot with that name in the sandbox group. If you provide this value, do not provide `snapshot_id`. |

###### `from_id(sandbox_id, *, owner_id=None) -> Sandbox`

Fetches the current state of a sandbox. Use this method to poll for readiness. Raises `SandboxNotFoundError` if the sandbox does not exist or has been terminated.

*On success:* Returns the current [`Sandbox`](#sandbox) state.

*Raises:* [`SandboxNotFoundError`](#sandboxnotfounderror), [`RateLimitError`](#ratelimiterror), [`ClientError`](#clienterror), [`ServerError`](#servererror)

| Argument | Description |
| --- | --- |
| `sandbox_id` | *Required.* The ID of the sandbox to retrieve. |
| `owner_id` | The ID of the workspace that owns the sandbox. Defaults to the client configuration. If this value is not set here, it _must_ be set in the [client configuration](#2-import-the-client-sync-or-async). Otherwise, this method raises `RenderError`. |

###### `list(*, owner_id=None, status=None, cursor=None, limit=None) -> SandboxList`

Returns up to 100 sandboxes per page, newest first. Use `status` to filter by one or more values and `cursor` to fetch the next page. Terminated sandboxes are excluded by default; include `terminated` in the `status` filter to retrieve them.

*On success:* Returns a [`SandboxList`](#sandboxlist) page.

*Raises:* [`RateLimitError`](#ratelimiterror), [`ClientError`](#clienterror), [`ServerError`](#servererror)

| Argument | Description |
| --- | --- |
| `owner_id` | The ID of the workspace whose sandboxes to list. Defaults to the client configuration. If this value is not set here, it _must_ be set in the [client configuration](#2-import-the-client-sync-or-async). Otherwise, this method raises `RenderError`. |
| `status` | One status or a sequence of statuses to filter results by. |
| `cursor` | A cursor from a previous response. Use this to retrieve the next page of results. |
| `limit` | The maximum number of sandboxes to return. The API caps this value at 100. |

###### `list_groups(*, owner_id=None) -> SandboxGroupList`

Lists the workspace's sandbox groups and returns `SandboxGroupList(groups, next_cursor)`. During the early access period, the result contains zero or one group. Use a group's ID for snapshot lookup, listing, and deletion.

*On success:* Returns a [`SandboxGroupList`](#sandboxgrouplist) page.

*Raises:* [`RateLimitError`](#ratelimiterror), [`ClientError`](#clienterror), [`ServerError`](#servererror)

| Argument | Description |
| --- | --- |
| `owner_id` | The ID of the workspace whose sandbox groups to list. Defaults to the client configuration. If this value is not set here, it _must_ be set in the [client configuration](#2-import-the-client-sync-or-async). Otherwise, this method raises `RenderError`. |

###### `terminate(sandbox_id, *, owner_id=None) -> None`

Stops the sandbox and releases its slot against your concurrency cap. This operation is idempotent: terminating an already-terminated sandbox succeeds.

*On success:* Returns `None`.

*Raises:* [`SandboxNotFoundError`](#sandboxnotfounderror), [`RateLimitError`](#ratelimiterror), [`ClientError`](#clienterror), [`ServerError`](#servererror)

| Argument | Description |
| --- | --- |
| `sandbox_id` | *Required.* The ID of the sandbox to terminate. |
| `owner_id` | The ID of the workspace that owns the sandbox. Defaults to the client configuration. If this value is not set here, it _must_ be set in the [client configuration](#2-import-the-client-sync-or-async). Otherwise, this method raises `RenderError`. |

## Runtime execution

###### `exec(sandbox_id, command, *, owner_id=None) -> Iterator[SandboxExecEvent] | AsyncIterator[SandboxExecEvent]`

Runs `command` through `bash -c` and streams events as they arrive: output chunks tagged `stdout` or `stderr`, then one final exit event. A non-zero exit code is a normal exit event, not an exception. If the stream itself fails, it raises `SandboxExecStreamError`.

*On success:* Returns an iterator of [`SandboxExecEvent`](#sandboxexecevent) values: a regular `Iterator` with `Render`, or an `AsyncIterator` with `RenderAsync`.

*Raises:* [`SandboxNotFoundError`](#sandboxnotfounderror), [`SandboxExecStreamError`](#sandboxexecstreamerror), [`SandboxExecError`](#sandboxexecerror), [`RateLimitError`](#ratelimiterror), [`ClientError`](#clienterror), [`ServerError`](#servererror)

| Argument | Description |
| --- | --- |
| `sandbox_id` | *Required.* The ID of the sandbox in which to run the command. |
| `command` | *Required.* The command to run through `bash -c`. |
| `owner_id` | The ID of the workspace that owns the sandbox. Defaults to the client configuration. If this value is not set here, it _must_ be set in the [client configuration](#2-import-the-client-sync-or-async). Otherwise, this method raises `RenderError`. |

###### `copy_to(sandbox_id, local_path, remote_path, *, owner_id=None) -> None`

Sends a local file or directory to a sandbox. For directories, it creates a tar archive, preserves symlinks, and skips sockets and FIFOs.

*On success:* Returns `None`.

*Raises:* [`SandboxNotFoundError`](#sandboxnotfounderror), [`RateLimitError`](#ratelimiterror), [`ClientError`](#clienterror), [`ServerError`](#servererror), `ValueError`

| Argument | Description |
| --- | --- |
| `sandbox_id` | *Required.* The ID of the destination sandbox. |
| `local_path` | *Required.* The local file or directory to copy. |
| `remote_path` | *Required.* The destination path in the sandbox. |
| `owner_id` | The ID of the workspace that owns the sandbox. Defaults to the client configuration. If this value is not set here, it _must_ be set in the [client configuration](#2-import-the-client-sync-or-async). Otherwise, this method raises `RenderError`. |

###### `copy_from(sandbox_id, remote_path, local_path, *, owner_id=None) -> str`

Fetches a file or directory from a sandbox, writes it to a local path, and returns that path. Directories are extracted automatically.

*On success:* Returns the local path written.

*Raises:* [`SandboxNotFoundError`](#sandboxnotfounderror), [`SandboxFileNotFoundError`](#sandboxfilenotfounderror), [`SandboxDownloadError`](#sandboxdownloaderror), [`RateLimitError`](#ratelimiterror), [`ClientError`](#clienterror), [`ServerError`](#servererror)

| Argument | Description |
| --- | --- |
| `sandbox_id` | *Required.* The ID of the source sandbox. |
| `remote_path` | *Required.* The file or directory path in the sandbox to copy. |
| `local_path` | *Required.* The local destination path. |
| `owner_id` | The ID of the workspace that owns the sandbox. Defaults to the client configuration. If this value is not set here, it _must_ be set in the [client configuration](#2-import-the-client-sync-or-async). Otherwise, this method raises `RenderError`. |

## Snapshot management

Access snapshot methods through `render.experimental.sandboxes.snapshots`.

Snapshot results include the snapshot ID, optional name, source sandbox ID, sandbox group ID, kind, status, plan, capture and expiration times, size in bytes, and any capture error.

Deleting a snapshot prevents future restores but does not affect sandboxes already restored from it. After a snapshot expires, you can no longer retrieve or restore it, and snapshot lists omit it.

###### `snapshots.create(sandbox_id, *, kind="filesystem", name=None, expires_at=None, owner_id=None) -> Snapshot`

Captures a running sandbox in a snapshot. The operation returns before capture completes. Wait for the snapshot's status to become `available` before restoring it. If the status becomes `failed`, check the snapshot's `error` field. To set a custom expiration time, pass `expires_at` as a timezone-aware `datetime`. Omit this parameter to use Render's default snapshot lifetime. The returned expiration field shows when the snapshot expires.

*On success:* Returns a [`Snapshot`](#snapshot) representing the initial state of the new snapshot.

*Raises:* [`SandboxNotFoundError`](#sandboxnotfounderror), [`RateLimitError`](#ratelimiterror), [`ClientError`](#clienterror), [`ServerError`](#servererror)

| Argument | Description |
| --- | --- |
| `sandbox_id` | *Required.* The ID of the running sandbox to capture. |
| `kind` | The snapshot type: `filesystem` to capture the writable filesystem, or `runtime` to also capture memory and CPU state. |
| `name` | An optional, case-sensitive name for the snapshot. Names are scoped to the sandbox group, can be reused, and cannot begin with `snp-`. |
| `expires_at` | A future, timezone-aware `datetime` when the snapshot expires. Defaults to Render's snapshot lifetime. |
| `owner_id` | The ID of the workspace that owns the sandbox. Defaults to the client configuration. |

###### `snapshots.from_id(*, sandbox_group_id, snapshot_id, owner_id=None) -> Snapshot`

Fetches a snapshot in the specified sandbox group. Use this method to poll the snapshot's status after capture.

*On success:* Returns the current [`Snapshot`](#snapshot) state.

*Raises:* [`SnapshotNotFoundError`](#snapshotnotfounderror), [`RateLimitError`](#ratelimiterror), [`ClientError`](#clienterror), [`ServerError`](#servererror)

| Argument | Description |
| --- | --- |
| `sandbox_group_id` | *Required.* The ID of the sandbox group that contains the snapshot. |
| `snapshot_id` | *Required.* The ID of the snapshot to retrieve. |
| `owner_id` | The ID of the workspace that owns the sandbox group. Defaults to the client configuration. |

###### `snapshots.list(*, sandbox_group_id, status=None, cursor=None, limit=None, owner_id=None) -> SnapshotList`

Lists up to 100 snapshots per page, newest first. The `status` parameter accepts a string or sequence of strings to filter by `creating`, `available`, or `failed`. The method returns `SnapshotList(snapshots, next_cursor)`; pass the final cursor to retrieve the next page.

*On success:* Returns a [`SnapshotList`](#snapshotlist) page.

*Raises:* [`RateLimitError`](#ratelimiterror), [`ClientError`](#clienterror), [`ServerError`](#servererror)

| Argument | Description |
| --- | --- |
| `sandbox_group_id` | *Required.* The ID of the sandbox group whose snapshots to list. |
| `status` | One status or a sequence of statuses to filter results by. |
| `cursor` | A cursor from a previous response. Use this to retrieve the next page of results. |
| `limit` | The maximum number of snapshots to return. The API caps this value at 100. |
| `owner_id` | The ID of the workspace that owns the sandbox group. Defaults to the client configuration. If this value is not set here, it _must_ be set in the [client configuration](#2-import-the-client-sync-or-async). Otherwise, this method raises `RenderError`. |

###### `snapshots.delete(*, sandbox_group_id, snapshot_id, owner_id=None) -> None`

Deletes a snapshot in the specified sandbox group. You cannot delete a snapshot while its status is `creating`.

*On success:* Returns `None`.

*Raises:* [`SnapshotNotFoundError`](#snapshotnotfounderror), [`SnapshotNotReadyError`](#snapshotnotreadyerror), [`RateLimitError`](#ratelimiterror), [`ClientError`](#clienterror), [`ServerError`](#servererror)

| Argument | Description |
| --- | --- |
| `sandbox_group_id` | *Required.* The ID of the sandbox group that contains the snapshot. |
| `snapshot_id` | *Required.* The ID of the snapshot to delete. |
| `owner_id` | The ID of the workspace that owns the sandbox group. Defaults to the client configuration. |

## Error types

Snapshot errors include `code` when the API returns an error code. Capturing a sandbox that is not running raises `ClientError` with the code `sandbox_not_running`.

### Sandbox errors

These errors pertain to operations that target a sandbox.

###### `SandboxNotFoundError`

Raised when the sandbox does not exist or is no longer retrievable.

### Command execution errors

These errors pertain to running commands in a sandbox.

###### `SandboxExecStreamError`

Raised when the exec stream ended with a terminal error; carries `status` and `message`.

###### `SandboxExecError`

Raised when the stream ended without a terminal event or sent something unparseable.

### File transfer errors

These errors pertain to copying files to or from a sandbox.

###### `SandboxFileNotFoundError`

Raised when the sandbox is alive, but the path does not exist.

###### `SandboxDownloadError`

Raised when a download could not be written or extracted safely.

### Snapshot errors

These errors pertain to creating, restoring, and managing sandbox snapshots.

###### `SnapshotNotFoundError`

Raised when the snapshot cannot be found in the specified group, including after deletion or expiration.

###### `SnapshotNotReadyError`

Raised when restore by ID or name requires an `available` snapshot, or deletion was attempted while capture was still `creating`.

###### `SnapshotPlanMismatchError`

Raised when a runtime snapshot is restored onto a different plan.

### API errors

These errors pertain to responses from the Render API.

###### `RateLimitError`

Raised when HTTP 429 occurs because of either the request rate or the concurrency cap (see [Early access limits](sandboxes#early-access-limits)).

###### `ClientError`

Raised when the API returns another 4xx response. Capturing a sandbox that is not running raises this error with the code `sandbox_not_running`.

###### `ServerError`

Raised when the API returns a 5xx response.

## Additional types

### Sandbox types

###### `Sandbox`

Represents a sandbox returned by `create()` or `from_id()`, or included in a `SandboxList`.

| Property | Description |
| --- | --- |
| `id` | The sandbox's ID. |
| `status` | The sandbox's current status. |
| `plan` | The sandbox's compute plan. |
| `network_policy` | The sandbox's default outbound network policy. |
| `region` | The Render region in which the sandbox runs. |
| `timeout_seconds` | The sandbox's maximum lifetime, in seconds. |
| `created_at` | The time when the sandbox was created. |
| `terminated_at` | The time when the sandbox was terminated, or `None` if it has not been terminated. |

###### `SandboxList`

Represents one page of sandboxes returned by `list()`.

| Property | Description |
| --- | --- |
| `sandboxes` | A list of `Sandbox` objects in this page. |
| `next_cursor` | The cursor for the next page, or `None` when there are no more results. |

### Sandbox group types

###### `SandboxGroup`

Represents a sandbox group returned in a `SandboxGroupList`.

| Property | Description |
| --- | --- |
| `id` | The sandbox group's ID. |
| `owner_id` | The ID of the workspace that owns the sandbox group. |
| `name` | The sandbox group's name. |
| `region` | The Render region that the sandbox group belongs to. |
| `is_default` | Whether this is the workspace's default sandbox group. |
| `concurrency_limit` | The maximum number of sandboxes that can run concurrently in this group. |
| `created_at` | The time when the sandbox group was created. |
| `updated_at` | The time when the sandbox group was last updated. |
| `environment_id` | The ID of the associated environment, or `None` if the group has none. |

###### `SandboxGroupList`

Represents one page of sandbox groups returned by `list_groups()`.

| Property | Description |
| --- | --- |
| `groups` | A list of `SandboxGroup` objects in this page. |
| `next_cursor` | The cursor for the next page, or `None` when there are no more results. |

### Snapshot types

###### `Snapshot`

Represents a snapshot returned by a `snapshots` method or included in a `SnapshotList`.

| Property | Description |
| --- | --- |
| `id` | The snapshot's ID. |
| `sandbox_group_id` | The ID of the sandbox group that contains the snapshot. |
| `source_sandbox_id` | The ID of the sandbox from which the snapshot was captured. |
| `name` | The optional name assigned when the snapshot was created, or `None`. |
| `kind` | The snapshot type: `filesystem` or `runtime`. |
| `status` | The snapshot's current status. |
| `plan` | The compute plan of the source sandbox. |
| `requested_at` | The time when snapshot capture was requested. |
| `captured_at` | The time when capture completed, or `None` while the snapshot is still being created. |
| `expires_at` | The time when the snapshot expires. |
| `size_bytes` | The snapshot's size in bytes, or `None` until capture completes. |
| `error` | The capture error message, if capture failed; otherwise `None`. |

###### `SnapshotList`

Represents one page of snapshots returned by `snapshots.list()`.

| Property | Description |
| --- | --- |
| `snapshots` | A list of `Snapshot` objects in this page. |
| `next_cursor` | The cursor for the next page, or `None` when there are no more results. |

### Command execution types

###### `SandboxExecOutput`

Represents an output event yielded by `exec()`.

| Property | Description |
| --- | --- |
| `stream` | The output stream: `stdout` or `stderr`. |
| `data` | The output text. |

###### `SandboxExecExit`

Represents the final event yielded by `exec()`.

| Property | Description |
| --- | --- |
| `exit_code` | The command's exit code. |

###### `SandboxExecEvent`

The `SandboxExecEvent` type is a `SandboxExecOutput` or `SandboxExecExit` object yielded by `exec()`.


---

##### Appendix: Glossary definitions

###### region

Each Render service runs in one of the following regions: *Oregon*, *Ohio*, *Virginia*, *Frankfurt*, or *Singapore*.

Services in the same region can communicate over their *private network*.

Related article: https://render.com/docs/regions.md