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

# Orders

> Place orders, list / fetch them, cancel before acquisition.

## POST /v1/orders — Place order

**This is a bid commitment, not a payment.** No deposit. By POSTing, the partner takes commercial responsibility to pay LMN if (and only if) the order reaches `secured`. Money flow is described in [Conventions](/conventions).

```bash theme={null}
curl -X POST \
  -H "x-api-key: $KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"vehicle_id": "01HXYZ...", "max_bid_amount_usd": 15500}' \
  https://api.lmnauto.com/v1/orders
```

| Header            | Required | Description                                                                                                                                                           |
| ----------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Idempotency-Key` | Yes      | UUID v4. Permanent uniqueness per `(api_key, key)`. Replays return the original response. Reusing with a different `vehicle_id` returns `422 idempotency_key_reused`. |

| Body field           | Type            | Required    | Description                                                                                                                                                                                                                                                                                                                                                                |
| -------------------- | --------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `vehicle_id`         | string          | Yes         | Current listing ID from `GET /v1/vehicles` or `GET /v1/vehicles/{id}`. Auction listings (`glovis_*`, `sk_*`, `aj_*`, `lotte_*`, `kcar_*`) and dealer listings (`encar_*`, `source: "dealer"`) are both accepted. For auction IDs this is not a permanent physical-car ID; use the current listing's `id`, not an old ID from `pricing.history`.                            |
| `max_bid_amount_usd` | integer \| null | Conditional | Bid ceiling in whole USD. **Required** for auction vehicles in an upcoming round (`auction_result: "upcoming"`). Must be > 0 and ≥ `pricing.listing_price`. **Null/omitted** for buy-now: auction vehicles with `auction_result: "no_bid"`, and all dealer (`encar_*`) listings (dealer is fixed-price, no bidding). Non-null dealer values return `400 validation_error`. |

### Response — `201 Created` (or `200 OK` on idempotent replay)

```json theme={null}
{
  "id": "01HXYZ...",
  "vehicle_id": "glovis_20260420_1064_2345",
  "vin": "KMHL14JA0NA123456",
  "license_plate": "12가 3456",
  "status": "placed",
  "max_bid_amount_usd": 15500,
  "is_highest_bid": true,
  "current_max_bid_usd": 15500,
  "amounts": { "purchase_price_usd": null, "auction_fee_usd": null },
  "fx_rate": 1347.52,
  "auction_date": "2026-04-20T13:00:00+09:00",
  "order_cutoff_at": "2026-04-20T12:00:00+09:00",
  "options": ["sunroof", "leather_seats", "navigation", "rear_view_camera"],
  "created_at": "2026-04-11T10:00:00+09:00",
  "updated_at": "2026-04-11T10:00:00+09:00"
}
```

## POST /v1/orders/backfill — Place order from LMN snapshot

Use this when you want to place an order for a dealer vehicle that may already be `SOLD`, `WAIT`, or removed upstream, but LMN may have a previously captured snapshot.

Auth, idempotency, request body, response shape, and errors are intentionally the same as `POST /v1/orders`:

```bash theme={null}
curl -X POST \
  -H "x-api-key: $KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"vehicle_id": "encar_41865534", "max_bid_amount_usd": null}' \
  https://api.lmnauto.com/v1/orders/backfill
