API Reference
SDK reference for the Iris sandbox API
How authentication works
Iris has two API surfaces:
- Gateway (
api.iris.dev) — sandbox lifecycle: create, fork, list, suspend. Authenticated with your API key. - Data plane (
sandbox.domain) — exec, files, checkpoints, services, store. Authenticated with a short-lived JWT issued by the gateway, scoped to one sandbox.
The SDK handles both automatically. You only ever set IRIS_API_KEY — token refresh for data plane calls is wired into the transport layer.
Sandbox management
Create
import { Sandbox } from '@iris/sdk'
const sandbox = await Sandbox.create()
const named = await Sandbox.create({ name: 'my-agent' })
console.log(sandbox.id) // "sb_abc123"from iris import IrisClient
client = IrisClient()
sandbox = client.sandboxes.create()
named = client.sandboxes.create(name="my-agent")
print(sandbox.id) # "sb_abc123"List
import { IrisClient } from '@iris/sdk'
const client = new IrisClient()
const sandboxes = await client.sandboxes.list()
for (const sb of sandboxes) {
console.log(sb.id, sb.state)
}from iris import IrisClient
client = IrisClient()
sandboxes = client.sandboxes.list()
for sb in sandboxes:
print(sb.id, sb.state)Fork
Creates a copy-on-write clone. The source keeps running unchanged.
const branch = await sandbox.fork()
await branch.exec.run('python3 risky.py')
await branch.delete()
// original sandbox untouchedbranch = sandbox.fork()
branch.exec.run(["python3", "risky.py"])
branch.delete()
# original sandbox untouchedSuspend and resume
Snapshots the sandbox and stops the VM. Compute billing pauses until resumed.
await client.sandboxes.suspend(sandbox.id)
// ... later
await client.sandboxes.resume(sandbox.id)client.sandboxes.suspend(sandbox.id)
# ... later
client.sandboxes.resume(sandbox.id)Delete
await sandbox.delete()
// or via client:
await client.sandboxes.delete(sandbox.id)sandbox.delete()
# or via client:
client.sandboxes.delete(sandbox.id)Exec
Run shell commands inside the sandbox.
const result = await sandbox.exec.run('echo hello')
console.log(result.stdout) // "hello\n"
console.log(result.ok) // true
console.log(result.exit_code) // 0
// Full options
const res = await sandbox.exec.run({
cmd: ['python3', 'train.py'],
dir: '/app',
env: { DEBUG: 'true' },
timeout_ms: 60_000,
stdin: '',
})result = sandbox.exec.run(["echo", "hello"])
print(result.stdout) # "hello\n"
print(result.ok) # True
print(result.exit_code) # 0
# Full options
res = sandbox.exec.run(
["python3", "train.py"],
dir="/app",
env={"DEBUG": "true"},
timeout_ms=60_000,
stdin="",
)Files
Read and write the sandbox filesystem.
await sandbox.files.write('/app/config.json', JSON.stringify({ debug: true }))
const text = await sandbox.files.readText('/app/output.txt')
const bytes = await sandbox.files.read('/app/model.bin')
const listing = await sandbox.files.list('/app')
const { exists } = await sandbox.files.exists('/app/data.csv')
await sandbox.files.move({ source: '/tmp/out.json', destination: '/app/out.json' })
await sandbox.files.remove('/tmp/scratch', { recursive: true })
await sandbox.files.mkdir({ path: '/app/logs', parents: true })import json
sandbox.files.write("/app/config.json", json.dumps({"debug": True}))
text = sandbox.files.read_text("/app/output.txt")
data = sandbox.files.read("/app/model.bin") # bytes
listing = sandbox.files.list("/app")
result = sandbox.files.exists("/app/data.csv")
sandbox.files.move("/tmp/out.json", "/app/out.json")
sandbox.files.remove("/tmp/scratch", recursive=True)
sandbox.files.mkdir("/app/logs", parents=True)See Files for the full operation reference.
Checkpoints
Snapshot and restore the sandbox filesystem.
const cp = await sandbox.checkpoint.create({ name: 'after-setup' })
console.log(cp.checkpoint_id)
const { checkpoints } = await sandbox.checkpoint.list()
const restored = await sandbox.checkpoint.restore(cp.checkpoint_id)
console.log(`Restored in ${restored.restore_duration_ms}ms`)
await sandbox.checkpoint.delete(cp.checkpoint_id)cp = sandbox.checkpoint.create(name="after-setup")
print(cp.checkpoint_id)
result = sandbox.checkpoint.list()
checkpoints = result.checkpoints
restored = sandbox.checkpoint.restore(cp.checkpoint_id)
print(f"Restored in {restored.restore_duration_ms}ms")
sandbox.checkpoint.delete(cp.checkpoint_id)See Checkpoints and Checkpoint Restore.
Services
Long-running background processes (databases, servers, queues).
await sandbox.services.upsert('redis', {
cmd: 'redis-server',
args: ['--port', '6379'],
health_port: 6379,
})
await sandbox.services.start('redis')
const svc = await sandbox.services.get('redis')
console.log(svc.status) // "running"
await sandbox.services.stop('redis')
await sandbox.services.delete('redis')sandbox.services.upsert(
"redis",
"redis-server",
args=["--port", "6379"],
health_port=6379,
)
sandbox.services.start("redis")
svc = sandbox.services.get("redis")
print(svc.status) # "running"
sandbox.services.stop("redis")
sandbox.services.remove("redis")See Services.
Store
Per-sandbox key-value store for agent state.
await sandbox.store.set('progress', {
value: { step: 3, score: 0.91 },
ttl_seconds: 3600,
})
const entry = await sandbox.store.get('progress')
const { keys } = await sandbox.store.list()
await sandbox.store.delete('temp')
await sandbox.store.batch([
{ op: 'set', key: 'result', value: { score: 0.95 } },
{ op: 'delete', key: 'temp' },
])sandbox.store.set("progress", {"step": 3, "score": 0.91}, ttl_seconds=3600)
entry = sandbox.store.get("progress")
keys = sandbox.store.list().keys
sandbox.store.delete("temp")
sandbox.store.batch([
{"op": "set", "key": "result", "value": {"score": 0.95}},
{"op": "delete", "key": "temp"},
])See Store.
HTTP integration
If you're not using an SDK, the two base URLs and auth headers are:
| Surface | Base URL | Auth header |
|---|---|---|
| Gateway | https://api.iris.dev | Authorization: Bearer iris_sk_... |
| Data plane | https://{sandbox.domain} | Authorization: Bearer <data_plane_token> |
Gateway requests are POST to /iris.public.v1.SandboxService/{MethodName} with a JSON body.
Data plane endpoints are REST — see the concept pages for per-operation HTTP specs.