Skip to main content
Four endpoints power partner discovery: filter values for dropdowns, paginated list, single-vehicle detail, and lookup by VIN or license plate.

GET /v1/vehicles/facets

Returns distinct filter values currently in catalog. Cached 5 minutes.
Response is flat unique-value arrays — no per-value counts (UIs surface plain “Kia”, not “Kia (1,234)”):
Optional query: source (CSV) to scope facets to a specific source set.

GET /v1/vehicles

Paginated, filterable inventory list. Returns VehicleSummary[].

Filters

Unrecognized query params are silently ignored. The server returns a 200 with default-filtered data instead of a 400. Common gotchas:
  • page / perPage — there is no offset pagination; use cursor + limit.
  • fuel_type — the param is fuel (singular). fuel_type is the BigQuery column name, not the API param.
  • transmissions (plural) — the FILTER param is transmission (singular). The plural form is the response field name in GET /v1/vehicles/facets.
  • result / status — use auction_status for auction result filtering.
For a last-mile delivery use case, use:
body_style=van is currently a deterministic text heuristic over model/trim tokens (van, cargo, 2-seater, Korean 밴/벤) until upstream auction sources provide explicit seat/cargo metadata.If your client returns more rows than expected, double-check your param names against this table — the server isn’t filtering by something it doesn’t recognize.

Model vs. sub-model

Korean inventory is organized in two levels: a ModelGroup (e.g. Cherokee) contains one or more Models (e.g. Grand Cherokee, Cherokee).
  • model selects the ModelGroup. model=Cherokee therefore returns every car in the Cherokee family — Grand Cherokee included.
  • sub_model narrows to a specific Model within that group: model=Cherokee&sub_model=Grand Cherokee.
sub_model requires model (it has no meaning without its group) and is a single value. Dealer vocabulary is validated before the upstream request: an unsupported make, model, or sub_model returns 400 validation_error with the offending field and value instead of silently producing a guaranteed-empty page. Discovering supported values: the response does not echo the sub-model — VehicleSummary.model is the ModelGroup (a Cherokee and a Grand Cherokee row both come back with model: "Cherokee"), so you cannot read the canonical sub_model spelling off a result. Matching is exact, and many models are split by generation, so a supported value may carry a generation/facelift qualifier — e.g. Grand Cherokee, Grand Cherokee (WL), Cherokee (KL). Ask LMN for the current per-make catalog rather than inferring names from responses.

Sort

Null-strict semantics

When you filter on a field that’s null for dealer cars (accident_grade, auction_date_*, auction_count_*), dealer rows are silently excluded only when source is omitted entirely. The response includes an X-LMN-Filtered-Out: dealer=N header so your UI can tell the dealer “42 dealer cars were hidden”. When you explicitly request source=dealer together with one of these auction-only filters, the request returns 400 validation_error instead (see Dealer source constraints below) — fail-fast rather than silent drop. The header has two caveats, both consequences of dealer inventory being a live third-party proxy:
  • It only appears when make is provided. The dealer upstream resolves inventory per-manufacturer, so without make the excluded count cannot be computed and the header is omitted.
  • N is approximate and best-effort. It is the upstream match count for your non-auction filters; a small number of those cars may still have been narrowed further by response-side filters (for example transmission). If the dealer upstream is temporarily unreachable, the header is omitted rather than delaying your response.

Dealer source constraints