```

Behavior:

1. If the vehicle is still live, LMN creates the order normally and captures a fresh at-order-time snapshot.
2. If the vehicle is no longer live (`SOLD`, `WAIT`, deleted, or 404), LMN creates the order from the latest stored vehicle snapshot for your account, if one exists.
3. If neither live data nor a stored snapshot exists, response remains `404 vehicle_not_found`.

<Note>
  Partners do not send snapshot JSON to this endpoint. LMN owns snapshot capture and snapshot reuse.
</Note>

### FX rate is locked at creation

`fx_rate` (KRW-per-USD) is captured at the moment you POST the order and **never changes** for the life of that order — not on PATCH, not on status pushes, not when markets move.

That rate drives the `purchase_price_usd` conversion when the order transitions to `secured`:

```
amounts.purchase_price_usd = auction_final_price_krw / fx_rate   (rounded)
```

Implication: once you've placed the order, you can compute the maximum settlement exposure yourself from `max_bid_amount_usd` — no FX surprise on auction day.

<Note>
  If the FX provider was unavailable at creation (rare), `fx_rate` is `null`. In that case LMN applies the settlement-day rate and communicates it offline with the `secured` transition. This does not happen silently — you'll see `fx_rate: null` in the response from the start and can rotate the order if that's unacceptable.
</Note>

### Competitive bidding

Multiple partners may all order the same auction vehicle. All POSTs return `201`. The response carries:

* `is_highest_bid` (boolean) — whether your bid is currently the highest among all active orders.
* `current_max_bid_usd` (integer) — the highest active bid across all partners.

At auction time, LMN bids with the highest active `max_bid_amount_usd`. Winner gets `secured`; losers get `failed (failure_reason: "outbid_internally")`.

### Errors

| Code                          | HTTP | Condition                                                                                                                                                                                                                              |
| ----------------------------- | ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `missing_idempotency_key`     | 400  | Header absent.                                                                                                                                                                                                                         |
| `missing_max_bid`             | 400  | Auction vehicle, but `max_bid_amount_usd` null/omitted/below listing\_price.                                                                                                                                                           |
| `vehicle_not_found`           | 404  | Unknown `vehicle_id`. For dealer (`encar_*`) IDs this means the upstream listing has been removed or the parseable Encar detail page marks the advertisement as `SOLD` or `WAIT`. Treat any dealer case as no longer available to buy. |
| `dealer_upstream_unavailable` | 503  | Dealer (`encar_*`) listing — upstream lookup failed (timeout, 5xx, or unexpected response shape). Listing may still exist; retry.                                                                                                      |
| `past_order_cutoff`           | 409  | Past `auction_date − N minutes`, where N is your integration's lead time (default 1440 = 24h; set per integration). Read `order_cutoff_at` from the response — don't compute. Does not apply to dealer listings (no auction date).     |
| `duplicate_order`             | 409  | Active order already exists for `(your key, this vehicle)`. `details.existing_order_id` referenced.                                                                                                                                    |
| `idempotency_key_reused`      | 422  | Same key, different `vehicle_id`.                                                                                                                                                                                                      |
| `vehicle_unavailable`         | 410  | Listing disappeared before processing.                                                                                                                                                                                                 |

***

## GET /v1/orders — List

Paginated, filterable list of your orders. AND semantics across filters.

| Param             | Description                                                                                             |
| ----------------- | ------------------------------------------------------------------------------------------------------- |
| `ids`             | CSV of order IDs (max 100). Foreign IDs silently dropped. Empty result → 200 with `data: []` (not 404). |
| `status`          | Single status filter.                                                                                   |
| `from`, `to`      | ISO 8601 with offset. Half-open `[from, to)` on `created_at`. Both required if either present.          |
| `sort`            | `created_desc` (default), `created_asc`, `auction_date_asc`, `updated_desc`.                            |
| `cursor`, `limit` | Composite cursor (sort-specific); default 50, max 200.                                                  |

### Sort use cases

| Value                    | When                                                                                                          |
| ------------------------ | ------------------------------------------------------------------------------------------------------------- |
| `created_desc` (default) | "Show what I just placed"                                                                                     |
| `created_asc`            | Backfill / oldest-first reconciliation                                                                        |
| `auction_date_asc`       | "Which of my orders resolves next?" Dealer-source orders (null `auction_date`) appear at the END (NULL LAST). |
| `updated_desc`           | "What changed recently?" — useful when a webhook was missed                                                   |

### Errors

| Code               | HTTP | Condition                                                    |
| ------------------ | ---- | ------------------------------------------------------------ |
| `validation_error` | 400  | Bad enum, `ids` > 100, `from` without `to`, `limit` > 200.   |
| `invalid_cursor`   | 400  | Cursor obtained with a different `sort`. Restart pagination. |

***

## GET /v1/orders/\{id} — Detail

Returns the full Order resource — current state, amounts, cutoffs, shipment.

```bash theme={null}
curl -H "x-api-key: $KEY" https://api.lmnauto.com/v1/orders/01HXYZ...
```

| Error                 | When                                                 |
| --------------------- | ---------------------------------------------------- |
| `404 order_not_found` | Unknown ID, or order belongs to a different API key. |

For auction vehicles, response includes recomputed `is_highest_bid` and `current_max_bid_usd` reflecting the latest competitive state.

Full Order schema in [Schemas](/schemas).

***

## GET /v1/orders/\{id}/vehicle — Purchased vehicle snapshot

Returns the immutable `VehicleDetail` snapshot captured when the order was created. This is the durable read path for purchased dealer (`encar_*`) cars after Encar removes the live listing page.

```bash theme={null}
curl -H "x-api-key: $KEY" https://api.lmnauto.com/v1/orders/01HXYZ.../vehicle
```

The response shape is the same as `GET /v1/vehicles/{id}` detail. For dealer orders created after this rollout, `photos` and image URLs inside inspection data are LMN-mirrored `https://storage.googleapis.com/lmnauto-auction-data/...` URLs, not Encar CDN URLs.

| Error                                  | When                                                                     |
| -------------------------------------- | ------------------------------------------------------------------------ |
| `404 order_not_found`                  | Unknown ID, or order belongs to a different API key.                     |
| `404 order_vehicle_snapshot_not_found` | Historical order created before purchased-vehicle snapshots were stored. |

***

## DELETE /v1/orders/\{id} — Cancel

Allowed **only** when the order is in `placed` status. Once LMN starts bidding (`acquiring`+), cancellation moves offline.

```bash theme={null}
curl -X DELETE \
  -H "x-api-key: $KEY" \
  https://api.lmnauto.com/v1/orders/01HXYZ...
```

Response: `200 OK` with the updated Order (`status: cancelled`, `cancellation_reason: dealer_cancelled`).

No money flow has occurred pre-`secured`, so cancellation has no settlement implication. Partner-to-dealer arrangements are outside this API.

