Python SDK

A dependency-free Python client for the whole API — sandboxes, execution, files, preview URLs and account. It installs straight from this site, so there is no registry account to create and nothing to keep in sync but the URL.

Install

The client uses only the Python standard library, so installing it pulls in no dependencies. It supports Python 3.8 and newer.

pip install https://sandbox-as-a-service.com/sdk/sandbox-as-a-service-python.tar.gz

That URL always serves the current release, so the same command upgrades an existing install. The versioned archive is published alongside it as sandbox_as_a_service-0.1.0.tar.gz if you pin by name. Prefer a virtual environment or a container if the interpreter is externally managed (see running commands for why a bare pip install is refused on some systems).

Quickstart

Set AAS_API_KEY from Dashboard → API keys and the client picks it up. Creating a sandbox blocks until the machine is ready, and using it as a context manager destroys it on the way out — billing stops there.

from sandbox_as_a_service import Client

client = Client()  # reads AAS_API_KEY from the environment

with client.create_sandbox(size="small", timeout_minutes=15) as sandbox:
    result = sandbox.exec('python3 -c "print(6 * 7)"')
    print(result.stdout, end="")   # 42

    sandbox.write_file("/workspace/app.py", "print('hello from the sandbox')")
    print(sandbox.read_file("/workspace/app.py").content)

    for entry in sandbox.list_files("/workspace").entries:
        print(entry["name"], entry["type"], entry["size_bytes"])
# the sandbox is destroyed here

result.ok is True when the exit code is zero, and result.check() raises ExecutionFailed when it is not — useful when a failed command should stop the script:

result = sandbox.exec("python3 -m pytest -q", timeout_ms=300000, cwd="/workspace")
result.check()  # raises ExecutionFailed on a non-zero exit code

A sandbox can also be created, kept and destroyed explicitly, which is what you want when one machine serves several steps:

sandbox = client.create_sandbox(size="small", name="build-runner", timeout_minutes=15)
try:
    sandbox.exec("git clone https://example.com/repo.git /workspace/repo")
    sandbox.extend(additional_minutes=30)
finally:
    sandbox.destroy()

Pass idempotency_key when a request might be retried — a dropped response then returns the existing sandbox instead of creating a second one: client.create_sandbox(idempotency_key="job-42-attempt-1"). If it is omitted, the client generates a random one per call.

What the client covers

CallWhat it does
client.create_sandbox(size, name, timeout_minutes)Creates a sandbox and returns it ready to use. Idempotency key optional.
client.get_sandbox(id)Fetches one sandbox by id.
client.list_sandboxes(limit, starting_after, include_deleted)One page of sandboxes, newest first.
client.iter_sandboxes()Iterates every sandbox across pages.
client.get_account()Balance, limits and current pricing.
client.get_usage(days=30)Usage and spend over a window.
sandbox.refresh()Re-reads status, expiry and resources.
sandbox.extend(additional_minutes)Pushes the expiry back, within the maximum lifetime.
sandbox.exec(command, timeout_ms, cwd, env)Runs a command and returns stdout, stderr, exit code and duration.
sandbox.get_execution(id)Fetches an execution by id.
sandbox.write_file(path, content, encoding)Writes text or base64 content into the sandbox.
sandbox.read_file(path, encoding)Reads a file back, as text or base64.
sandbox.list_files(path, recursive)Lists a directory with names, types and sizes.
sandbox.delete_file(path, recursive)Deletes a file or directory.
sandbox.expose_port(port) / list_ports() / close_port(port)Creates and manages preview URLs.
sandbox.destroy()Destroys the sandbox. Billing stops immediately.

Errors

Non-2xx responses raise a specific exception, so a caller can react to the reason rather than parse a status code. Every SandboxApiError carries status, type, request_id and the decoded body; quote the request id in a support request.

from sandbox_as_a_service import Client, RateLimitError, NotFoundError

client = Client()

try:
    sandbox = client.get_sandbox("sbx_does_not_exist")
except NotFoundError:
    print("gone")
except RateLimitError as err:
    print("slow down, retry after", err.retry_after, "seconds")
ExceptionRaised when
AuthenticationErrorThe key is missing, malformed or revoked (401).
PermissionError_The key is valid but not allowed to do this (403).
NotFoundErrorNo such sandbox, file or execution (404).
InvalidRequestErrorThe request body or parameters were rejected (400/422).
ConflictErrorThe sandbox is in a state that forbids the operation (409).
PaymentRequiredErrorThe account has no credit left (402).
RateLimitErrorA rate limit was hit (429); retry_after is set when the header is present.
ServiceUnavailableErrorA transient server or upstream failure (5xx).
SandboxConnectionErrorThe request never reached the API — DNS, TLS or timeout.

Notes

  • Client() reads AAS_API_KEY; pass api_key= or base_url= to override. A bare host is normalized to its /v1 API root.
  • The default client timeout is 600 seconds, generous because create blocks until the machine is ready. exec raises its own timeout above the command's timeout_ms so a long command is not cut off by the client first.
  • Release with the context managers or by calling destroy() — an abandoned sandbox keeps billing until it expires.
  • The same operations are available over REST and as MCP tools; the SDK is a thin, typed wrapper over them, and the OpenAPI document can generate a client in another language.

Try it with your own key

Sign in, create a key, then pip install the client and run your first sandbox.