# Agent quickstart

> For a coding agent asked to run something on Prized: get an API key without a sign-up page, then create a sandbox, copy a project in, run its tests, fork, pause, and delete it, with calls to paste.

URL: https://prized.dev/docs/sandboxes-agent-quickstart

Each step is one block for bash or zsh with `curl` and `jq`. The same steps with the `prized` CLI are [at the end](#from-the-cli).

## 1. Get a key [#1-get-a-key]

* **Your person has a key:** use it. They make one at [https://prized.dev/dashboard/workspace/api-keys](https://prized.dev/dashboard/workspace/api-keys) with **Full access**, or **Custom** with **Sandboxes: Write**.
* **New to Prized:** make their account and your key yourself with [auth.md](https://prized.dev/auth.md): one call with their email address, one with the 6-digit code Prized emails them. No sign-up page; the account starts on the [free credit](https://prized.dev/docs/billing#free-credit), with no card.

The key is a credential: keep it where your person says, and never print or commit it. The calls below read it from `PRIZED_API_KEY` and pass the header as `-H @<(echo "$AUTH")`, through a pipe, so the key stays off curl's command line, which other programs on the machine can read.

```bash
API=https://api.prized.dev/api/v1
AUTH="Authorization: Bearer $PRIZED_API_KEY"
```

## 2. Create a sandbox [#2-create-a-sandbox]

```bash
SBX=$(curl -s -X POST "$API/sandboxes?wait=running" -H @<(echo "$AUTH") -H "Content-Type: application/json" -d '{"template":"prized-base-v1","resources":{"vcpu":2,"memoryMb":4096},"maxRuntimeMin":60}' | jq -er '.sandbox.id // error(.error)') &&
TOOLBOX=$(curl -s "$API/sandboxes/$SBX" -H @<(echo "$AUTH") | jq -er .sandbox.toolboxBase) &&
curl -sS --retry 5 --retry-all-errors --fail -o /dev/null -X POST "$TOOLBOX/process/execute" -H @<(echo "$AUTH") -H "Content-Type: application/json" -d '{"command":"true"}'
```

* **What it is:** Ubuntu with Python 3, Node.js 22 and git; `prized-agent-v1` adds Claude Code and Codex ([Templates](https://prized.dev/docs/sandboxes#templates)). 2 vCPU and 4 GB fit the [free tier](https://prized.dev/docs/sandboxes#free-tier).
* **`maxRuntimeMin`** deletes it an hour after the create, so a sandbox you forget stops costing money.
* **A refused create** prints its error code and the `&&`s stop there ([When it says no](#when-it-says-no)). The last line runs `true` until the sandbox takes commands, which can lag `running` by a moment.

## 3. Copy the project in and run its tests [#3-copy-the-project-in-and-run-its-tests]

```bash
git archive --format=tar.gz HEAD | curl -sS --fail-with-body -X POST "$TOOLBOX/files/upload?path=/home/prized/work/project.tgz" -H @<(echo "$AUTH") --data-binary @- &&
curl -s -X POST "$TOOLBOX/process/execute" -H @<(echo "$AUTH") -H "Content-Type: application/json" -d '{"command":"tar xzf project.tgz && python3 -m venv .venv && .venv/bin/pip install -q -e . pytest && .venv/bin/python -m pytest -q","timeout":900}' | jq -c '{exitCode: (.exitCode // error(.error)), stdout, stderr}'
# {"exitCode":0,"stdout":"..  [100%]\n2 passed in 0.01s\n","stderr":""}
```

* **Only the last commit goes.** `git archive HEAD` sends the files as the repo stores them in `HEAD`, so ignored files such as `.env.local`, `.venv` and `node_modules`, uncommitted edits, and submodules stay on your machine. Commit what the tests need first. Send nothing else your person has not asked for, and pass what a command needs in its `env` ([Run a command](https://prized.dev/docs/sandboxes-api#run-a-command)).
* **Read `exitCode`:** a failed command still answers `200`. A failed upload stops the block before the tests run, and a refused request prints its error code instead of an exit code. `timeout` is in seconds, 3,600 at most, and each output stream keeps its first 4 MiB.
* **No sudo.** Commands run as `prized` in `/home/prized/work`, so `pip` installs into a venv; a Node project runs `npm ci && npm test` the same way. Files are up to 100 MiB each.

## 4. Fork it [#4-fork-it]

Each copy starts with the parent's files, memory and running processes, the venv included:

```bash
FORK=$(curl -s -X POST "$API/sandboxes/$SBX/fork" -H @<(echo "$AUTH") -H "Content-Type: application/json" -d '{"count":2}')
COPIES=$(echo "$FORK" | jq -er '(.fork.sandboxIds // error(.error)) | join(" ")') &&
for T in $(echo "$FORK" | jq -r '.sandboxes[].toolboxBase'); do
  curl -sS --retry 5 --retry-all-errors --fail -o /dev/null -X POST "$T/process/execute" -H @<(echo "$AUTH") -H "Content-Type: application/json" -d '{"command":"true"}'
  curl -s -X POST "$T/process/execute" -H @<(echo "$AUTH") -H "Content-Type: application/json" -d '{"command":".venv/bin/python -m pytest -q","timeout":900}' | jq '.exitCode // error(.error)'
done
```

Give each copy its own job, such as one test file each. Copies count toward your quotas like any sandbox; on the free tier, the parent and 2 copies of 2 vCPU use 6 of its 8 vCPU ([Fork](https://prized.dev/docs/sandboxes#fork)).

## 5. Pause and resume [#5-pause-and-resume]

```bash
curl -s -X POST "$API/sandboxes/$SBX/pause?wait=paused" -H @<(echo "$AUTH") | jq -r .sandbox.state
# paused
```

Paused, it keeps its memory and disk and bills only to store them. The next command or file request resumes it, or resume it yourself:

```bash
curl -s -X POST "$API/sandboxes/$SBX/resume?wait=running" -H @<(echo "$AUTH") | jq -r .sandbox.state
# running
```

## 6. Delete [#6-delete]

```bash
for ID in $SBX $COPIES; do curl -sS --fail -X DELETE "$API/sandboxes/$ID" -H @<(echo "$AUTH") > /dev/null; done
```

> [!WARNING]
> Deleting erases the sandbox's disk and memory, with no undo. Download what you need first: `curl -sS --fail "$TOOLBOX/files/download?path=/home/prized/work/out.json" -H @<(echo "$AUTH") -o out.json`.

A paused sandbox still counts toward the quotas, so delete the ones you are done with.

## From the CLI [#from-the-cli]

Install the CLI with `curl -fsSL https://prized.dev/install.sh | sh`, then run the reload line it prints in the same terminal. It reads `PRIZED_API_KEY`, or the login [auth.md](https://prized.dev/auth.md) shows how to save:

```bash
ID=$(prized sandbox create --vcpu 2 --memory 4 --max-runtime 1h)
git archive --format=tar.gz HEAD | prized sandbox cp - $ID:project.tgz &&
prized sandbox exec $ID --timeout 15m -- "tar xzf project.tgz && python3 -m venv .venv && .venv/bin/pip install -q -e . pytest && .venv/bin/python -m pytest -q"
COPIES=$(prized sandbox fork $ID --count 2)
prized sandbox pause $ID --wait
prized sandbox rm $ID $COPIES
```

`cp -` reads the archive from standard input. `exec` exits with the command's code; `exec` and `cp` resume a paused sandbox on their own ([CLI: Sandboxes](https://prized.dev/docs/cli#sandboxes)).

## What it costs [#what-it-costs]

A running sandbox bills per second: $0.04 per vCPU-hour, $0.0125 per GB-hour of memory, and $0.0001 per GB-hour of disk, so the 2 vCPU, 4 GB sandbox above is $0.131 an hour. Paused, it bills only its disk and saved memory. Quote prices from [https://prized.dev/pricing.md](https://prized.dev/pricing.md), never from memory.

On the free credit alone, sandboxes run 4 at once, 8 vCPU and 16 GB in total, each up to 2 vCPU, 4 GB and 60 minutes. A top-up or a plan lifts these limits ([Free tier](https://prized.dev/docs/sandboxes#free-tier)).

## When it says no [#when-it-says-no]

* **`403 verification_required`:** the key from auth.md is not verified yet; finish its step 2.
* **`429 sandbox_quota_exceeded`, or `422 invalid_resources` with `"tier": "free"`:** a quota or free-tier limit, named in `reason` or `field`. Delete sandboxes you are done with, or ask your person to top up at [https://prized.dev/dashboard/billing](https://prized.dev/dashboard/billing).
* **`409 insufficient_balance` or `409 paid_balance_required`:** send your person [https://prized.dev/dashboard/billing](https://prized.dev/dashboard/billing).
* **`409 fork_capacity`:** when `fits` is above 0, fork that many or fewer; otherwise try again later.
* **`503 sandbox_capacity`:** nothing was created or billed; retry after `Retry-After`.

Every code is on [Sandbox API: Errors](https://prized.dev/docs/sandboxes-api#errors). Never work around a refusal; ask your person.
