> ## 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.

# Event types

> Order and Eagle Eye webhook event types.

Order events carry a full `Order` snapshot in `data.order` so your handler can act without a follow-up GET. Eagle Eye events carry the watch context plus the vehicles or vehicle IDs that changed.

<Note>
  **Order payload parity (v1.18+):** the `data.order` field in every order webhook is structurally identical to the response of `GET /v1/orders/{id}` — same field names, types, nullability, and enrichment (including `is_highest_bid` and `current_max_bid_usd`). You can reuse the same `Order` type and deserializer across order reads and order webhooks.

  **Eagle Eye vehicle parity:** `vehicle` objects inside `eagle_eye.match` `additions` and `price_changes` use the same `VehicleSummary` schema returned by `GET /v1/vehicles`. Eagle Eye adds watch and signal metadata around that vehicle object; it does not define a separate vehicle model.

  **Examples below are abbreviated for brevity.** Order webhook payloads include every field documented under [Get an order](/api-reference/orders/get-order), not only the ones shown here. Eagle Eye vehicle examples are also abbreviated; build against the shared `VehicleSummary` schema.
</Note>

## `order.status_changed`

Fires on every server-side status transition. Includes the previous status for reconstruction.

```json theme={null}
{
  "id": "evt_01HXYZ...",
  "type": "order.status_changed",
  "occurred_at": "2026-04-20T13:30:00+09:00",
  "data": {
    "previous_status": "acquiring",
    "order": {
      "id": "01HXYZ...",
      "vehicle_id": "glovis_20260420_1064_2345",
      "status": "secured",
      "max_bid_amount_usd": 15500,
      "amounts": {
        "purchase_price_usd": 14800,
        "auction_fee_usd": 234
      },
      "failure_reason": null,
      "shipment": null,
      "created_at": "2026-04-11T10:00:00+09:00",
      "updated_at": "2026-04-20T13:30:00+09:00"
    }
  }
}
```

### Status transitions that fire this event

| Transition                                    | Driver                                                       |
| --------------------------------------------- | ------------------------------------------------------------ |
| `placed` → `inspection_in_progress`           | LMN starts the optional pre-acquisition inspection           |
| `placed` → `acquiring`                        | LMN starts bidding/purchasing (inspection skipped)           |
| `inspection_in_progress` → `inspection_ready` | Inspection completed; ready for LMN acquisition decision     |
| `inspection_ready` → `acquiring`              | Inspection passed; LMN starts bidding/purchasing             |
| `inspection_ready` → `cancelled`              | Inspection failed (`cancellation_reason: inspection_failed`) |
| `acquiring` → `secured`                       | LMN won/purchased                                            |
| `acquiring` → `failed`                        | LMN lost auction or purchase failed                          |
| `secured` → `export_processing`               | Title transferred to LMN; Korean export begins               |
| `export_processing` → `in_transit`            | Bill of Lading issued; vessel departed Korean port           |
| `placed` → `cancelled` (LMN auto)             | Reschedule-too-soon / source-cancel / seller-withdraw        |

Partner-initiated transitions (`placed` creation, `placed → cancelled` via DELETE, `in_transit → customs`, `customs → delivered`) are confirmed by the API response and do **not** fire webhooks.

### Failed-auction example

```json theme={null}
{
  "id": "evt_01HABC...",
  "type": "order.status_changed",
  "occurred_at": "2026-04-20T13:45:00+09:00",
  "data": {
    "previous_status": "acquiring",
    "order": {
      "id": "01HDEF...",
      "status": "failed",
      "failure_reason": "outbid",
      "amounts": {
        "purchase_price_usd": null,
        "auction_fee_usd": null
      }
    }
  }
}
```

`failure_reason` enum (terminal `failed`, reachable from `acquiring` only):

* `outbid` — lost to external bidder at auction.
* `outbid_internally` — another partner's higher bid won. **All competing `placed` orders on the same auction lot enter `acquiring` together** before resolution, so each competitor sees a clean `placed → acquiring → failed` sequence.
* `vehicle_unavailable` — LMN's dealer purchase attempt failed (car sold to another buyer).
* `auction_cancelled` — auction event cancelled after LMN began bidding.
* `auction_passed` — vehicle passed at auction, OR zombie cleanup at `auction_date + 24h` (see below).
* `seller_withdrew` — seller withdrew the car after LMN started attempting to acquire.

### Zombie-cleanup variant

