Skip to main content
Import the top-level client from porter_sandbox:
from porter_sandbox import Porter, AsyncPorter

Porter

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

with Porter() as porter:
    sandbox = porter.sandboxes.create(
        image="python:3.12-slim",
        name="my-sandbox",
    )
Constructor options:
OptionTypeDescription
api_keystr | NoneOptional 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_urlstr | NoneOptional API base URL override. In-cluster Porter Applications use the in-cluster Sandbox API URL by default.
timeoutfloat | NoneRequest timeout in seconds. Defaults to 30 seconds.

porter.sandboxes

create

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:
ArgumentTypeDescription
imagestrContainer image to run.
namestr | NoneOptional 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.
commandlist[str] | NoneOptional entrypoint override.
argslist[str] | NoneOptional arguments passed to the command.
envdict[str, str] | NoneEnvironment variables to set in the sandbox.
tagsdict[str, str] | NoneKey-value labels for finding related sandboxes.
volume_mountsdict[str, str] | NoneVolume IDs keyed by absolute mount path inside the sandbox.
Returns a Sandbox handle.

get

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

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:
PropertyTypeDescription
idstrSandbox identifier.
phaseStatusResponsePhase | NoneLast-known lifecycle phase.
tagsdict[str, str] | NoneLast-known tags.
Methods:
status = sandbox.refresh()
result = sandbox.exec(["python", "-c", "print('hi')"])
logs = sandbox.logs(limit=100)
sandbox.terminate()
MethodDescription
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.
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:
MethodDescription
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:
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:
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