# PATCH /api/v1/hosts/machines/{id}/offer

Edit the listing by publishing the next offer version (host owner)

Operation: `editOffer`.

Edit the listing by publishing the next offer version (host owner)

The host console's listing editor. Despite the verb this is APPEND-ONLY: the next `version` is inserted and no existing row is ever rewritten, so a live job keeps the rate its quote snapshotted — the quote remains the only price authority. `expected_version` is compare-and-swapped against the CURRENT offer version (not the machine version the POST form uses); a race answers 409 with `error.code = VERSION_CONFLICT` and a sibling `current` block so the editor can show what changed instead of overwriting it. `listing_expires_at` has no column of its own and is FOLDED onto `available_until` (the earlier of the two wins — `available_until` already means "bookable until", which is what the catalog filters on); the response echoes the stored value. `min_duration_s` and `max_duration_s` are accepted but NOT stored, because no per-offer duration bound exists in the schema and nothing at quote time would enforce one; they are named back to the caller in `ignored_fields` rather than silently dropped. A publish that would retract availability a live job is already holding is refused 409 CONFLICT.

## Endpoint

`PATCH https://amplerun-api.spiry.org/api/v1/hosts/machines/{id}/offer`

## 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 |
| --- | --- | --- | --- | --- |
| `id` | path | Required | UUID |  |
| `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 |
| --- | --- | --- | --- |
| `expected_version` | DecimalString | Required |  |
| `rate_micro_per_hour` | MicroAmount | Required |  |
| `included_disk_gib` | integer | Required |  |
| `included_egress_gib` | integer | Required |  |
| `available_from` | Rfc3339Utc | Required |  |
| `available_until` | Rfc3339Utc | Required |  |
| `listing_expires_at` | Rfc3339Utc | Optional |  |
| `min_duration_s` | integer | Optional | Accepted, never stored; reported in ignored_fields. |
| `max_duration_s` | integer | Optional | Accepted, never stored; reported in ignored_fields. |
| `availability_class` | AvailabilityClass | Optional | D-22. Omitted keeps the current version's class. interruptible needs preemption_notice_s; an idle or co-listed host can rent only interruptible offers. 409 until the D-22 migration is released. |
| `preemption_notice_s` | integer | Optional | D-22. Required for interruptible, refused for dedicated; omitted keeps the current value. |

```json
{
  "type": "object",
  "additionalProperties": false,
  "required": [
    "expected_version",
    "rate_micro_per_hour",
    "included_disk_gib",
    "included_egress_gib",
    "available_from",
    "available_until"
  ],
  "properties": {
    "expected_version": {
      "$ref": "#/components/schemas/DecimalString"
    },
    "rate_micro_per_hour": {
      "$ref": "#/components/schemas/MicroAmount"
    },
    "included_disk_gib": {
      "type": "integer",
      "minimum": 0
    },
    "included_egress_gib": {
      "type": "integer",
      "minimum": 0
    },
    "available_from": {
      "$ref": "#/components/schemas/Rfc3339Utc"
    },
    "available_until": {
      "$ref": "#/components/schemas/Rfc3339Utc"
    },
    "listing_expires_at": {
      "$ref": "#/components/schemas/Rfc3339Utc"
    },
    "min_duration_s": {
      "type": "integer",
      "minimum": 0,
      "description": "Accepted, never stored; reported in ignored_fields."
    },
    "max_duration_s": {
      "type": "integer",
      "minimum": 0,
      "description": "Accepted, never stored; reported in ignored_fields."
    },
    "availability_class": {
      "$ref": "#/components/schemas/AvailabilityClass",
      "description": "D-22. Omitted keeps the current version's class. interruptible needs preemption_notice_s; an idle or co-listed host can rent only interruptible offers. 409 until the D-22 migration is released."
    },
    "preemption_notice_s": {
      "type": "integer",
      "minimum": 0,
      "maximum": 3600,
      "description": "D-22. Required for interruptible, refused for dedicated; omitted keeps the current value."
    }
  }
}
```

## Responses

### `202`

Next offer version published.

`application/json`
| Field | Type | Presence | Description |
| --- | --- | --- | --- |
| `offer_id` | UUID | Required |  |
| `offer_version` | DecimalString | Required |  |
| `state` | "listed" / "unlisted" / "draining" | Required |  |
| `rate_micro_per_hour` | MicroAmount | Required |  |
| `included_disk_gib` | integer | Required |  |
| `included_egress_gib` | integer | Required |  |
| `available_from` | Rfc3339Utc | Required |  |
| `available_until` | Rfc3339Utc | Required |  |
| `availability_class` | AvailabilityClass | Optional |  |
| `preemption_notice_s` | integer or null | Optional |  |
| `ignored_fields` | array of string | Required | Request fields accepted by the schema but deliberately not stored. |

```json
{
  "type": "object",
  "additionalProperties": false,
  "required": [
    "offer_id",
    "offer_version",
    "state",
    "rate_micro_per_hour",
    "included_disk_gib",
    "included_egress_gib",
    "available_from",
    "available_until",
    "ignored_fields"
  ],
  "properties": {
    "offer_id": {
      "$ref": "#/components/schemas/UUID"
    },
    "offer_version": {
      "$ref": "#/components/schemas/DecimalString"
    },
    "state": {
      "type": "string",
      "enum": [
        "listed",
        "unlisted",
        "draining"
      ]
    },
    "rate_micro_per_hour": {
      "$ref": "#/components/schemas/MicroAmount"
    },
    "included_disk_gib": {
      "type": "integer",
      "minimum": 0
    },
    "included_egress_gib": {
      "type": "integer",
      "minimum": 0
    },
    "available_from": {
      "$ref": "#/components/schemas/Rfc3339Utc"
    },
    "available_until": {
      "$ref": "#/components/schemas/Rfc3339Utc"
    },
    "availability_class": {
      "$ref": "#/components/schemas/AvailabilityClass"
    },
    "preemption_notice_s": {
      "anyOf": [
        {
          "type": "integer",
          "minimum": 0,
          "maximum": 3600
        },
        {
          "type": "null"
        }
      ]
    },
    "ignored_fields": {
      "type": "array",
      "description": "Request fields accepted by the schema but deliberately not stored.",
      "items": {
        "type": "string"
      }
    }
  }
}
```

### `409`

Offer version race (`VERSION_CONFLICT`, with `current`) or a live job whose availability the change would retract (`CONFLICT`).

`application/json`
| Field | Type | Presence | Description |
| --- | --- | --- | --- |
| `error` | object | Required |  |
| `current` | object | Optional | Present only for VERSION_CONFLICT — the listing as it now stands. |

```json
{
  "type": "object",
  "required": [
    "error"
  ],
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "message",
        "retryable",
        "request_id"
      ],
      "properties": {
        "code": {
          "type": "string",
          "enum": [
            "VERSION_CONFLICT",
            "CONFLICT",
            "IDEMPOTENCY_CONFLICT"
          ]
        },
        "message": {
          "type": "string"
        },
        "retryable": {
          "type": "boolean"
        },
        "request_id": {
          "$ref": "#/components/schemas/UUID"
        }
      }
    },
    "current": {
      "type": "object",
      "description": "Present only for VERSION_CONFLICT — the listing as it now stands.",
      "additionalProperties": false,
      "required": [
        "offer_version",
        "rate_micro_per_hour",
        "available_until"
      ],
      "properties": {
        "offer_version": {
          "$ref": "#/components/schemas/DecimalString"
        },
        "rate_micro_per_hour": {
          "$ref": "#/components/schemas/MicroAmount"
        },
        "available_until": {
          "$ref": "#/components/schemas/Rfc3339Utc"
        }
      }
    }
  }
}
```

### `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 PATCH 'https://amplerun-api.spiry.org/api/v1/hosts/machines/{id}/offer' \
  --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/edit-offer/
