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

# Operations, pricing, and errors

> Build reliable automation around asynchronous mutations, quote expiry, retries, and capacity refusals.

Every infrastructure mutation returns `202 Accepted` with an operation ID and
resource ID. The mutation has been durably accepted; the resource is not
necessarily ready yet.

Acceptance is a promise, not a receipt. A create has exactly three outcomes:

| Outcome | What you get | Whose action |
| - | - | - |
| Refused synchronously | `4xx`/`5xx` with an error code; **no resource id, nothing exists, nothing bills** | Named by the error code (see below) |
| Accepted | `202` with a resource id the provider will honor; poll the operation | Yours to wait on |
| Failed after acceptance | operation `failed` with `errorMessage` and a structured `failure` | `failure.actor` says who |

Before accepting, AI Reserve checks what it can know up front: your wallet,
your Compute limits, placement, **and its own standing with the infrastructure
provider**. A request the provider is certain to refuse for a reason that is
AI Reserve's — not yours — is answered `503 provider_unavailable` with
`details.actor: "platform"` and a `details.reference` to quote to support,
instead of a `202` that could only fail. Nothing of yours needs to change;
retry later with the same `Idempotency-Key`.

## Wait for completion

```bash theme={"dark"}
aireserve gpu operations get <operation-id>

aireserve gpu operations wait <operation-id> --timeout-sec 600
```

Terminal statuses are `succeeded`, `failed`, and `cancelled`. Save the operation
ID when your process may restart. Intermediate reconciliation details are not a
stable API contract; key automation off operation status and the final resource.

A terminal `failed` or `cancelled` operation carries `failure`, a structured
reading of `errorMessage` so you never parse `provider_rejected:<code>` by hand:

```json theme={"dark"}
{
  "status": "failed",
  "errorMessage": "provider_rejected:no_capacity",
  "failure": {
    "code": "provider_rejected:no_capacity",
    "actor": "provider",
    "message": "The infrastructure provider could not place the request: no capacity for this shape right now. Nothing was created.",
    "next": "Request a fresh quote, perhaps for another region or shape."
  }
}
```

| `failure.actor` | Meaning | What to do |
| - | - | - |
| `customer` | The request itself was refused (an image tag that does not exist, an invalid field) | Fix it and launch again with a new key |
| `provider` | Nothing to fix; the provider could not serve the shape right now | Re-quote, perhaps another region or shape |
| `platform` | AI Reserve's own standing or credentials with the provider; nothing about your request is wrong | Retry later, or contact support with the operation id |

Nothing is billed for a failed create in any of the three cases.

## Retry safely with idempotency

The CLI derives an idempotency key for instance launch and creates keys for
other mutations. For direct REST calls, send your own unique key:

```http theme={"dark"}
Idempotency-Key: instance-launch-01J...
```

* Reusing a key with the same accepted request returns the original receipt.
* Reusing it with a different request fails with `operation_conflict`.
* Two intentional launches require two different keys.
* Inline persistent storage and the instance are recorded under one key, so a
  transport retry cannot create an extra volume.

Keep the same key across network retries. Do not derive a new key after an
ambiguous timeout.

## Quote semantics

`POST /v1/gpu/instances/quote` creates and charges nothing. It records the
configuration and price selected at that moment and expires after 120 seconds.
A quote is not a capacity reservation.

At launch, AI Reserve rechecks the price and current resource state:

* `price_changed`: request a fresh quote;
* `quote_expired`: request a fresh quote;
* `volume_in_use`: wait for the current attachment to terminate;
* provider capacity may still disappear before provisioning completes.

Launching from a refreshed quote is a new CLI intent unless you explicitly
reuse the original `--idempotency-key` for the same ambiguous launch attempt.

## Common errors

| Error code | Meaning | What to do |
| - | - | - |
| `no_capacity` | The request cannot be placed; `details.reason` explains why | Follow the reason and alternatives below |
| `volume_in_use` | The volume is not ready or remains attached | Terminate the attached instance and wait, or choose another volume |
| `price_changed` | Current price differs from the quoted price or a priced field was changed | Request a new quote |
| `quote_expired` | The quote is expired or malformed | Request a new quote |
| `insufficient_funds` | The organization wallet cannot cover the new exposure | Fund or enable the wallet |
| `quota_exceeded` | The request exceeds Compute limits | Reduce the request or ask an admin to adjust limits |
| `operation_conflict` | Another mutation is active or an idempotency key conflicts | Wait, or use a new key for a new intent |
| `compute_access_required` | The API key lacks Compute Manage access | Update or replace the key |
| `provider_unavailable` | The infrastructure control plane is unavailable, or AI Reserve's provider account cannot take the order (`details.actor: "platform"`) | Retry later with the same idempotency key; quote `details.reference` to support if it persists |

## `no_capacity` reasons

A `409 no_capacity` response does not name a provider or data center. It carries
customer-actionable details:

| `details.reason` | Meaning | What to change |
| - | - | - |
| `price_ceiling` | Eligible capacity exists above the ceiling | Raise to at least `cheapestEligibleUsdPerHour` |
| `volume_location` | An existing volume pins placement where no eligible capacity fits | Raise the ceiling, or request new storage in an alternative region |
| `no_persistent_storage` | Matching GPU capacity cannot create the requested persistent storage | Use ephemeral storage or another region |
| `no_stock` | No matching accelerator/count is currently for sale | Change region, accelerator, or count and quote again |

```json theme={"dark"}
{
  "error": {
    "code": "no_capacity",
    "message": "No 1 x H100_80GB capacity can mount this volume within $3.00/hr.",
    "details": {
      "reason": "volume_location",
      "volumeRegion": "europe",
      "cheapestEligibleUsdPerHour": "3.420000",
      "alternatives": [
        {
          "region": "united_states",
          "totalRunningUsdPerHour": "2.890000"
        }
      ]
    }
  }
}
```

The CLI prints the reason, the cheapest eligible rate when known, and a suggested
next command. The current standalone SDKs expose generic API errors and do not
retain structured capacity details; inspect the REST error envelope when you
need the full refusal payload.

## Clusters: refusals after acceptance

A cluster quote reports stock for one node of the requested shape. Whether
every node can be placed together on one interconnect is known only when the
provider creates the cluster, so a `202 Accepted` launch can still end with
the operation `failed` and `errorMessage` `provider_rejected:no_capacity`.
Nothing is billed; request a fresh quote. Cluster operations are
`cluster_create` and `cluster_terminate`; there is no stop.

## Understand the price ceiling

For a direct launch, `maxHourlyPrice` bounds the new running commitment:

```text theme={"dark"}
GPU + ephemeral root disk + persistent storage created by this request
```

An existing volume is already billing independently. Its rate appears in the
quote but does not count against the new-compute ceiling.

## Billing timeline

* Compute accrues from confirmed readiness through confirmed stop or
  termination; final partial intervals are prorated.
* A stopped instance does not accrue GPU compute.
* A persistent volume accrues from volume creation until successful deletion.
* Inline storage can begin billing before its instance reaches `running` because
  the volume is provisioned first.

Review charge history with:

```bash theme={"dark"}
aireserve gpu usage
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.