If LMN never picked up a `placed` order and the auction has been over for 24 hours, the system auto-resolves it with `failure_reason: auction_passed`. The webhook collapses the synthetic intermediate state — `previous_status` is `placed` (not `acquiring`), and an additive `synthetic_acquiring: true` discriminator is set:

```json theme={null}
{
  "id": "evt_01HZOM...",
  "type": "order.status_changed",
  "occurred_at": "2026-04-21T13:00:00+09:00",
  "data": {
    "previous_status": "placed",
    "synthetic_acquiring": true,
    "order": {
      "id": "01HXYZ...",
      "status": "failed",
      "failure_reason": "auction_passed",
      "acquired_at": null
    }
  }
}
```

Treat this as a regular `failed` event, or branch on `synthetic_acquiring` to suppress noise from known LMN ops outages.

### Cancellation example

```json theme={null}
{
  "id": "evt_01HCAN...",
  "type": "order.status_changed",
  "occurred_at": "2026-04-19T08:00:00+09:00",
  "data": {
    "previous_status": "placed",
    "order": {
      "status": "cancelled",
      "cancellation_reason": "auction_cancelled"
    }
  }
}
```

`cancellation_reason` enum (terminal `cancelled`, reachable from `placed` only):

* `dealer_cancelled` — partner sent `DELETE`.
* `auction_rescheduled_too_soon` — LMN auto, auction rescheduled past order cutoff.
* `auction_cancelled` — LMN auto, auction event cancelled before LMN started bidding.
* `seller_withdrew` — LMN auto, seller pulled dealer listing before LMN started purchase.

`failure_reason` and `cancellation_reason` are **mutually exclusive** — an order has one or the other, never both. For reasons that can appear in either enum (`auction_cancelled`, `seller_withdrew`), the order's current status at the moment of the upstream event decides the terminal.

## `order.auction_rescheduled`

Fires when the auction source postpones or advances an auction, shifting `auction_date` and recomputing `order_cutoff_at`. **No status change.**

```json theme={null}
{
  "id": "evt_01HRES...",
  "type": "order.auction_rescheduled",
  "occurred_at": "2026-04-14T08:15:00+09:00",
  "data": {
    "previous_auction_date": "2026-04-20T13:00:00+09:00",
    "order": {
      "auction_date": "2026-04-22T13:00:00+09:00",
      "order_cutoff_at": "2026-04-21T00:00:00+09:00"
    }
  }
}
```

Compare `data.previous_auction_date` against `data.order.auction_date` to detect direction and magnitude. Update dealer-facing deadlines accordingly.

If a reschedule moves `auction_date` so close that `order_cutoff_at` is already in the past on a `placed` order, LMN auto-cancels with `cancellation_reason: "auction_rescheduled_too_soon"` and fires a separate `order.status_changed` event. Orders already in `acquiring` or later are unaffected (LMN is committed; the auction proceeds on the new date).

## `order.price_updated`

Fires when the vehicle backing an active `placed` order has its `listing_price` updated by the upstream scraper. **No status change.** The payload keys (`previous_listing_usd` / `current_listing_usd`) keep the `_usd` suffix for webhook-event convention; they refer to the same underlying value as `pricing.listing_price` on the vehicle. Useful for partners whose bid strategy depends on the current market estimate — a price drop may mean the dealer should raise `max_bid_amount_usd` to stay competitive, while a spike may mean the current `max_bid` is now insufficient.

```json theme={null}
{
  "id": "evt_01HJPU...",
  "type": "order.price_updated",
  "occurred_at": "2026-04-22T03:02:10+09:00",
  "data": {
    "previous_listing_usd": 14200,
    "current_listing_usd": 13650,
    "delta_usd": -550,
    "delta_pct": -3.9,
    "order": {
      "id": "01HXYZ...",
      "vehicle_id": "glovis_20260420_1064_2345",
      "status": "placed",
      "max_bid_amount_usd": 15000
    }
  }
}
```

**Semantics:**

* `delta_usd` is negative when the price dropped (partner-friendly).
* `delta_pct` is rounded to 1 decimal place and is `null` if `previous_listing_usd` was 0.
* Fires at most once per actual change — identical refreshes to the same value are deduped server-side.
* Fires only while the order is in `placed` — terminal-state and post-`acquiring` orders ignore market refreshes.

## `order.re_auctioned`

Fires when a vehicle tied to one of your **terminal** orders (status `failed` / `cancelled` / `delivered`) reappears in a new auction round. Matched by Korean license plate across auction houses, so the same physical car is caught even if it moves from Glovis to SK or Lotte between listings.