The dealer source is fulfilled by a live proxy to a third-party retail inventory (encar). Two design choices flow from that: Required: source=dealer (alone or mixed with auction sources) requires make. make may be a CSV list, for example Hyundai,Kia; the API fans out to one upstream dealer request per manufacturer. model may also be CSV; for dealer rows the API fans out valid make/model pairs, for example make=Hyundai,Kia&model=Avante,K5 becomes Hyundai Avante plus Kia K5 upstream searches. Without make, the request returns 400 validation_error (details.field: "make"). Vocabulary: make, model, and sub_model must resolve to LMN’s current dealer catalog or a documented compatibility alias. Unsupported values return 400 validation_error with details.field, details.value, and (for model fields) details.make. This replaces the previous silent-zero fallback. Values are case-insensitive; the legacy Mercedes Benz spelling and audited Lexus forms such as ES350/RX350 remain accepted. Forbidden: Combining source=dealer with any auction-only filter returns 400 validation_error. The offending field is reported in details.field: Filter parity gaps (dealer-only): A few filters supported on the auction side are silently dropped when applied to the dealer query because the upstream DSL doesn’t support them: keyword, body_style. The auction half of a mixed request still honors these. (Note: transmission is applied to dealer rows via a post-filter, color is honored as a single value, and options_include is applied natively — see below.) options_include for dealer: options_include is applied to dealer rows — it’s translated to Encar’s native Options. search DSL, with the same AND semantics as auction (a car must have all listed options). Two tokens are the exception: panoramic_sunroof and dashcam have no Encar filter equivalent, so a dealer request containing either returns 400 validation_error (details.field: "options_include", with the offending token named) rather than silently dropping it. This 400 is dealer-scoped — auction-only requests still accept every documented token — and is raised at validation time, so a mixed source=glovis,dealer request carrying one of these tokens returns 400 (not a degraded auction-only 200 with X-LMN-Partial-Dealer-Unavailable). Every other documented options_include token filters dealer rows normally. The full catalog of the 62 dealer-filterable tokens (and the 2 dealer-unsupported ones) is in options_include for dealer (full catalog) below. Under-contract listings are hidden. A dealer listing marked under contract on Encar (계약중 — a buyer has placed a deposit) is excluded from GET /v1/vehicles results while the contract is active, the same as a listing Encar reports SOLD or WAIT. Unlike those two, it’s reversible — LMN carries no special state for it, so if the contract falls through, the listing simply reappears in results on the next request. Detail behaves the same way; see the 404 note under Dealer detail caveats. Eagle Eye watches report this transition as its own removal reason — see Removal reasons.

options_include for dealer (full catalog)

Use the table below as the options_include token reference for dealer inventory filtering.
options_include is applied to source=dealer results server-side — each token is translated to Encar’s native option facet, so dealer rows are filtered at the source rather than after the fact. Multiple values are AND-combined: a vehicle must have all requested options to match. Tokens are case-insensitive snake_case (Sunroof, sunroof, and SUNROOF are equivalent).
Two documented option tokens are not available for dealer and return 400 validation_error (details.field: "options_include", with the offending token named): panoramic_sunroof and dashcam. Encar’s search filter exposes no facet for them. These two tokens still work for auction sources — the 400 is dealer-scoped (and applies to a mixed source=glovis,dealer request, since validation runs before the query fans out).
The 62 tokens below are all filterable for dealer, grouped by category. Column Token is the value you pass in options_include; Option is the human-readable equipment name.
Not available for dealer (→ 400): panoramic_sunroof, dashcam.
Auction sources currently support the original option set. Full parity for the newly-added dealer tokens on the auction side is a separate follow-up — for the auction half of a query, treat the tokens above as best-effort until parity ships.
Example — AND semantics across two options:
A car must carry every requested token to appear in the result — adding more tokens narrows the set, never widens it.

Mixed source — first page only

A mixed query like source=glovis,dealer&make=Hyundai works on the first page. Passing cursor together with mixed source returns 400 mixed_source_pagination_unsupported — paginate each source separately when iterating deeper than one page. When sort=auction_date_asc (the default), the response budget is split: half the limit is allocated to auction rows (sorted by date ascending) and half to dealer rows (sorted by year descending, since dealer listings have no auction date). Other sort options (price_asc, price_desc, year_desc, mileage_asc) sort across the merged result set directly.

Dealer page limit

The dealer upstream caps page size at 48 regardless of the limit you request. When limit > 48 and dealer is in scope, the dealer half is internally capped and the response includes X-LMN-Dealer-Page-Max: 48. Paginate dealer separately via cursor to retrieve more dealer rows.

Dealer upstream unavailability

The dealer half depends on external upstreams (Encar and Danawa). Every response where dealer inventory is explicitly requested includes a source_status object for Encar and Danawa. Each source is fresh, stale, partial, unavailable, or not_requested; as_of is the oldest evidence timestamp included for fresh, stale, or partial data. If live Encar search still fails after one retry, LMN may serve the exact matching cached Encar page when it is no more than 30 minutes old. Those rows are returned normally with source_status.encar.status: "stale" and the cached as_of. Treat them as last-known inventory and re-check live availability before relying on a vehicle. A multi-make/model query is partial when some Encar branches answer and others remain unavailable; its count covers answered branches only. When no eligible cache exists, two failure modes remain:
  • Pure dealer request fails (source=dealer only) → 503 dealer_upstream_unavailable only when every dealer source is down. If just one source fails, you still get a 200 OK with the surviving source’s rows plus the two degradation headers below.
  • Mixed request degrades (source=glovis,dealer) → 200 OK with the auction rows (and any surviving dealer rows) plus two headers: X-LMN-Partial-Dealer-Unavailable: 1 — a binary flag (always the literal 1) signalling partial dealer degradation — and X-LMN-Dealer-Unavailable-Sources: <csv>, a comma-separated list of the failed or incomplete source names (encar, danawa, or encar,danawa). These headers are emitted for partial/unavailable, not stale. Check the flag for presence, read the source names from X-LMN-Dealer-Unavailable-Sources. The auction half is still authoritative; retry the named dealer source(s) via a separate source=dealer query when you need them.
