> ## Documentation Index
> Fetch the complete documentation index at: https://agent37.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Instances

> Create, size, and manage the persistent computer that runs your agent.

An instance is a persistent, isolated computer running your agent. Create one per end user. The call is synchronous: when `status` is `running`, the instance's computer is up and the agent inside finishes booting moments later — poll `GET /v1/health` on the instance URL until it answers `{ "ok": true }`, then message it at `https://{id}.agent37.app/v1/responses` (see [Send a message](/agents-api/chat) and [Instance and preview URLs](/agents-api/urls)).

Creating an instance requires one day of compute at its running rate in your workspace wallet, but debits nothing: the balance check is the create gate (below it, the create fails with `402 insufficient_balance` and nothing is provisioned), and the meter only starts when the instance first reaches `running`. How many instances you can run at once is set by your [instance limit](/agents-api/billing#instance-limits), which rises as you top up. See [Billing](/agents-api/billing).

## Create an instance

`POST /v1/instances` returns `201` with the full instance object once `status` is `running`. Every field is optional, so a `POST` with no body works: you get the default template (`agent37-hermes`) on its smallest shape, 2 vCPU / 4 GB.

<ParamField body="template" type="string" default="agent37-hermes">
  A template name. `agent37-hermes` (full Hermes, with browser and desktop) is the default; `agent37-hermes-small` (the lean image, no browser or desktop) and `agent37-openclaw` (OpenClaw, with a headless browser) are the other system templates. You can also pass one of your own [workspace templates](/agents-api/templates) by name. Any name takes an optional `@<version>` to [pin a published release](/agents-api/templates#pin-a-template-version) — a tag on system templates (`agent37-hermes@2026.07.02b`), a revision number on workspace templates (`my-agent@2`) — pin when your creates must be reproducible; the bare name follows the latest release. Unknown names and unpublished versions return `400 invalid_request`. Direct image references are rejected with `400`: register a template first, then pass its name.
</ParamField>

<ParamField body="resources" type="object">
  The instance shape, for example `{ "cpu": 2, "memory": 4, "disk": 6 }`. Omitted, it uses the template's smallest shape: 1 vCPU / 3 GB on `agent37-hermes-small`, 2 vCPU / 4 GB on standard templates. `agent37-hermes-small` unlocks the sub-floor 1 vCPU / 3 GB shape; standard templates use one of the three shapes below. Free workspaces (before your first top-up) can use up to the 2 vCPU / 4 GB shape; the larger 4/8 and 8/16 shapes return `403 tier_limit` until you top up. Disk is any whole number of GB within the shape's range, and defaults to the range minimum when omitted. Any other combination returns `400 invalid_request` listing the valid shapes.
</ParamField>

<ParamField body="user" type="string">
  An opaque tag for your own attribution, typically your end user's id. Stored, never interpreted, echoed back on the instance object.
</ParamField>

<ParamField body="name" type="string">
  A label for the instance.
</ParamField>

<ParamField body="metadata" type="object">
  Your own key/value pairs. Stored, never interpreted.
</ParamField>

<ParamField body="budget" type="object">
  Caps on this instance's managed usage (managed LLM, Brave search, and Composio calls), in micros (millionths of a dollar): `monthly_cap_micros` resets each UTC month, `credit_micros` adds one-time headroom that persists until spent. Both default to `0`, so managed calls are refused until you raise one. These are ceilings, not money; spend still draws the workspace wallet. See [Budgets](/agents-api/budgets).
</ParamField>

<ParamField body="auto_sleep" type="boolean" default="false">
  Opt the instance into [auto-sleep](#auto-sleep): once no bytes have moved through its URLs for `idle_timeout_seconds`, it is checkpointed to `sleeping` and bills disk alone until a request wakes it. Its awake minutes bill at 4x the compute rate.
</ParamField>

<ParamField body="idle_timeout_seconds" type="integer" default="300">
  How long the instance must be idle before it sleeps, in seconds. An integer from `60` to `86400` (one minute to one day). Only meaningful with `auto_sleep: true`.
</ParamField>

<ParamField body="public_ports" type="object[]">
  Ports to expose at permanent unauthenticated URLs, each `{ port, prefix? }` — for webhooks and other callers that can't send a credential. See [Public ports](/agents-api/public-ports), or follow the end-to-end [Hermes webhook setup](/agents-api/hermes-webhooks) for port `8644`.
</ParamField>

### Shapes and pricing

| cpu | memory | disk     | Price at the default disk                         |
| --- | ------ | -------- | ------------------------------------------------- |
| 1   | 3 GB   | 6-20 GB  | \$3.44 per month (`agent37-hermes-small` only)    |
| 2   | 4 GB   | 6-20 GB  | \$4.94 per month (default for standard templates) |
| 4   | 8 GB   | 20-40 GB | \$10.60 per month                                 |
| 8   | 16 GB  | 40-80 GB | \$21.20 per month                                 |

Disk above the range minimum adds \$0.09 per GB per month. The monthly price is the rate; the wallet is metered per minute, and only for what the instance holds: running time bills the full rate, or 4x it for an [auto-sleep](#auto-sleep) instance, and stopped or sleeping time bills the disk alone. Deleting an instance settles its final minutes and billing ends. See [Billing](/agents-api/billing).

### Example

The `credit_micros` of `1000000` gives the instance \$1 of managed-spend headroom so its first chat works out of the box.

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.agent37.com/v1/instances \
    -H "Authorization: Bearer sk_live_..." \
    -H "Content-Type: application/json" \
    -d '{
      "template": "agent37-hermes",
      "user": "u_882",
      "budget": { "credit_micros": 1000000 }
    }'
  ```

  ```python python theme={null}
  import requests

  resp = requests.post(
      "https://api.agent37.com/v1/instances",
      headers={"Authorization": "Bearer sk_live_..."},
      json={
          "template": "agent37-hermes",
          "user": "u_882",
          "budget": {"credit_micros": 1000000},
      },
  )
  instance = resp.json()
  print(instance["id"], instance["status"])
  ```

  ```javascript node theme={null}
  const res = await fetch("https://api.agent37.com/v1/instances", {
    method: "POST",
    headers: {
      Authorization: "Bearer sk_live_...",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      template: "agent37-hermes",
      user: "u_882",
      budget: { credit_micros: 1000000 },
    }),
  });
  const instance = await res.json();
  ```

  ```json response theme={null}
  {
    "id": "ab12cd34ef",
    "status": "running",
    "status_reason": null,
    "template": "agent37-hermes",
    "template_revision": null,
    "image_ref": "ghcr.io/agent37-platform/hermes:2026.07.02b",
    "image_digest": "sha256:4f8d0d9e9f3b3a5a9f4488fb33274de9f7b7450c6cf6d3573e68fd231d7c8891",
    "resources": { "cpu": 2, "memory": 4, "disk": 6 },
    "url": "https://ab12cd34ef.agent37.app",
    "domain_urls": [],
    "public_ports": [],
    "user": "u_882",
    "name": null,
    "metadata": null,
    "auto_sleep": false,
    "idle_timeout_seconds": 300,
    "past_due": false,
    "created": 1781222400
  }
  ```
</CodeGroup>

## The instance object

<ResponseField name="id" type="string">
  A bare 10-character lowercase alphanumeric id, no prefix. It doubles as the DNS label in the instance's URL.
</ResponseField>

<ResponseField name="status" type="string">
  The lifecycle state. `running` means the instance's computer is up; poll `GET /v1/health` before the first message. See the [statuses table](#statuses) below.
</ResponseField>

<ResponseField name="status_reason" type="object | null">
  Why the most recent lifecycle operation failed, as `{ code, message, operation, at }`, or `null` when there is no failure reason. `at` is an epoch-second timestamp.
</ResponseField>

<ResponseField name="template" type="string">
  The template the instance was built from, including its [version pin](/agents-api/templates#pin-a-template-version) when it has one (`agent37-hermes@2026.07.02b`, `my-agent@2`).
</ResponseField>

<ResponseField name="template_revision" type="integer | null">
  The workspace template revision this instance has installed. Compare it with the template's current `revision` to detect an available update. It changes only when the instance is created or [updated](#update), and is `null` for system templates and for instances created before revisions existed (an update stamps it).
</ResponseField>

<ResponseField name="image_ref" type="string | null">
  The public source reference for a system template or registry-born workspace template. `null` for an image published by a [cloud build](/agents-api/templates#build-an-image-in-the-cloud). This never exposes Agent37's internal private-mirror path.
</ResponseField>

<ResponseField name="image_digest" type="string | null">
  The immutable `sha256:...` digest of the image the instance runs. Use this, not a mutable `image_ref` tag, as the exact image identity. `null` only on older instances that predate digest pinning.
</ResponseField>

<ResponseField name="resources" type="object">
  The shape: `cpu` (vCPUs), `memory` and `disk` (GB).
</ResponseField>

<ResponseField name="url" type="string">
  The bare instance URL, `https://{instanceId}.agent37.app`, where the agent's chat API lives (it routes to the template's `default_port`, `3737` unless declared otherwise). Every other port is reachable at `https://{instanceId}-{port}.agent37.app` — derivable, no declaration needed. Open any port in a browser with a [signed URL](/agents-api/urls#browser-access-with-signed-urls). See [Instance and preview URLs](/agents-api/urls).
</ResponseField>

<ResponseField name="domain_urls" type="string[]">
  The instance URL mirrored under each of your workspace's active [custom domains](/agents-api/domains); empty until a domain is active.
</ResponseField>

<ResponseField name="public_ports" type="object[]">
  The instance's [public ports](/agents-api/public-ports), each `{ port, url, domain_urls, prefix, created }` — permanent unauthenticated URLs, empty unless you created some.
</ResponseField>

<ResponseField name="user" type="string | null">
  Your attribution tag, echoed back.
</ResponseField>

<ResponseField name="name" type="string | null">
  Your label, echoed back.
</ResponseField>

<ResponseField name="metadata" type="object | null">
  Your key/value pairs, echoed back.
</ResponseField>

<ResponseField name="auto_sleep" type="boolean">
  Whether the instance sleeps on idle. Set at create or by `PATCH`. See [Auto-sleep](#auto-sleep).
</ResponseField>

<ResponseField name="idle_timeout_seconds" type="integer">
  How long the instance must be idle before it sleeps, in seconds. Defaults to `300`.
</ResponseField>

<ResponseField name="slept_at" type="integer | null">
  Present only while `status` is `sleeping` or `waking`: when the instance fell asleep, in epoch seconds (`null` for the second or so while the checkpoint is being written). Instances that have been asleep for a long stretch may take a few seconds to start instead of waking sub-second.
</ResponseField>

<ResponseField name="past_due" type="boolean">
  `true` when the workspace balance went negative and the instance was suspended. Top up to clear it; the next request to the instance's URL wakes it. See [Billing](/agents-api/billing#past-due-and-suspension).
</ResponseField>

<ResponseField name="created" type="integer">
  Creation time in epoch seconds.
</ResponseField>

## Endpoints

| Method   | Path                         | Returns                                                                |
| -------- | ---------------------------- | ---------------------------------------------------------------------- |
| `POST`   | `/v1/instances`              | `201` with the full instance object                                    |
| `GET`    | `/v1/instances`              | `200` `{ "data": [...] }`, newest first, each the full instance object |
| `GET`    | `/v1/instances/{id}`         | `200` with the full instance object                                    |
| `PATCH`  | `/v1/instances/{id}`         | `200` with the full instance object                                    |
| `DELETE` | `/v1/instances/{id}`         | `200` `{ "id": "...", "deleted": true }`                               |
| `POST`   | `/v1/instances/{id}/stop`    | `200` `{ id, status }` ack                                             |
| `POST`   | `/v1/instances/{id}/start`   | `200` `{ id, status }` ack                                             |
| `POST`   | `/v1/instances/{id}/restart` | `200` `{ id, status }` ack                                             |
| `POST`   | `/v1/instances/{id}/update`  | `200` `{ id, status, image_ref, image_digest, template_revision }` ack |
| `POST`   | `/v1/instances/{id}/resize`  | `200` `{ id, status, resources }` ack                                  |

## List, get, delete

`GET /v1/instances` returns `{ "data": [ ... ] }`, newest first, each element the full instance object. `GET /v1/instances/{id}` returns one. Unknown, deleted, or other-workspace ids uniformly return `404 not_found`.

`DELETE /v1/instances/{id}` returns `{ "id": "ab12cd34ef", "deleted": true }`. It acts once: a repeat delete returns `404`. Delete settles the final metered window and billing ends; nothing is ever prepaid, so there is nothing to refund.

```bash curl theme={null}
curl -X DELETE https://api.agent37.com/v1/instances/ab12cd34ef \
  -H "Authorization: Bearer sk_live_..."
# -> { "id": "ab12cd34ef", "deleted": true }
```

<Warning>
  Delete is destructive: the instance's files, memory, and sessions are gone. To pause work while keeping everything, `stop` it instead. A stopped instance bills its disk alone; delete is what ends billing entirely.
</Warning>

## Edit name, metadata, and auto-sleep

`PATCH /v1/instances/{id}` edits the instance's `name`, `user` tag, and `metadata` after creation, plus its [auto-sleep](#auto-sleep) settings. These are the same fields you can set at create, and they are the only things this call changes: it never touches the running container. It returns `200` with the full instance object, the same shape as `GET`.

The patch is partial: only the keys you send change, the rest are left alone. Send a string to set a label field, or `null` (or `""`) to clear it. You must send at least one of `name`, `user`, `metadata`, `auto_sleep`, or `idle_timeout_seconds`; an empty body returns `400 invalid_request`.

<ParamField body="name" type="string | null">
  A label for the instance, up to 60 characters. `null` or `""` clears it.
</ParamField>

<ParamField body="user" type="string | null">
  Your attribution tag, up to 200 characters. `null` or `""` clears it.
</ParamField>

<ParamField body="metadata" type="object | null">
  Your key/value pairs, up to 4 KB serialized. The object replaces the stored one, it is not merged. `null` or `{}` clears it.
</ParamField>

<ParamField body="auto_sleep" type="boolean">
  Turn [auto-sleep](#auto-sleep) on or off. Takes effect within about half a minute, with no restart and no recreate.
</ParamField>

<ParamField body="idle_timeout_seconds" type="integer">
  The new idle timeout: an integer from `60` to `86400` seconds.
</ParamField>

Edits never bill and never recreate the container, and they work in any state except `deleted`. Unknown, deleted, or other-workspace ids return `404 not_found`.

<CodeGroup>
  ```bash curl theme={null}
  curl -X PATCH https://api.agent37.com/v1/instances/ab12cd34ef \
    -H "Authorization: Bearer sk_live_..." \
    -H "Content-Type: application/json" \
    -d '{ "name": "Production agent", "user": "u_882", "metadata": { "plan": "pro" } }'
  ```

  ```python python theme={null}
  import requests

  resp = requests.patch(
      "https://api.agent37.com/v1/instances/ab12cd34ef",
      headers={"Authorization": "Bearer sk_live_..."},
      json={"name": "Production agent", "user": "u_882", "metadata": {"plan": "pro"}},
  )
  instance = resp.json()
  ```

  ```javascript node theme={null}
  const res = await fetch("https://api.agent37.com/v1/instances/ab12cd34ef", {
    method: "PATCH",
    headers: {
      Authorization: "Bearer sk_live_...",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      name: "Production agent",
      user: "u_882",
      metadata: { plan: "pro" },
    }),
  });
  const instance = await res.json();
  ```

  ```json response theme={null}
  {
    "id": "ab12cd34ef",
    "status": "running",
    "status_reason": null,
    "template": "agent37-hermes",
    "template_revision": null,
    "image_ref": "ghcr.io/agent37-platform/hermes:2026.07.02b",
    "image_digest": "sha256:4f8d0d9e9f3b3a5a9f4488fb33274de9f7b7450c6cf6d3573e68fd231d7c8891",
    "resources": { "cpu": 2, "memory": 4, "disk": 6 },
    "url": "https://ab12cd34ef.agent37.app",
    "domain_urls": [],
    "public_ports": [],
    "user": "u_882",
    "name": "Production agent",
    "metadata": { "plan": "pro" },
    "auto_sleep": false,
    "idle_timeout_seconds": 300,
    "past_due": false,
    "created": 1781222400
  }
  ```
</CodeGroup>

## Lifecycle

Five calls control whether the instance's computer is running, which image it runs, and how big it is. Each is a `POST` to a subpath; `stop`, `start`, and `restart` take no body, `update` takes an optional `template` version, and `resize` takes the new size. They acknowledge the new state only, returning `{ id, status }` (`update` adds nullable `image_ref`, `image_digest`, and `template_revision`; `resize` adds `resources`); `GET` the instance for its full representation.

The whole disk persists, like a VM. Files anywhere on the filesystem, installed packages, edited config, connected accounts: all of it survives `stop`, `start`, `restart`, and `resize`, and rides along if the platform ever moves the instance between hosts. The one exception is `update`, which resets the operating system layer to the fresh image while keeping your data (`/home/node` and `/home/linuxbrew`). Writes outside those two directories share a 10 GB operating-system layer separate from the instance's billed disk. In-memory state is lost whenever the container is recreated; anything that must outlive a restart belongs in a file.

### Stop

`POST /v1/instances/{id}/stop` halts the container. The agent stops doing work (no cron, no heartbeats, no responses) and `status` becomes `stopped`. The data stays intact, CPU and memory are released back to the host, and the disk stays reserved on that host.

Stop also works on a `sleeping` instance, and the difference is intent: a sleeper wakes on any request, a stopped instance stays down until an explicit `start`. Stopping a sleeper discards its checkpoint (the data stays) and its URLs stop waking it. The one exception is the second or so while the sleep checkpoint is being written: stop then returns `409 try_again`, and you retry in a few seconds.

Stopping an already stopped instance returns the same ack again; any other state returns `400`.

```bash curl theme={null}
curl -X POST https://api.agent37.com/v1/instances/ab12cd34ef/stop \
  -H "Authorization: Bearer sk_live_..."
# -> { "id": "ab12cd34ef", "status": "stopped" }
```

### Start

`POST /v1/instances/{id}/start` brings a `stopped` instance back up, recreating the container from the image it already ran. It normally returns to its host in seconds; if that host no longer has room for the instance's CPU and memory, the platform moves the instance to one that does, and the start takes a couple of minutes while the data syncs over. Only when no host has room does it return `409 capacity_unavailable`, changing nothing. If the instance is `past_due` (suspended for non-payment), start returns `402 insufficient_balance` until the workspace is funded; topping up clears the flag on its own, and start (or any request to the instance's URLs) then boots it fresh. Starting an already running instance returns the same ack again.

Start also wakes a `sleeping` instance, with the same effect as a request to one of its URLs. For a [private sandbox with no ports](/agents-api/templates#register-a-workspace-template) there is no URL to request, so start is its only wake path. During the brief window while the sleep checkpoint is being written it returns `409 try_again`; retry in a few seconds.

```bash curl theme={null}
curl -X POST https://api.agent37.com/v1/instances/ab12cd34ef/start \
  -H "Authorization: Bearer sk_live_..."
# -> { "id": "ab12cd34ef", "status": "running" }
```

### Restart

`POST /v1/instances/{id}/restart` recreates the container from the image already on the host (no download) and returns it to `running`. Use it to recover a wedged agent or pick up changed settings. Same image, same data. The instance must be `running`; use `start` to bring a `stopped` one back up. Concurrent restarts of the same instance do not stack: one proceeds and the rest return `409 try_again`.

```bash curl theme={null}
curl -X POST https://api.agent37.com/v1/instances/ab12cd34ef/restart \
  -H "Authorization: Bearer sk_live_..."
# -> { "id": "ab12cd34ef", "status": "running" }
```

### Update

`POST /v1/instances/{id}/update` pulls the template's image, resets the operating system layer to it, and preserves the data in `/home/node` and `/home/linuxbrew`. It is the one lifecycle call that discards changes outside those directories, which also makes it the clean-slate repair tool: use it to move an instance onto a newer version after a release (or after you point a workspace template at a new tag), or to recover a failed/stuck instance (read its [logs](/agents-api/logs) first to see why it failed). A `running` or recoverable non-stopped instance is recreated and returns `running`; a `stopped` instance pulls the image pointer now and stays `stopped`, then uses that image the next time it starts.

The body is optional. Without one, update re-resolves the instance's stored template: a workspace instance installs the template's current image and `revision`, an unpinned system instance moves to the template's current image, and a [version-pinned](/agents-api/templates#pin-a-template-version) instance stays on its pin. The one accepted field, `template`, takes any template name: the same template with an `@<version>` — a published tag on a system template, a published revision number on a workspace template — pins that release (this works on an unpinned instance too, and pinning an earlier workspace revision is the rollback), the bare name clears the pin to follow latest, and a *different* template migrates the instance onto it. A template migration keeps the instance's id, URLs, public ports, and data, and the recreated container adopts the new template's image, default port, and agent type. It returns `400` if the instance's current size isn't offered by the target template (the 1 vCPU / 3 GB shape exists only on templates that support it, like `agent37-hermes-small`). Any other field returns `400`. The ack carries the resulting `status`, the applied `template` when one was passed, `image_ref`, `image_digest`, and `template_revision`. A `sleeping` instance cannot be updated: wake it first, with any request to its URL or an explicit [`start`](#start). A bad image reference on the template surfaces here as a `502 provisioning_failed`.

```bash curl theme={null}
curl -X POST https://api.agent37.com/v1/instances/ab12cd34ef/update \
  -H "Authorization: Bearer sk_live_..."
# -> { "id": "ab12cd34ef", "status": "running", "image_ref": "ghcr.io/acme/my-agent:v2", "image_digest": "sha256:9b2e...c41f", "template_revision": 2 }

# Set or move a version pin (or pass the bare name to clear it) — a system tag,
# or a workspace revision like '{ "template": "my-agent@1" }' to roll back:
curl -X POST https://api.agent37.com/v1/instances/ab12cd34ef/update \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "template": "agent37-hermes@<tag>" }'

# Migrate the instance onto a different template (data kept, container recreated from the new image):
curl -X POST https://api.agent37.com/v1/instances/ab12cd34ef/update \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "template": "my-custom-agent" }'
# -> { "id": "ab12cd34ef", "status": "running", "template": "my-custom-agent", "image_ref": "ghcr.io/acme/my-agent:v2", "image_digest": "sha256:9b2e...c41f", "template_revision": 1 }
```

### Resize

`POST /v1/instances/{id}/resize` grows a running instance to a bigger size. The body uses the same vocabulary as create's `resources`, and omitted fields keep their current value, so `{ "disk": 15 }` grows disk alone and `{ "cpu": 4, "memory": 8 }` moves up a shape (disk rises to the new shape's minimum if it was below it). Resize only grows: any request that would shrink a dimension returns `400`, and moving to a smaller size means creating a new instance. The ack carries the new `resources`, and the meter bills at the new rate from the moment of the resize (see [Billing](/agents-api/billing)).

The container is recreated with the new limits, like `restart`: the disk, instance id, and URLs are kept, in-memory state is lost, and the instance is back in seconds. If its current host cannot fit the increase, the platform moves the instance to one that can; the resize then takes a couple of minutes while the data syncs over. Only when no host has room does it return `409 capacity_unavailable`, changing nothing.

```bash curl theme={null}
curl -X POST https://api.agent37.com/v1/instances/ab12cd34ef/resize \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "cpu": 4, "memory": 8 }'
# -> { "id": "ab12cd34ef", "status": "running", "resources": { "cpu": 4, "memory": 8, "disk": 20 } }
```

## Auto-sleep

An instance with `auto_sleep: true` does not have to be up to be available. Once no bytes have moved through any of its URLs for `idle_timeout_seconds` (default 300, from one minute to a day), the platform checkpoints it and `status` becomes `sleeping`: CPU and memory are released, the disk stays reserved, and billing drops to the disk rate alone (see [Billing](/agents-api/billing)). Activity is data flow in either direction on any of the instance's URLs; a connection that is open but silent does not count, and API reads like `GET /v1/instances/{id}` never reset the timer.

The wake guarantee is priced in: an auto-sleep instance bills its awake minutes at 4x the compute rate, because the platform keeps capacity for it wakeable on demand instead of sharing it. A mostly-idle instance still comes out well below the always-on price: a 2 vCPU / 4 GB instance awake an hour a day costs about \$1.34 per month, versus \$4.94 always-on.

Waking is transparent. Any request to any of the instance's URLs wakes it: the request is held while the instance restores, then forwarded, usually well under a second. So does an explicit [`POST /v1/instances/{id}/start`](#start) — for a private sandbox with no ports, which receives no requests, that is the only wake path. If the checkpoint cannot be restored, or the instance was moved to cold storage after a long idle stretch, the wake falls back to a fresh boot and takes a few seconds instead. In-memory state usually survives a wake, but it is not guaranteed: treat anything that must outlive a sleep as a file.

While asleep:

* The instance object reports `status: "sleeping"` and `slept_at`, for example `"slept_at": 1781222400`.
* [Signed URLs](/agents-api/urls#browser-access-with-signed-urls) can still be minted, and opening one is exactly the kind of request that wakes the instance.
* `stop` works, and means "stay down until I `start`" (see [Stop](#stop)). During the brief window while the checkpoint is being written it returns `409 try_again`; retry in a few seconds.
* `restart`, `update`, and `resize` require `running` and return `400`: wake the instance first, with any request to its URL or an explicit [`start`](#start).

Both fields are set at create and editable any time with `PATCH /v1/instances/{id}`, no restart needed. Instances default to `auto_sleep: false` and never sleep unless you opt them in.

## Statuses

| Status         | Meaning                                                                                                                       |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `provisioning` | Being created. You only observe this if a create is in flight.                                                                |
| `running`      | Up. Poll `GET /v1/health` before the first message.                                                                           |
| `stopping`     | A stop is in progress.                                                                                                        |
| `stopped`      | Halted until an explicit `start`. Data intact, disk reserved, compute released. Bills disk only.                              |
| `starting`     | A start is in progress.                                                                                                       |
| `restarting`   | A restart is in progress.                                                                                                     |
| `updating`     | An update or resize is in progress.                                                                                           |
| `sleeping`     | Checkpointed on idle ([auto-sleep](#auto-sleep)). Any request to its URLs, or an explicit `start`, wakes it. Bills disk only. |
| `waking`       | A wake is in progress on the slower fallback path; the held request completes when it finishes.                               |
| `failed`       | A create or lifecycle action failed.                                                                                          |
| `deleting`     | A delete is in progress.                                                                                                      |
| `deleted`      | Gone. The id reads as `404` from here on.                                                                                     |

<Note>
  `past_due` is a flag, not a status: a suspended instance shows it alongside `sleeping` (or `stopped`, if it already was). Top up the wallet to clear it; see [Billing](/agents-api/billing#past-due-and-suspension).
</Note>

## Capacity and limit errors

| Error                        | When                                                                                                                                                                                                           |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `402 insufficient_balance`   | Create when the wallet holds less than one day of the instance's running rate, or start of a past-due instance while the balance is negative.                                                                  |
| `409 instance_limit_reached` | Create when the workspace is at its instance cap: one instance on the free credit, 10 once topped up, 50 once top-ups total \$500 (email [vishnu@agent37.com](mailto:vishnu@agent37.com) to raise it further). |
| `403 tier_limit`             | Create or resize asks for a shape larger than your plan includes. Free workspaces run any template up to the 2 vCPU / 4 GB shape; a top-up unlocks the 4/8 and 8/16 shapes.                                    |
| `503 no_capacity`            | Create when no host has capacity for the requested shape right now.                                                                                                                                            |
| `409 capacity_unavailable`   | Start or resize when no host in the fleet can fit the instance right now; the platform first tries to move it to a host with room.                                                                             |

See [Errors](/agents-api/errors) for the full catalog and the error envelope.