<Note>
  **Race condition**: If you `DELETE` while LMN concurrently transitions the order (e.g., `placed → acquiring`), you may receive `409 invalid_status_transition`. Re-fetch `GET /v1/orders/{id}` to see current state.
</Note>

| Error                       | When                                                                                            |
| --------------------------- | ----------------------------------------------------------------------------------------------- |
| `order_not_found`           | 404                                                                                             |
| `invalid_status_transition` | 409 — order not in `placed`, or already cancelled. `details.current_status` shows actual state. |

## PATCH /v1/orders/\{id} — Update max bid

Update the `max_bid_amount_usd` on an existing order. Useful when you want to raise (or lower) your bid after placing the initial order — e.g., to improve win probability as auction day approaches.

Allowed only while:

* `status = placed`
* Current time is before `order_cutoff_at`

Any other state → `409` with the specific code. The payload must carry **only** `max_bid_amount_usd`; no other fields are mutable via PATCH.

```bash theme={null}
curl -X PATCH \
  -H "x-api-key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{ "max_bid_amount_usd": 16000 }' \
  https://api.lmnauto.com/v1/orders/01HXYZ...
```

### Response

`200 OK` with the updated Order. `is_highest_bid` and `current_max_bid_usd` are recomputed across **all** active orders on the same vehicle (so if a competing partner has a higher max, your updated order may still come back with `is_highest_bid: false`).

```json theme={null}
{
  "id": "01HXYZ...",
  "vehicle_id": "glovis_20260424_1068_6018",
  "status": "placed",
  "max_bid_amount_usd": 16000,
  "is_highest_bid": true,
  "current_max_bid_usd": 16000,
  "updated_at": "2026-04-24T09:15:03+09:00"
}
```

### Errors

| Error                       | When                                                                                   |
| --------------------------- | -------------------------------------------------------------------------------------- |
| `validation_error`          | 400 — body missing or `max_bid_amount_usd` not a positive integer.                     |
| `order_not_found`           | 404 — unknown ID, or order belongs to another partner.                                 |
| `invalid_status_transition` | 409 — order has moved past `placed`. `details.current_status` shows actual state.      |
| `past_order_cutoff`         | 409 — `order_cutoff_at` already elapsed. `details.cutoff_at` + `details.now` provided. |

<Note>
  **Concurrency**: PATCH takes the same vehicle-level advisory lock as `POST /v1/orders`, so `is_highest_bid` stays consistent under concurrent bid updates. No need to back off and retry.
</Note>

<Note>
  **Idempotency**: PATCH does **not** require `Idempotency-Key`. Replaying the same PATCH is safe (sets the same value). If you need strict at-most-once semantics, include your own client-side deduplication.
</Note>

## Sandbox status simulation

Use the dedicated [Status updates](/endpoints/status-updates) guide for `POST /v1/orders/{id}/sandbox-status`, including request fields, lifecycle behavior, QA cases, and response examples.

## GET /v1/orders/\{id}/events — Event history

Returns the LMN-side webhook event log for the order — every event LMN attempted to deliver, with current delivery state. Useful for self-service debugging without contacting LMN support.

| Param    | In    | Required | Notes                                    |
| -------- | ----- | -------- | ---------------------------------------- |
| `id`     | path  | yes      | Order ID.                                |
| `cursor` | query | no       | Opaque cursor returned in `next_cursor`. |
| `limit`  | query | no       | 1–100. Default 50.                       |

### Response — `200 OK`

```json theme={null}
{
  "data": [
    {
      "id": "evt_01HK5M...",
      "type": "order.status_changed",
      "delivery_status": "delivered",
      "attempts": 1,
      "last_response_code": 200,
      "next_retry_at": null,
      "created_at": "2026-04-24T03:14:11+09:00",
      "delivered_at": "2026-04-24T03:14:13+09:00",
      "payload": { "id": "evt_01HK5M...", "type": "order.status_changed", "occurred_at": "...", "data": { } }
    },
    {
      "id": "evt_01HJPU...",
      "type": "order.price_updated",
      "delivery_status": "delivery_failed",
      "attempts": 4,
      "last_response_code": 503,
      "next_retry_at": "2026-04-24T05:30:00+09:00",
      "created_at": "2026-04-22T03:02:10+09:00",
      "delivered_at": null,
      "payload": { }
    }
  ],
  "next_cursor": null
}
```

`type` is one of the five event types in [webhooks → event types](/webhooks/event-types). `payload` is the exact JSON body LMN sent (or will send) to your webhook URL — same shape your endpoint receives.

### `delivery_status` values

| Value              | Meaning                                                                                |
| ------------------ | -------------------------------------------------------------------------------------- |
| `pending`          | Enqueued, not yet picked up by a delivery worker.                                      |
| `delivering`       | Claimed by a worker, in-flight.                                                        |
| `delivered`        | 2xx response received. Terminal state.                                                 |
| `delivery_failed`  | All retries exhausted (or non-retryable error). Terminal state.                        |
| `delivery_skipped` | No webhook URL configured for the partner — recorded for completeness but not retried. |

### Errors

| Error             | When                                                   |
| ----------------- | ------------------------------------------------------ |
| `order_not_found` | 404 — unknown ID, or order belongs to another partner. |