The detail endpoint maps the same way: GET /v1/vehicles/encar_<id> returns 503 dealer_upstream_unavailable when the detail upstream is unreachable. 404 vehicle_not_found means the dealer listing is not currently available to buy: either the upstream explicitly returned 404 for that ID, the upstream detail page was still readable but marked the advertisement as SOLD or WAIT (both mean the listing is dead — Encar shows its own “sold or deleted” page for either), or the listing is under contract (계약중) on Encar — a buyer has placed a deposit but the sale hasn’t finalized — unless you have already created an order for that car, in which case the detail keeps resolving from your stored order-time snapshot (200) instead of returning 404, so a vehicle you’ve purchased survives delisting. The snapshot is scoped to your partner account and the key’s environment, so this recovery applies only to cars you ordered. Unlike SOLD / WAIT, an under-contract 404 is reversible — if the contract falls through, detail resolves normally again on LMN’s next check, with nothing to reset on your side. Dealer detail also attempts Encar inspection enrichment. When the inspection page is reachable, inspection_report is populated — dealer_inspection carries frame/exterior damage counts, body_condition.panels[] carries any damaged panels, and checklist[] carries the EN-translated mechanical inspection. A clean car returns a populated report with zero damage and a populated checklist (not null). inspection_report and body_condition are null only when Encar has no inspection record for the car (upstream 404) or the secondary fetch fails transiently; the rest of the detail still returns.

Response

Full Vehicle schema in Schemas.
id / vehicle_id values are auction listing IDs. They can change when the same physical car is re-listed in a later auction round. LMN matches same-car history internally by Korean license plate; use license_plate from the detail response when you need to identify the physical car.

GET /v1/vehicles/{id} — Detail

Returns the full Vehicle Detail — Summary fields plus VIN, photos, body condition diagram, full inspection report, and price breakdown.

ID format

The {id} path parameter is either:
  • An auction listing ID with one of the source prefixes: glovis_…, sk_…, aj_…, lotte_…, kcar_…. These are pulled from GET /v1/vehicles (the id field on each row).
  • A dealer (encar) listing ID with the prefix encar_<numeric>. Detail for dealer IDs is served via a live proxy to the upstream; expect modestly higher latency than auction detail.
The id you pass back must match exactly what GET /v1/vehicles returned. The auction-prefix IDs are not permanent physical-car identifiers — the same car may receive a different ID when re-listed in another auction round. Use license_plate on detail responses when you need the physical-car identifier.

Dealer detail caveats

Dealer detail responses differ from auction in three ways:
  • pricing.breakdown.auction_fee is 0; pricing.breakdown.dealer_fee is 300 (flat USD, not KRW-derived). pricing.discount_config.fixed_discount_amount is 300, which offsets the dealer fee so net economic impact on estimated_landed is zero — estimated_landed = listing_price + lmn_commission + ocean_freight.
  • pricing.auction_fee_config, pricing.market_assessment, comparables.past_sales, comparables.upcoming_sales, and pricing.history are all null or empty — these are auction-only concepts. (body_condition / inspection_report are populated for dealer when Encar has an inspection record — see the dealer-inspection note above; they are not auction-only.) pricing.discount_config is populated but the bid-based fields (bid_threshold, rate_below, rate_at_or_above) are all 0.
  • 404 vehicle_not_found is returned when the dealer listing is not currently available to buy: the upstream either explicitly returns 404, still serves a parseable detail page but marks the advertisement as SOLD or WAIT, or the listing is under contract (계약중) on Encar. Exception: if you hold an active or delivered order for that car, detail instead returns your stored order-time snapshot (200) and does not 404 — purchased vehicles survive delisting (snapshot scoped to your account + environment). That response carries a non-null order (buyable: false) and, once a purchase price is recorded on the order, pricing.listing_price is that price — see Schemas → order. A failed or cancelled order no longer keeps the snapshot: detail resolves from live inventory again (and may 404); use GET /v1/orders/{id}/vehicle for that order’s history. Under contract is reversible (unlike SOLD / WAIT): detail resolves normally again once the contract falls through, with nothing to reset on your side. Other failure modes (timeout, 5xx, unexpected response shape) surface as 503 dealer_upstream_unavailable so callers can distinguish “removed/sold listing” from “transient upstream issue.”

