# POST /api/v1/quotes

Create immutable quote (verified renter)

Operation: `createQuote`.

Create immutable quote (verified renter)

Returns an immutable quote with 60s expiry, terms version, machine manifest hash and total rate. Refresh stale catalog quotes before charging. Quoting is free and holds nothing; POST /api/v1/jobs reserves. The Idempotency-Key is not deduplicated on this route, so a retry returns a fresh quote. 409 CONFLICT when the offer's machine is not admitted: an unverified listing (OfferSummary admitted false) is shown but cannot be quoted or reserved until it passes qualification.

## Endpoint

`POST https://amplerun-api.spiry.org/api/v1/quotes`

## Authentication

Use the credential and scope required by this operation. For programmatic renter/host calls: `Authorization: Bearer $AMPLERUN_API_KEY`. A host-agent signature or other specialized proof is required where the description specifies it.

## Parameters

| Name | Location | Presence | Type | Description |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | Required | UUID | UUID scoped to authenticated principal, route and canonical request hash. |

## Request body

Required body. 

### `application/json`

| Field | Type | Presence | Description |
| --- | --- | --- | --- |
| `offer_id` | UUID | Required |  |
| `image_digest` | ImageDigest | Optional | A published template's image, or a custom public image pinned by digest. |
| `image_ref` | string | Optional | Custom public image by tag or digest ([registry/]repository[:tag][@sha256:...]); the server pins it to a digest at quote time. |
| `duration_limit_s` | integer | Required | Maximum runtime in seconds, metered from verified readiness. |
| `budget_micro` | MicroAmount | Required | Spending cap: the job is never charged more than this. |
| `template_id` | UUID | Optional | D-19(c): published template; the server sets image_digest from it and the offer must fit, else 422. Mutually exclusive with image_digest. The template's `id` (UUID), not its slug. |
| `asset` | "USDC" / "USDT" | Optional | Additive. Settlement asset whose balance the reservation holds; unknown values are 422. |

```json
{
  "type": "object",
  "additionalProperties": false,
  "required": [
    "offer_id",
    "duration_limit_s",
    "budget_micro"
  ],
  "description": "Exactly one of template_id, image_digest or image_ref (422 otherwise). With template_id the server resolves the published template's pinned image_digest and requires the offer to fit (422). An image_ref, or an image_digest no published template pins, is a custom image: it is accepted only while the marketplace enables custom images (422 otherwise), is resolved anonymously against an allowed public registry (docker.io, ghcr.io, quay.io, nvcr.io, public.ecr.aws) and quoted by its digest (422 when private, missing, not linux/amd64 or over the size cap), and only on a machine whose host opted in (422).",
  "properties": {
    "offer_id": {
      "$ref": "#/components/schemas/UUID"
    },
    "image_digest": {
      "$ref": "#/components/schemas/ImageDigest",
      "description": "A published template's image, or a custom public image pinned by digest."
    },
    "image_ref": {
      "type": "string",
      "minLength": 1,
      "maxLength": 255,
      "description": "Custom public image by tag or digest ([registry/]repository[:tag][@sha256:...]); the server pins it to a digest at quote time."
    },
    "duration_limit_s": {
      "type": "integer",
      "minimum": 1,
      "description": "Maximum runtime in seconds, metered from verified readiness."
    },
    "budget_micro": {
      "$ref": "#/components/schemas/MicroAmount",
      "description": "Spending cap: the job is never charged more than this."
    },
    "template_id": {
      "$ref": "#/components/schemas/UUID",
      "description": "D-19(c): published template; the server sets image_digest from it and the offer must fit, else 422. Mutually exclusive with image_digest. The template's `id` (UUID), not its slug."
    },
    "asset": {
      "enum": [
        "USDC",
        "USDT"
      ],
      "default": "USDC",
      "description": "Additive. Settlement asset whose balance the reservation holds; unknown values are 422."
    }
  }
}
```

Contract example:

```json
{
  "offer_id": "8b0c2f4e-1d3a-4c5b-9e6f-7a8b9c0d1e2f",
  "template_id": "a35d15fe-ab57-4283-87f8-a00528d1d631",
  "duration_limit_s": 7200,
  "budget_micro": "1000000"
}
```

## Responses

### `201`

Immutable quote.

`application/json`
| Field | Type | Presence | Description |
| --- | --- | --- | --- |
| `quote_id` | UUID | Required |  |
| `expires_at` | Rfc3339Utc | Required | Quotes expire after 60 seconds. |
| `machine_id` | UUID | Required |  |
| `gpu_count` | integer | Required |  |
| `machine_rate_micro_per_hour` | MicroAmount | Required |  |
| `platform_fee_bps` | integer | Required |  |
| `budget_micro` | MicroAmount | Required |  |
| `duration_limit_s` | integer | Required |  |
| `included_disk_gib` | integer | Optional |  |
| `included_egress_gib` | integer | Optional |  |
| `manifest_hash` | Sha256Hash | Required |  |
| `image_digest` | ImageDigest | Required |  |
| `terms_version` | string | Required |  |
| `meter_start` | schema | Required |  |
| `template_id` | UUID | Optional | D-19(c): echoed when the quote was created for a template. |
| `image_ref` | string | Optional | Echoed when the request named a custom image by image_ref; image_digest is what it was pinned to. |
| `estimated_total_micro` | MicroAmount | Optional | D-19(c): floor(total_rate_micro_per_hour * duration_limit_s / 3600), fee included; informational — the quote's budget_micro remains the only price authority. |
| `asset` | "USDC" / "USDT" | Optional | Additive. Settlement asset whose balance the reservation holds; USDC unless the request chose USDT. |
| `availability_class` | AvailabilityClass | Optional |  |
| `preemption_notice_s` | integer or null | Optional | D-22. Notice in seconds before an interruptible rental is stopped; null for dedicated. |
| `interruption_estimate` | InterruptionEstimate or null | Optional | D-22. For an interruptible quote, computed with horizon_h = the quoted duration rounded up to whole hours; null for dedicated. |

```json
{
  "$ref": "#/components/schemas/Quote"
}
```

### `default`

Error envelope. 401 unauthenticated, 403/404 forbidden, 409 conflict, 422 invalid input, 429 rate limited (code UNAVAILABLE, retryable:true, no Retry-After header), 503 unavailable money/provider state with retryable:true.

`application/json`
| Field | Type | Presence | Description |
| --- | --- | --- | --- |
| `error` | object | Required |  |

```json
{
  "$ref": "#/components/schemas/ErrorEnvelope"
}
```

## Static request outline

Replace path/query placeholders and provide the required JSON body, headers and credential from the sections above. This is a request outline, not a command that chooses an amount or starts a rental for you.

```sh
curl --request POST 'https://amplerun-api.spiry.org/api/v1/quotes' \
  --header "Authorization: Bearer $AMPLERUN_API_KEY"
```

[Schema definitions](https://docs.amplerun.com/reference/schemas.md) · [Download OpenAPI](/openapi.json) · [Authentication](https://docs.amplerun.com/agents/authentication.md) · [Errors and recovery](https://docs.amplerun.com/reference/errors.md)

---
Generated from the AmpleRun API contract.
Canonical: https://docs.amplerun.com/reference/api/create-quote/
