# Integrate with the SDK

https://instabox.sh/docs/integrate.md

The calls an app needs: create, pause and resume, delete, a shell, the desktop, and usage.

Everything below runs on your server with an API key (`ibk_...`, from **API keys** in the dashboard sidebar). Never send the key to a browser.
```
npm install @insforge/instabox-sdk
export INSTABOX_API_KEY=ibk_...
```
The SDK reads `INSTABOX_API_KEY` from the environment, so the `apiKey` option below is optional. Pass it when the key comes from somewhere else, such as your own secret store. Without a key, every call throws `InstaboxAuthError` (`missing_api_key`) before sending a request.

### 1. Create a machine
```
import { Sandbox } from '@insforge/instabox-sdk'

const sbx = await Sandbox.create('agent-browser', {
  // optional: the env var works without this line
  apiKey: process.env.INSTABOX_API_KEY,
  // your own tags, to find it later
  metadata: { customer: 'acme' },
  // disable personal Vault delivery; no Secret selections are supplied
  vault: false,
})
// m_...: store it with your user
console.log(sbx.sandboxId)
```
`agent-browser` is the default template: Linux, a desktop and a browser. Later, from another request: `const sbx = await Sandbox.connect(id)`. `Sandbox.list({ metadata: { customer: 'acme' } })` finds machines by tag.

### 2. Pause and resume
```
// memory, files and running processes are kept
await sbx.pause()
// carries on where it left off, usually in about a second
await sbx.resume()
// connect also resumes a paused machine
const again = await Sandbox.connect(id)
// look without waking it
const peek = await Sandbox.connect(id, { resume: false })
```
Idle machines pause by themselves after 30 minutes.

### 3. Delete it
```
// deletes the machine and its disks; false if already gone
await sbx.kill()
// the same, by ID
await Sandbox.kill(id)
```