```json theme={null}
{
  "id": "evt_01HK5M...",
  "type": "order.re_auctioned",
  "occurred_at": "2026-04-24T00:15:00+09:00",
  "data": {
    "previous_vehicle_id": "glovis_20260410_1062_5000",
    "new_vehicle_id": "glovis_20260428_1070_3021",
    "new_auction_date": "2026-04-28T09:00:00+09:00",
    "license_plate": "12가 3456",
    "order": {
      "id": "01HWYZ...",
      "status": "failed",
      "failure_reason": "outbid"
    }
  }
}
```

**Use case:** the dealer originally bid, lost (or cancelled), and wants a second chance. On receiving this event, surface the new `vehicle_id` back to the dealer UI and let them re-POST `/v1/orders` if still interested.

**Semantics:**

* The attached `data.order` is the **original terminal order** — NOT a new order. No new order is implicitly created.
* Fires at most once per `(license_plate, new_auction_date)` — no duplicates during re-scrapes.
* `data.previous_vehicle_id` is the ID from the terminal order; `data.new_vehicle_id` is the current listing's ID.
* `data.new_auction_date` is in KST ISO 8601 with `+09:00` offset.

## `eagle_eye.match`

Fires when a saved Eagle Eye watch has at least one addition, price change, or removal. The payload is batched per watch and includes enough context for a partner UI to explain why the vehicle appeared.

```json theme={null}
{
  "id": "evt_01HZX0Q...",
  "type": "eagle_eye.match",
  "occurred_at": "2026-06-09T12:00:00+09:00",
  "data": {
    "watch_id": "wat_01HZW...",
    "watch_name": "GLE 450 watch",
    "batch_id": "batch_01HZX0M9R5Q7TZWN4D5VG3F2KA",
    "evaluated_at": "2026-06-09T03:00:00.000Z",
    "additions": [
      {
        "vehicle": {
          "id": "glovis_20260609_1234_5678",
          "source": "glovis",
          "make": "Mercedes-Benz",
          "model": "GLE-Class",
          "year": 2022,
          "pricing": {
            "listing_price": 31000000,
            "currency": "KRW"
          }
        },
        "match_reason": ["filters", "signals.undervalued"],
        "signal_detail": {
          "undervalued": {
            "reference_price_krw": 38500000,
            "listing_price_krw": 31000000,
            "delta_pct": 19.5
          }
        }
      }
    ],
    "price_changes": [
      {
        "vehicle": {
          "id": "sk_20260609_88_1001",
          "source": "sk",
          "pricing": {
            "listing_price": 30000000,
            "currency": "KRW"
          }
        },
        "previous": {
          "price_krw": 32500000,
          "observed_at": "2026-06-08T03:00:00.000Z"
        },
        "match_reason": ["filters", "signals.price_drop"],
        "signal_detail": {
          "price_drop": {
            "previous_price_krw": 32500000,
            "current_price_krw": 30000000,
            "drop_pct": 7.7,
            "min_drop_pct_configured": 5
          }
        }
      }
    ],
    "removals": [
      {
        "vehicle_id": "glovis_20260601_1234_1000",
        "reason": "auction_complete"
      }
    ]
  }
}
```

### Signal detail

Signal-driven matches include `signal_detail` so product teams can show the dealer why the alert matters:

| Signal           | Detail fields                                                                    |
| ---------------- | -------------------------------------------------------------------------------- |
| `repeat_listing` | `bucket`, `listing_count`, `cumulative_drop_pct`, `window_days`                  |
| `undervalued`    | `reference_price_krw`, `listing_price_krw`, `delta_pct`                          |
| `price_drop`     | `previous_price_krw`, `current_price_krw`, `drop_pct`, `min_drop_pct_configured` |

`price_drop` is drop-only. A price increase does not carry `signals.price_drop`; if the vehicle still qualifies, the current match updates silently and no `price_changes` webhook entry is emitted. If the increase makes it fail the watch's filters, LMN sends a `removal`.

### Removal reasons

| Reason                  | Meaning                                              |
| ----------------------- | ---------------------------------------------------- |
| `delisted`              | Dealer inventory listing disappeared.                |
| `auction_complete`      | Auction listing finished.                            |
| `price_above_threshold` | Vehicle rose above the watch's configured price cap. |

Hiding a match via `POST /v1/eagle-eye/watches/{watch_id}/matches/hide` is a view-state change on your side only — it never produces a `removals` entry on this webhook.

Use `GET /v1/eagle-eye/watches/{watch_id}/events` to recover the exact webhook payload history for a watch.