Response

Key nullables:
  • Unless explicitly documented otherwise, vehicle response monetary values are whole USD integers. This includes pricing, comparables, and inspection_report.accident_cost_summary.
  • pricing.breakdown.* fields may be null individually when a cost component isn’t yet finalized.
  • pricing.auction_fee_config exposes the source/category fee percentage plus min/max caps converted to whole USD with the response FX snapshot. percentage is a percent value (2.2 means 2.2%, not 0.022). LMN calculates pricing.breakdown.auction_fee internally from source/category KRW rules, applies KRW caps, then converts to USD.
  • pricing.market_assessment is null for dealer-source vehicles (no auction market to compare against).
  • comparables.past_sales is sold-only and empty for dealer vehicles or when no matching sold comps exist in the past 4 weeks.
  • comparables.upcoming_sales contains comparable future auction options and is empty when none exist. It does not include sold_price.
  • pricing.history contains auction appearances for the same physical car, matched internally by Korean license plate across supported auction sources. Each pricing.history[].vehicle_id is the listing ID for that auction round and may differ from the current response id. It is empty when the car has no known prior/current auction appearances with a usable listed price.
  • body_condition / inspection_report are populated for dealer-source vehicles when Encar has an inspection record; null only when the upstream inspection is missing (404) or the secondary fetch fails transiently.
  • body_condition.image_url is returned only when LMN has a mirrored HTTPS image. Upstream auction-site image URLs are not exposed; use panels[] when image_url is null.
  • vin and license_plate may be null for pre-auction listings.
  • fuel, transmission, color may be null for rare upstream data gaps.
  • order is null unless you hold an order on this car and the response was served from that order’s snapshot; then it is { id, status, purchase_price, purchase_price_usd, buyable: false } and pricing.listing_price reflects your recorded purchase price. See Schemas → order.
Auction grade and condition-tag descriptions are published at Auction guide — Grades.

Pricing

Field-level reference for the pricing object — including listing_price, sold_price, auction_fee_config, discount_config, breakdown (with symmetric auction_fee/dealer_fee integers and post-discount estimated_landed notes), history, and market_assessment — lives in the Vehicle schema: Schemas → Vehicle → pricing. All monetary values inside pricing are whole USD integers. pricing.breakdown.estimated_landed is the only field that’s already post-discount; everything else (listing_price, sold_price, the line-item costs in breakdown) is gross. To get an exact landed total for your specific bid (rather than LMN’s illustrative number against an internal basis price), use the recompute formula below.

Recomputing landed cost for your bid

estimated_landed is a comparison aid, not a quote. For exact bid planning, recompute using your intended bid (all amounts in USD):
ocean_freight is not a fixed constant. It is resolved per vehicle: Mercedes-Benz is 1800 for any body type; other makers are 1800 for SUV-class (SUV, minivan, van, truck) and 1500 for sedan-class (sedan, compact, wagon, coupe, convertible); an unknown body type uses 1500. Always read pricing.breakdown.ocean_freight from the response instead of hardcoding a value.
Rounding rules Caveats
  • **FX rounding (±1).∗∗LMNinternallycomputestheauctionfeeinKRWagainsttheKRWsource−of−truthfeeschedule,thenconvertstoUSDattheresponseedge.PartnersrecomputingentirelyinUSDmayseea≤1).** LMN internally computes the auction fee in KRW against the KRW source-of-truth fee schedule, then converts to USD at the response edge. Partners recomputing entirely in USD may see a ≤1 difference vs. LMN’s KRW-side math. The invoice is authoritative.
  • Planned bid vs. actual purchase price. your_bid_usd is the partner’s intended bid — typically a ceiling. At settlement, LMN recomputes auction fee and discount against the actual hammer price (purchase_price_usd on the order), which may be lower than max_bid_amount_usd. The invoice reflects what was actually won at, not the ceiling.
  • listing_price vs. internal basis. The basis used for estimated_landed is sold_price if available, otherwise LMN’s market-derived final-price estimate, otherwise the auction starting price. For unsold cars with no estimate this happens to equal listing_price, but listing_price itself does not drive the calculation in all cases.

