Skip to main content
Import the top-level client from porter-sandbox:
import { Porter } from "porter-sandbox";

Porter

Porter is the top-level client. It exposes resource namespaces for sandboxes, volumes, health, and readiness.
const porter = new Porter();
const sandbox = await porter.sandboxes.create({
  image: "python:3.12-slim",
  name: "my-sandbox",
});
Constructor options:
OptionTypeDescription
apiKeystring | undefinedOptional 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.
baseUrlstring | undefinedOptional API base URL override. In-cluster Porter Applications use the in-cluster Sandbox API URL by default.
timeoutMsnumber | undefinedRequest timeout in milliseconds. Defaults to 30 seconds.
Close the client when your process is done:
porter.close();

porter.sandboxes

create

const sandbox = await porter.sandboxes.create({
  image: "python:3.12-slim",
  name: "my-sandbox",
  command: undefined,
  args: undefined,
  env: undefined,
  tags: { workflow: "demo" },
  volume_mounts: undefined,
});
Options:
OptionTypeDescription
imagestringContainer image to run.
namestring | undefinedOptional 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.
commandstring[] | undefinedOptional entrypoint override.
argsstring[] | undefinedOptional arguments passed to the command.
envRecord<string, string> | undefinedEnvironment variables to set in the sandbox.
tagsRecord<string, string> | undefinedKey-value labels for finding related sandboxes.
volume_mountsRecord<string, string> | undefinedVolume IDs keyed by absolute mount path inside the sandbox.
Returns a Sandbox handle.

get

const sandbox = await 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

const sandboxes = await 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
idstringSandbox identifier.
phaseStatusResponsePhase | nullLast-known lifecycle phase.
tagsRecord<string, string> | nullLast-known tags.
Methods:
const status = await sandbox.refresh();
const result = await sandbox.exec(["python", "-c", "print('hi')"]);
const logs = await sandbox.logs({ limit: 100 });
await 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(options?)Fetches structured log lines.
terminate()Terminates the sandbox.

Volumes

Volumes are persistent storage that can be mounted into sandboxes.
const volume = await porter.volumes.create({ name: "my-data" });

const sandbox = await 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(body)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.

Low-level client

The top-level client exposes generated low-level clients through .raw:
const rawClient = porter.raw;
const rawSandboxes = porter.sandboxes.raw;
Use these only when you need an endpoint that is not wrapped by the ergonomic SDK surface yet.

Next steps