DocsQuickstart

Quickstart

Create a sandbox, run a command in it and shut it down, in TypeScript or Python. The curl tab covers create, read and kill.

Before you start

You need an API key. Create one at dashboard.impello.ai/keys. Every key starts with imp_, and the dashboard is the only place you can read it. See API keys.

Put the key in your environment. Both SDKs read IMPELLO_API_KEY.

export IMPELLO_API_KEY=imp_...

Every documented SDK setting uses the IMPELLO_ prefix. If your code already exports the older names from another sandbox provider, the SDKs still read those as a fallback — see Migrate.

Install

The TypeScript SDK needs Node 20.18.1 or later on the 20 line, or Node 22 or later. Node 21 is not supported. The Python SDK needs Python 3.10 or later.

npm install @impello/sdk

Your first sandbox

Create a sandbox from the default base template, run a command in it, read the sandbox's details, then kill it.

import { Sandbox } from '@impello/sdk'

const sandbox = await Sandbox.create('base')

const result = await sandbox.commands.run('echo hello')
console.log(result.stdout)

const info = await sandbox.getInfo()
console.log(info.sandboxId, info.state, info.endAt)

await sandbox.kill()

Save the TypeScript as quickstart.mts and run it with npx tsx quickstart.mts; the .mts extension is what lets the top-level await run. Save the Python as quickstart.py and run it with python quickstart.py.

What each step does:

  • Sandbox.create('base') starts a sandbox from the base template and returns a handle to it. The template name is optional and base is the default. The rest are on Templates.
  • commands.run('echo hello') runs a shell command and waits for it to exit. The result carries stdout, stderr and exitCode (exit_code in Python). See Run commands.
  • getInfo() (get_info() in Python) returns the sandbox ID, the template, the metadata, the state, the start time and the time the sandbox expires.
  • kill() stops the sandbox and returns true. It returns false when the sandbox no longer exists.

Commands are not part of the HTTP API: the SDK opens a separate connection to the sandbox itself to run them. The curl tab stops at create, read and kill.

Python: with, async and a bound client

A Python Sandbox is a context manager, and leaving the block calls kill().

from impello import Sandbox

with Sandbox.create("base") as sandbox:
    print(sandbox.commands.run("uname -a").stdout)

For asyncio, use AsyncSandbox. Every method is awaited, and async with kills the sandbox on the way out.

import asyncio
from impello import AsyncSandbox

async def main():
    async with await AsyncSandbox.create("base") as sandbox:
        result = await sandbox.commands.run("echo hello")
        print(result.stdout)

asyncio.run(main())

To bind a key to a client rather than to the environment, use Impello. Its Sandbox and AsyncSandbox behave like the top-level classes; a per-call argument beats the client's, which beats the environment.

from impello import Impello

client = Impello(api_key="imp_...")
sandbox = client.Sandbox.create("base")

The TypeScript SDK has one always-async Sandbox and no client class. Pass apiKey per call instead, as in Sandbox.create('base', { apiKey: 'imp_...' }).

If it fails

What went wrongTypeScriptPython
No key in the environment and none passedAuthenticationErrorAuthenticationException
A key the API rejectsAuthenticationErrorAuthenticationException
The key is not a known prefix followed by hexAuthenticationErrorAuthenticationException
The command exited non-zeroCommandExitErrorCommandExitException
The sandbox expired, a command ran past its deadline, or the request timed outTimeoutErrorTimeoutException
The create was refused: no credit, a spend ceiling, or a plan limitSandboxError, or RateLimitError for a 429SandboxException, or RateLimitException for a 429

A missing key is raised before any request leaves your process. A refused create has no class of its own — read the message rather than branching on the type, and see Refused creates. The SDKs differ on keys in the older format another sandbox provider issued: Python refuses those locally, TypeScript sends them and the server rejects them. The full list is on Errors.

Next steps