Similar-sales definition

The comparables.past_sales array surfaces up to 20 comparable cars that sold in the past 4 weeks. The comparables.upcoming_sales array uses the same match rules but only includes future upcoming auction options. Sort order is by auction date descending (most recent first). past_sales never includes upcoming; future alternatives are returned only in upcoming_sales. These defaults match LMN’s internal “Market Comparison” logic shown in the web UI, so the partner API returns the same comp set an LMN operator would see for the same vehicle.

Market assessment (pricing.market_assessment)

A derived server-side summary so you don’t have to compute comp medians client-side. Runs on the comparables.past_sales set (sold comps only) and compares their starting-price median to your current listed/estimated price. diff_percent is the % the current listed/estimated price is below (positive) or above (negative) the comp median. price_drop, when present, reports how the same vehicle’s starting price has moved across prior auction rounds — useful in combination with the label (a good + 2-round drop is a different signal than good + first appearance).
This is an advisory signal, not a valuation guarantee. It reflects starting prices of comps in the past_sales window, not expected auction-day outcomes. Always apply your own deal logic on top.

Errors

Full Vehicle schema in Schemas.

GET /v1/vehicles/lookup/{key} — Lookup by VIN or plate

The same detail payload as GET /v1/vehicles/\{id\}, but keyed by something you already hold: a VIN from a funding application, or a license plate off a photo. Use it to answer “do you have a record of this car?” without knowing our id. This endpoint is recall, not browse. Unlike the list and detail-by-id endpoints, it returns a car whether or not it is still for sale — sold listings, cars under contract, and auction lots that already ran all resolve here. Read listing_status on every response before treating a price as a quote. If you want live inventory only, filter on listing_status == "live". Key detection is automatic. A key containing any Hangul syllable is treated as a license plate; anything else must be a 17-character VIN.
The response body is byte-for-byte the detail body — see GET /v1/vehicles/{id}. A X-LMN-Lookup-Key-Type header echoes vin or plate so you can confirm how your key was read.

One car, two listings

Encar publishes some cars twice — a regular listing and an 엔카믿고 listing, with adjacent ids and identical specs. Roughly 58% of live VINs and 51% of live plates match more than one id. The lookup returns the most recently seen first and transparently tries the other if the first cannot be resolved. Two lookups of the same key can therefore return different id values for the same physical car. Match on license_plate or vin, not on id, if you need to tell cars apart.

Freshness

Plate coverage and VIN coverage are not the same. A plate lookup that finds no indexed candidate falls through to a live Encar search (see “One car, two listings” above), so it reflects current inventory even for a car we haven’t indexed yet. A VIN lookup has no such fallback — the live-search fallback is plate-only — so a VIN only ever matches our indexed dealer snapshot, which does not cover every live listing. A VIN 404 therefore does not prove the car is unavailable; it may simply be outside what we’ve indexed. If you hold both the VIN and the plate for a car, prefer the plate. Auction inventory is unaffected by the above. Auction lots are indexed directly from our own auction data, not proxied through a third-party search, so this asymmetry is a dealer-inventory concern only. Auction recall also reaches past lots, not just upcoming ones, so a VIN that went through an auction we covered resolves even long after the sale. Lots we withdrew or never captured an outcome for stay unreachable.

Availability — read listing_status

Every vehicle body carries listing_status, and on this endpoint it is the field that tells you whether what you are holding is an offer or a record: Anything other than live is a historical record. The price fields are whatever we last observed and must not be quoted as an offer. One exception has no marker. If you have already created an order for a car, the lookup returns your stored order-time snapshot before ever calling upstream — verbatim, and its listing_status reflects that snapshot, not the car’s state now. This applies only to cars you’ve ordered. Separately, and independent of the above: candidate ids are cached for 5 minutes, so a car listed in the last few minutes may return 404 briefly until the cache turns over.

Errors

A 503 and a 404 mean different things here. A 503 always means “ask again”. A 404 means we hold no record of the key at all — not that the car has sold, which now comes back as a sold result rather than a 404. How much a 404 tells you still depends on the key. For auction inventory and for plate lookups we search as widely as we can, including a live upstream search for plates, so a 404 there is a reasonably strong signal though not an absolute one. For a VIN against dealer inventory it is weaker: see Freshness above, since a VIN matches only our indexed snapshot.