Skip to main content
The boxrouter package gives Python a synchronous and an asynchronous client for the BoxRouter API. It needs Python 3.11 or later. python -m pip show boxrouter prints the version you have.

Install

Your first sandbox is in the quickstart.

Configure the Client

For each setting, the client uses the argument first, then the environment variable, then the default. timeout takes an httpx.Timeout. Its limits apply to individual network waits, not the whole request; see HTTPX timeouts. Creating a sandbox that sets up an image can wait minutes, so leave the default read timeout or raise it. Command options set a command’s own limit. The client resends an API call only when the error says retry: safe, up to max_retries times, with the same idempotency key. Recover from Errors has the rules.

Choose Sync or Async

BoxRouter blocks. AsyncBoxRouter has the same methods, with three calling patterns:
  • Await coroutine methods such as create, exec and destroy.
  • Enter the async context managers returned by terminal and launch with async with.
  • Use async for for an async iterator such as volumes.list_files.
Leaving async with box requests the sandbox’s destruction, even when your code raised. Leaving async with client closes HTTP connections and leaves every sandbox as it was.

Handle Errors

Branch on error.retry, not on error.status: the status never decides a retry. A command that exits nonzero or reaches its timeout is a result: read exit_code and timed_out, because nothing is raised. Pass check=True to raise CommandFailed for either. Save this as errors.py. It runs a command in a sandbox that does not exist and prints the error’s code and outcome:
A retry of check_outcome means BoxRouter cannot tell whether the call ran. Read the operation before resending (Recover from Errors has the steps). Quote request_id to support. When the workload and the sandbox’s cleanup both fail, the SDK raises a BaseExceptionGroup holding both; catch it with except*. If only the cleanup fails, you get its error alone. Either way it carries the sandbox ID as a note. A failed cleanup does not prove the sandbox stopped: keep its ID and look it up under Sandboxes before you retry.

Where Each Task Lives

Next Steps

Find an SDK or CLI Call

The Python call for each sandbox task.

Recover from Errors

When resending a failed call is safe.

Use the TypeScript SDK

The same tasks in TypeScript.