### 4. A shell
For commands from your code:
```
const r = await sbx.commands.run('python3 -c "print(6 * 7)"', {
  cwd: '/data/home',
  timeoutMs: 60_000,
})
// a non-zero exit throws CommandExitError (stdout, stderr, exitCode)
console.log(r.stdout, r.exitCode)
await sbx.files.write('/data/home/app.py', 'print("hi")')
console.log(await sbx.files.read('/data/home/app.py'))
```
For an interactive SSH session (your public key in, a short-lived certificate out):
```
const ssh = await sbx.sshCredentials(publicKey, { ttlSeconds: 3600 })
// save ssh.certificate as <key>-cert.pub next to the private key,
// add ssh.knownHostsLine to known_hosts, then:
// ssh -p ${ssh.port} ${ssh.username}@${ssh.host}
```
See [SSH](https://instabox.sh/docs/ssh.md) for the details.

### 5. The desktop (VNC)
```
// starts the desktop; safe to call again
await sbx.desktop.start()

// Let people watch it: a link to one machine's desktop,
// for a new tab or an <iframe>
const { url } = await sbx.desktop.streamUrl({
  viewOnly: true,
  ttlSeconds: 3600,
})

// Let an agent use it
await sbx.desktop.open('https://example.com')
const png = await sbx.desktop.screenshot()
await sbx.desktop.click(640, 400)
await sbx.desktop.type('hello')
await sbx.desktop.press('Enter')

// Take the links away (e.g. when a user's access ends);
// open viewers close within seconds
await sbx.desktop.revokeStreamUrls()
```
See [Desktop](https://instabox.sh/docs/desktop.md) for embedding the link and a full agent loop.

### 6. Watch load and bill per machine
```
// CPU and memory, one sample per 30 s, oldest first
const samples = await sbx.getMetrics()
// bill a customer: running seconds of their machines this month
const machines = await Sandbox.list({ metadata: { customer: 'acme' } })
let seconds = 0
for (const m of machines) {
  const u = await Sandbox.getUsage(m.sandboxId)
  seconds += u.runningSeconds
}
```
`getUsage` covers the current UTC month by default and counts running time only, not paused or stopped. See [Metrics and usage](https://instabox.sh/docs/sdk.md) for every field.

### Errors
Calls throw `InstaboxError` with `status` and `code` (`not_found`, `quota_exceeded`, ...); a missing or bad key throws `InstaboxAuthError`. The same calls over HTTP:

| SDK | HTTP |
|---|---|
| `Sandbox.create` | `POST /v1/machines` |
| `pause` / `resume` | `POST /v1/machines/{id}/suspend` / `.../resume` |
| `kill` | `DELETE /v1/machines/{id}` |
| `commands.run` | `POST /v1/machines/{id}/exec` |
| `sshCredentials` | `POST /v1/machines/{id}/connections` |
| `desktop.start` | `POST /v1/machines/{id}/desktop` |
| `desktop.streamUrl` / `revokeStreamUrls` | `POST` / `DELETE /v1/machines/{id}/desktop/stream` |
| `getMetrics` | `GET /v1/machines/{id}/metrics` |
| `getUsage` | `GET /v1/machines/{id}/usage` |
| `Sandbox.usage` | `GET /v1/usage` |

Every endpoint: the [API reference](https://instabox.sh/docs/api.md).

### SDK operations
Every call in the SDK, by task. `sbx` is a `Sandbox` object.

| Operation | Call | What it does |
|---|---|---|
| **1. Create and find** | | |
| Create | `Sandbox.create(template?, opts?)` | New machine, waits until it runs |
| Connect | `Sandbox.connect(id, opts?)` | Attach by ID; resumes it |
| List | `Sandbox.list(opts?)` | Your machines, filter by metadata |
| Info | `sbx.getInfo()` | State, metadata, auto-pause |
| Running? | `sbx.isRunning()` | True if running now |
| **2. Pause and resume** | | |
| Pause | `sbx.pause()` | Suspend, memory kept |
| Resume | `sbx.resume()` | Resume or start it |
| Stop | `sbx.stop()` | Shut down, `/data` kept |
| Idle pause | `sbx.setAutoSuspend(idleMs)` | Pause it when idle |
| **3. Delete** | | |
| Delete | `sbx.kill()` | Delete it and its disks |
| Delete by ID | `Sandbox.kill(id, opts?)` | The same, by ID |
| **4. Shell** | | |
| Run | `sbx.commands.run(cmd, opts?)` | Run a command, get its output |
| Raw exec | `sbx.commands.exec(cmd, opts?)` | Run, no throw on non-zero exit |
| Read file | `sbx.files.read(path, opts?)` | Text, or bytes |
| Write file | `sbx.files.write(path, data)` | Create or replace a file |
| List files | `sbx.files.list(path)` | A directory's entries |
| Remove file | `sbx.files.remove(path)` | A file or a directory |
| File exists? | `sbx.files.exists(path)` | True if it exists |
| SSH | `sbx.sshCredentials(publicKey, opts?)` | A short-lived certificate |
| **5. Desktop and VNC** | | |
| Start | `sbx.desktop.start(opts?)` | Start the desktop |
| Status | `sbx.desktop.status()` | Running, screen size |
| Share link | `sbx.desktop.streamUrl(opts?)` | A link to watch it |
| Revoke links | `sbx.desktop.revokeStreamUrls()` | End every link and viewer |
| Screenshot | `sbx.desktop.screenshot()` | A PNG of the screen |
| Click | `sbx.desktop.click(x, y, opts?)` | Click at a point |
| Move | `sbx.desktop.move(x, y)` | Move the pointer |
| Drag | `sbx.desktop.drag(from, to)` | Drag with the left button |
| Scroll | `sbx.desktop.scroll(opts)` | Turn the wheel |
| Type | `sbx.desktop.type(text, opts?)` | Type text |
| Press | `sbx.desktop.press(keys)` | A key or a chord |
| Open URL | `sbx.desktop.open(url)` | Open it in the browser |
| Pointer | `sbx.desktop.cursorPosition()` | Where the pointer is |
| **6. Metrics and usage** | | |
| Metrics | `sbx.getMetrics(opts?)` | CPU and memory samples |
| Metrics by ID | `Sandbox.getMetrics(id, opts?)` | The same, by ID |
| Usage | `sbx.getUsage(opts?)` | Running time, for billing |
| Usage by ID | `Sandbox.getUsage(id, opts?)` | The same, by ID |
| Account usage | `Sandbox.usage(opts?)` | Counts, storage, limits |
| **7. Also** | | |
| Labels | `sbx.setMetadata(metadata)` | Replace its metadata |
| Save snapshot | `sbx.createSnapshot(opts)` | Save its disks |
| Copy | `Sandbox.create(snapshot.id)` | A new machine from a snapshot |
| List snapshots | `Sandbox.listSnapshots(opts?)` | Your snapshots |
| Get snapshot | `Sandbox.getSnapshot(id, opts?)` | One snapshot |
| Delete snapshot | `Sandbox.deleteSnapshot(id, opts?)` | Delete a snapshot |

Full details: [SDK reference](https://instabox.sh/docs/sdk.md).
