Skip to main content
This guide is everything you need to render the two inspection panels that appear on lmnauto.com car-detail pages — using only the JSON returned by GET /v1/vehicles/{id}. It is intentionally exhaustive: a partner engineer should be able to build a pixel-faithful rendering from scratch using only this page plus the response.
Using React? Don’t build this from scratch. LMN ships a drop-in React package, @lmnauto/inspection-ui, that renders the entire inspection UI — grades, body-damage diagrams, checklist, accident/insurance, inspector notes — exactly as lmnauto.com does, for all six sources. You pass the GET /v1/vehicles/{id} payload and it does the mapping:
The mapping logic lives with LMN (who own the payload), so your UI stays correct as sources evolve — no per-source damage-code/panel-ID handling on your side. It’s zero-runtime-dependency (React peer only), fully themeable via a typed theme prop (§8), and every section is toggleable. The package is distributed privately (tarball or git) — contact LMN for access.This page remains the reference for non-React partners, custom rendering, or understanding the underlying data semantics.

Why a dedicated guide?

The inspection data is the densest, most source-variable part of the response. The unified shape covers six inspectors (Glovis, SK, AJ, Lotte, KCar, Encar dealer) that all expose different raw data, normalized into a single response contract. The shape is mostly consistent across sources, with a few documented asymmetries:
  • Shape asymmetries — auction and dealer both carry checklist[]; only dealer adds the dealer_inspection damage-count block. accident_history[] remains auction-only for now (dealer surfaces accident state via has_accident / accident_summary).
  • Value asymmetries — SK and Lotte return a mirrored diagram image_url (damage baked in) and AJ a blueprint base image; Glovis, K-Car, and dealer return null and need a client-rendered diagram from panels[]. Damage codes and panel IDs differ per source (see Damage Code Dictionary and Panel ID Catalog) — render-time partner code must tolerate the variations.
Getting the rendering right depends on understanding where these asymmetries surface in your JSON. If you only need the API reference (path, query params, error codes), see Vehicles. This page is the rendering companion.

1. Anatomy of the response

The detail endpoint returns these two top-level objects relevant to inspection: Either can be null independently — feature-detect before rendering.

Why both can be null

The full report and the diagram are independent ingestion pipelines, so partial states are expected. Always feature-detect at the field level too — accident_cost_summary may be null even when inspection_report itself is populated.

2. Per-source field matrix

Every field below is part of the same response shape, but populated differently depending on inspection_report.source. Knowing which fields you can expect per source lets you build skeletons and empty states that don’t flicker. Practical reading: Glovis and AJ are the most data-rich (full checklist + accident history + cost breakdown). SK / Lotte / KCar return enough to render a graded card but no checklist depth. Dealer (Encar) now returns the mechanical checklist[] (engine, transmission, steering, braking, electrical, …, EN-translated) alongside the dealer_inspection damage counts. Render whatever is non-empty; the renderer below handles all six.
Clean dealer cars now return a populated inspection_report. Previously a dealer car with no panel damage returned inspection_report: null (and the UI showed “No inspection report available”), even though the inspection existed and was simply clean. As of the change below, a successfully-fetched dealer inspection always returns a report — a clean car reads as zero damage with a populated mechanical checklist[]. inspection_report is still null only when the inspection genuinely doesn’t exist upstream (Encar 404) or the fetch failed transiently.

3. The Body Inspection card

The card titled “Body Inspection” on lmnauto.com. For live comparison, see any dealer listing at https://lmnauto.com/en/auction?source=retail&tab=encar_<id> — the worked example in §12 uses encar_41657860 (BMW M5 2019).

3.1 Visual structure

3.2 Response shape

3.3 Field reference

3.4 Count derivation

Compute the two count boxes from the panels array:

3.5 Status text per count box

3.6 Count box color

3.7 Rank breakdown (dealer-source only)

When inspection_report.source === "dealer", render a small summary beneath the diagrams using the server-computed totals in inspection_report.dealer_inspection:
The mechanical condition of the car (engine, transmission, steering, braking, electrical, fuel) is in inspection_report.checklist[] for dealer cars too — each entry is { group, item, result }, already KO→EN translated. Render it with the same checklist component used for auction sources. Display under each diagram:
Per-rank breakdown is available at dealer_inspection.rank_counts. To reproduce the reference UI’s “Rank 1 / Rank 2 / Rank A / Rank B / Rank C” lines, read dealer_inspection.rank_counts ({ rank_one, rank_two, rank_a, rank_b, rank_c }, integers, dealer-only). By construction rank_a + rank_b + rank_c === critical_frame_damage and rank_one + rank_two === exterior_damage, so the aggregate count fields above remain valid for older clients.Do not try to compute per-rank counts by scanning body_condition.panels[].damage_codes. When a panel has both a rank attribute and a regular damage code (the common case — RANK_ONE together with CHANGE), the rank attribute is dropped from damage_codes in favor of the more specific damage. Counting from damage_codes would systematically undercount — use rank_counts, which is tallied before that collapse.
For auction sources, omit this section — they don’t use rank vocabulary.

4. Damage Code Dictionary

The damage_code vocabulary is source-specific. Each inspector emits its own codes — Glovis uses lowercase mnemonics, SK/AJ/Lotte use uppercase letter codes, and the Encar dealer path uses descriptive uppercase tokens. The unified panel.severity and panel.description fields paper over this — those are normalized for display. Use damage_code for icon mapping and case-by-case handling; rely on description for textual rendering.
Practical rendering rule: Map damage_code → icon using the source-specific tables below. Render panel.description as the primary user-visible text. That way new codes that aren’t yet in your icon map degrade to “no icon + correct text” rather than dropping the panel.
The full set of codes you may receive, per inspection_report.source:

4.1 Glovis (source: "glovis")

Lowercase mnemonics derived from Korean damage type names.

4.2 SK (source: "sk")

Uppercase single- or double-letter codes. Codes G, G1, G2 may appear in raw upstream data but are filtered out before reaching the partner API — you will not see them.

4.3 AJ (source: "aj")

Uppercase letter codes. Shares some letters with SK (e.g. X, W) — never mix the two dictionaries; always switch on source first.

4.4 Lotte (source: "lotte")

Lotte uses a code set similar to SK. Treat unknown codes by falling back to description text — the inspector’s free-text describes the damage in English.

4.5 KCar (source: "kcar")

Same fallback rule as Lotte — handle unknown codes gracefully via description. KCar emits a sparse, mostly-letter-code set; expect coverage to grow over time.

4.6 Dealer (Encar) (source: "dealer")

Descriptive uppercase tokens derived from Encar’s outers[].attributes[] raw values. WELD and HILLS are recognized by the server’s severity and description logic for forward-compatibility, but are not currently produced by any upstream mapping. The dealer codes you can actually receive today are CHANGE, METAL, CORROSION, SCRATCH, DAMAGE, and the RANK_* attributes. WELD / HILLS are listed so your renderer tolerates them if they start appearing — fall back to panel.description for any code you don’t recognize.
Rank attrs are stripped from damage_codes when a non-rank code is also present. A panel with ["RANK_ONE", "CHANGE"] upstream emits damage_codes: ["CHANGE"] from this API — the rank attribute is collapsed in favor of the more specific damage code. You will only see RANK_ONE/RANK_TWO/RANK_A/RANK_B/RANK_C in damage_codes when it is the only code for that panel (i.e., when Encar reported a rank with no accompanying statusTypes entry — rare in practice).For per-rank breakdown, do not derive from damage_codes. Use the aggregate counts in inspection_report.dealer_inspection.{critical_frame_damage, exterior_damage}. See section 3.7.

4.7 Severity is server-computed — trust the emitted field

The severity field on each panel is set server-side and is the only signal you should use for color coding. Severity rules differ per source (each source has its own code-to-severity table at ingest time, e.g. Glovis maps wmedium while AJ maps Whigh), and frame panels may be promoted at the unified-mapping layer for some sources. The compounding rules are not stable contract — they may evolve as we ingest new inspectors. What is stable contract: Use panel.severity for color picking. Do not re-derive from damage_code or damage_codes — your local re-derivation will drift from server behavior as we tune the per-source tables, and you’ll either over-color (false alarms) or under-color (silent damage) edge cases. If you need to display a textual rationale alongside the marker, render panel.description — it is the localized English explanation of the panel’s damage state, regardless of source.

5. Panel ID Catalog

panel_id values use two different naming conventions depending on the source: The dealer values are not normalized — they’re whatever Encar’s API returns for that listing. We expose them verbatim so your client can correlate against Encar’s own UI if needed.
Build two PANEL_COORDS maps, one for kebab-case auction panels and one for camelCase dealer panels. Switching on inspection_report.source is the cleanest way to choose. We recognize this asymmetry is friction — a future API revision is planned to add canonical kebab-case IDs alongside the raw values. Until then, your client carries both maps.

5.1 Auction panel IDs (kebab-case)

This is the complete set currently emitted by the auction inspectors. New IDs may be added over time (additive); your client should fall back gracefully on unknowns (see the Note at the end of this section).

Exterior panels

Frame panels

5.2 Dealer panel IDs (camelCase, derived from Encar type.code)

Dealer responses come from Encar’s https://api.encar.com/v1/readside/inspection/vehicle/{id} endpoint. Each outers[] entry has a nested type.code (Encar’s panel identifier, e.g. P062) and a type.title (Korean label). The partner API reads these and emits:
  1. panel_id — translated via the internal Encar panel-code map to a canonical camelCase token (quarterPanelRight for P062, frontFenderLeft for P021). When the upstream type.code is not yet in the map, the raw code passes through verbatim ("P099") so partners still have a stable per-panel identifier.
  2. raw_panel_code — the unmodified Encar type.code value (e.g. "P062"). Always present when upstream provided it.
  3. raw_label_ko — the unmodified Encar type.title value (Korean, e.g. "쿼터 패널(우)"). Always present when upstream provided it.
  4. label — the English label from the map when canonical-mapped, otherwise the raw Korean title.
The canonical map is seeded with the codes observed in real responses and grows additively as new codes are encountered. Adding a code never breaks existing partner integrations.
Handling unknown panel_id values. If your PANEL_COORDS map does not contain the panel_id you receive (because it’s a raw P-code that we haven’t yet added to our canonical map, or a new code Encar emitted that we haven’t seen), fall back to listing the panel by label in a textual “Affected panels” list under the diagram. Use the raw_label_ko field if you want to display the Korean label alongside or instead. Do not drop the panel silently.A pattern that handles both canonical and raw passthrough:
Synthetic panel_${index+1} IDs are rare today — they only appear when Encar’s response omits both type.code and all legacy flat fields, which is unusual. Most dealer panels you receive will have either a canonical camelCase ID or a raw P-code.
The canonical camelCase tokens you can expect to see (set grows as we add map entries): The exact set of camelCase IDs Encar returns varies by listing — we pass through verbatim rather than normalizing, so any value Encar produces is the value you receive. The English panel.label field carries a human-readable rendering when available; when it is not, it falls back to the raw panel_id string.

5.3 Catalog completeness and fallbacks

This catalog reflects the set of IDs currently in use as of the latest release. New IDs may be added (additive — never a breaking change) as inspector data formats evolve. Your client must handle unknown IDs gracefully:
If panel_id arrives that is not in your PANEL_COORDS map, do not drop the panel silently. Fall back to listing it by label in a textual “Affected panels” section under the diagram. The damage is real even when you don’t have a marker position for it; suppressing the entry hides information from your customer.A change-resilient pattern:

6. The Inspection Report card

The card titled “Inspection Report” or Grade” on lmnauto.com. For live comparison, see any auction listing at https://lmnauto.com/en/auction?source=auctions&tab=glovis_<date>_<auction_id>_<lot_id> — the worked example in §11 uses glovis_20260521_1078_1005 (Hyundai Sonata 2020).

6.1 Visual structure

6.2 Response shape

This is an auction (source: "aj") response, so dealer_inspection is omitted entirely from the JSON — it would only appear when source === "dealer".

6.3 Field reference

6.4 category_grades[] rendering

Each row is laid out as:
The “Category label” is human-readable English derived from category:

6.5 checklist[] rendering

The checklist is grouped by group. Render as a collapsible list, with group as section header and one row per item. The result field contains the raw inspector verdict and is often in Korean — display as-is unless you maintain a translation map (see Korean Glossary). Item count by source:
  • Glovis: exactly 17 items. Groups: Engine, Transmission, Brakes, Steering, Electrical, Body, Glass, Interior.
  • AJ: up to 39 items. Same group taxonomy plus suspension, fuel system, cooling system.
  • SK / Lotte / KCar: 5-8 items, sparse coverage.
  • Dealer: always [].

6.6 accident_history[] rendering

Each entry has structured fields (subject to source variation):
Render as a timeline or table. The type field distinguishes “owner_self” (the current/past owner caused it) from “third_party” (someone else was at fault for the damage). Korean carfax convention treats these very differently for pricing.

6.7 issues[] rendering

Normalized “issues found” across all sources. Each entry:
Render as a vertical list of pills with the detail text. Color the pill by status.

6.8 dealer_inspection (dealer-only)

When source === "dealer", this sub-object carries Encar-specific aggregate data:
Render as a small key-value list at the bottom of the report card. The raw Korean strings can be displayed verbatim (your end customers may include Korean speakers) or translated using the Korean Glossary.

7. Overall grade interpretation

The overall_grade field is a two-part string "X/Y". The semantics differ per source. The grade_description field tells you which is which for the current row, but here’s the master decoder: In the badge, render the two parts stacked or with a / separator. The exact pixel layout in the LMN reference UI is a 56×56 square with both characters rendered in a serif font centered.

Pill colors by overall grade

A quick heuristic for badge background:

8. Theming

@lmnauto/inspection-ui v0.2.0+ is fully themeable. Pass a partial theme to any root component — only the keys you set change, everything else keeps the lmnauto.com reference default. An unthemed <InspectionReport> is byte-for-byte unchanged.
Accent fan-out — setting accent also retints the bad-severity count text, the accident “bad” badge, and the CHANGE damage marker, unless you set those tokens explicitly. A single accent gets you most of the way to on-brand.

8.1 CSS-variable escape hatch

Every token is also a --lmn-insp-* CSS custom property on the component’s root, so you can theme from your own stylesheet instead of (or alongside) the prop:
The theme prop wins where both are set. Mind the unit difference: the prop takes a unitless number (radius: 8); the CSS variable needs the unit (--lmn-insp-radius: 8px).

8.2 Token reference

Defaults are the exact lmnauto.com reference colors. Each row is a theme key and a CSS variable. Brand Surfaces & text Severity (dealer count cards & accident text) Accident badges (dealer) Damage markers — set via the damage map: theme={{ damage: { CHANGE: '#…' } }} Shape
v0.2.0 scope: the dealer (encar) path is fully tokenized. On auction listings the shared surface/text, radius, and font tokens apply, but the auction grade badge and body-damage diagram colors are not yet themeable — tracked as a follow-up.

9. Korean Glossary

The following raw Korean strings may appear in dealer_inspection.frame_status, dealer_inspection.panel_status, inspection_report.checklist[].result, and in some accident_history[].description entries. Maintain a client-side translation map if you want English-only UI.

9.1 Status terms

9.2 Category terms (in accident_history[].description)

9.3 Translation strategy

The safest approach is client-side translation with raw fallback — translate known terms, leave unknowns intact:
This keeps you safe when LMN adds new Korean status terms (you’ll see them in raw form rather than dropping them).

10. Full reference renderer (React)

This is a complete, production-ready React component that consumes the JSON and renders both panels. Adapt to your component library — the logic is the contract.

11. Worked example A — Glovis auction (real API response)

This is a verbatim slice of a real GET /v1/vehicles/{id} response from sandbox at the time of writing. Sandbox base URL is https://sandbox-api.lmnauto.com; production is https://api.lmnauto.com (see Quickstart for both). The response shape is identical across environments — sandbox just runs against the staging data snapshot. Request
Response (inspection portion) — note image_url: null and dealer_inspection absent. This is a Hyundai Sonata 2020 with significant frame damage history (overall grade C/1).
Things to notice about this real response (vs. documented ideal):
  • image_url is null for Glovis. Glovis (and K-Car, dealer) have no mirrored image — render the diagram from panels[] directly. SK and Lotte do return a mirrored image_url (damage baked in), and AJ returns a blueprint base image drawn under the markers.
  • accident_summary and accident_reason are null even though has_frame_damage: true. Don’t gate the “Accident History” pill on accident_summary being non-null; use has_accident / has_frame_damage directly.
  • checklist has 48 items, not the canonical “17 items” that older documentation mentions. The count varies per inspection — render whatever the array contains.
  • Some panel.label values are Korean (e.g. "리어휠하우스(좌)") even though others are English. The Korean-to-English mapping is incomplete; display label as-is and translate client-side if you need an English-only UI. See the Korean Glossary.
  • category_grades[].category can be Korean ("동력" in this row) for categories not yet in the English mapping.
  • exterior_summary here describes mechanical issues (engine/transmission), not exterior panels. The field name is historically misleading on Glovis — it’s effectively a free-text “summary of issues found” rather than strictly panel-related.
UI mapping
  • Badge: C/1 on red (C is left, 1 is the worst condition score).
  • Pill: green No Accident (has_accident: false) — but a separate caution callout for has_frame_damage: true is healthier UX, since the car has significant frame welding.
  • Body Inspection card:
    • Counts: Frame 11 panels (mostly medium w, one high xx = rear-panel), Exterior 6 panels (high xx only — five rear/side replacements).
    • Diagram: render from panels[] because image_url is null. Markers: 6 red on exterior silhouette, 1 red + 10 amber on frame silhouette.
  • Category rows: 9 entries — render two reds (“Engine”, “Shift Issue”) and seven greens. The Korean 동력 row renders as-is unless you translate client-side.
  • Checklist: collapsible list with 48 items (group-by-group).
  • Issues Found: 2 entries.
  • Inspector notes block: long run-on string of replacement summaries.
  • No accident_cost_summary, no accident_history entries (the frame damage exists but no structured accident record is currently associated).

12. Worked example B — Encar dealer (real API response)

This is a verbatim slice of a real GET /v1/vehicles/{id} response from sandbox. It is a BMW M5 2019 listing with two ranked exterior panels — a clean worked example of the canonical dealer shape described in §5.2 and §4.6: nested type.code translated to a drawable camelCase panel_id, and statusTypes[] normalized into canonical damage codes. Request
Response (inspection portion) — verbatim from sandbox post-fix.
Things to notice:
  • Both panels have canonical camelCase panel_id values (quarterPanelRight, frontFenderLeft) drawable directly on the standard Encar silhouette.
  • raw_panel_code preserves the upstream Encar P-code (P062, P021) so you can correlate against Encar’s own admin tooling or display the raw value alongside the canonical one.
  • raw_label_ko carries the upstream Korean label verbatim — useful if your customer base includes Korean speakers or for showing both languages side-by-side.
  • damage_code is the canonical normalized code derived from Encar’s statusTypes[] (W → METAL, X → CHANGE) — not the rank attribute. The rank attribute (RANK_TWO, RANK_ONE) remains preserved in the aggregate dealer_inspection.exterior_damage count (2).
  • severity is computed from the canonical damage code: METALmedium (sheet metal repair), CHANGEhigh (replacement). Use the emitted value directly; do not re-derive locally.
  • frame_status: null, panel_status: null for this car — Encar didn’t return the descriptive status strings. Render the dealer summary with placeholder dashes for those fields.
  • insurance_history: 1, insurance_amount: 1370 — own-damage accident history is populated for dealer cars from a separate insurance-record upstream; the amount is whole USD (FX-converted server-side), matching the auction accident_cost_summary convention — don’t re-apply fx_rate. A null (not 0) still means “no data reported”; 0 means “no claims”.
  • vehicle_info, overall_status, photos, certification carry the full inspection-sheet detail. Render vehicle_info as a key-value list, overall_status as a status table, photos as a thumbnail row, and certification as a small attribution line.
UI mapping
  • Badge: slate (no overall_grade). Title: “Encar Dealer Inspection”.
  • Pill: green No Accident (has_accident: false).
  • Two grade rows: green “Accident Grade” + “No structural damage”, amber “Exterior Grade” + “2 exterior damage cases”.
  • Mechanical checklist[] present (engine, transmission, steering, braking, electrical, …, EN-translated); inspector notes present; no auction-only accident-cost summary.
  • Dealer summary block at bottom: frame_status / panel_status dash (null this car); exterior_damage: 2, insurance history (1 claim, $1,370), plus the vehicle_info / overall_status / photos / certification sheet detail carry the real signal.
  • Body Inspection card:
    • Count boxes: Frame 0 (green “No structural damage”), Exterior 2 (red “Major damage” — driven by the high-severity CHANGE on the front-fender-left).
    • Diagram: amber marker on the right quarter panel (quarterPanelRight, METAL/medium), red marker with × overlay on the left front fender (frontFenderLeft, CHANGE/high).
    • Affected panels list: empty — both panels are drawable.
  • Rank summary below diagrams: “Exterior — 2 ranked panels”, “Frame — None”.

13. Edge cases (full list)

Some auction listings haven’t been inspected yet (ingestion can lag by minutes to hours, especially for KCar). Render a neutral empty state: “Inspection report not yet available. Check back in a few hours.” Do not show a “report” card with all blank fields — it implies “we inspected and found nothing”, which is wrong.
Render only the populated card. Specifically:
  • body_condition null but inspection_report populated → no diagram, show the grade card alone with all available fields.
  • body_condition populated but inspection_report null → diagram alone with the count boxes; omit any reference to grade.
If we emit a panel_id not in your PANEL_COORDS map (we extend the catalog as inspector data evolves), do not drop the panel. Render it in a textual list under the diagram via the UnknownPanels component in section 10. The damage is real even if you don’t have a marker position for it.
dealer_inspection.frame_status and panel_status are raw Encar Korean. Either display as-is (your end customers may include Korean speakers) or translate via section 9’s dictionary. The panel_status value sometimes includes a count suffix ("교환 1") — strip and translate the term, preserve the digit.
All monetary fields here are already FX-converted to USD whole integers (computed server-side using the day’s exchange rate). Do not re-convert. If fx_rate on the vehicle response is null, this field is also null.incidents[] (Glovis) lists one row per insurance-settled accident — { date, insurance_paid, repair_cost }. The aggregate insurance_paid equals the sum of incidents[].insurance_paid: rounding to whole USD is applied per incident and then summed, so a per-incident breakdown always reconciles exactly to the total (don’t recompute from the won amounts client-side). When incidents[] is [] (a source with no per-incident detail), fall back to showing the count + aggregate only.
Only Glovis returns image_url. SK / AJ / Lotte / KCar all return null — draw your own diagram from panels[]. Dealer is the same.
Some checklist[].result values may be empty strings (the inspector marked the item but left the result blank). Treat as missing — render the item with a placeholder, do not skip the item.
For dealer rows, upstream Encar data may classify a panel with both a rank attribute (e.g., RANK_ONE) and a damage marker (e.g., CHANGE). When this happens the API collapses damage_codes to the non-rank code(s) only — so you will see damage_codes: ["CHANGE"], not ["RANK_ONE", "CHANGE"].The rank attribute is not lost — it is reflected both in the aggregate counts under inspection_report.dealer_inspection.{critical_frame_damage, exterior_damage} and, per-rank, in inspection_report.dealer_inspection.rank_counts ({ rank_one, rank_two, rank_a, rank_b, rank_c }). rank_counts is tallied from the rank attributes before the damage_codes collapse described above, so it stays accurate even for panels that carry both a rank and a damage code.This means: on a single dealer panel you see one marker on the diagram colored by the panel’s severity (computed from the strongest code present), and the totals beneath the diagram come from dealer_inspection, not from damage_codes.
accident_history may be populated while accident_cost_summary is null (the source recorded an accident but the cost details weren’t captured). Render the history regardless.
Glovis occasionally updates its inspection format (e.g., adds new items). Older inspections may have an item from the previous taxonomy that doesn’t match the current 17-item set. Just render whatever’s in the array; we don’t filter for “canonical” items server-side.

14. Localization

The inspection text is in English by default (translated server-side from Korean source data). For RTL languages (Arabic in particular): For Arabic UI, mirror the layout (badges on the right, summary text left-aligned) and run the English strings through your translation pipeline. The reference UI on lmnauto.com supports Arabic via next-intl; equivalent client-side translation is straightforward.

15. Performance and caching

  • The detail response is cached server-side for 30 minutes per ID (Encar dealer detail) or until the next inspection ingest (auction). Refetching more often than every 5 minutes per car is wasteful.
  • The inspection diagram (image_url) is served from GCS with a 7-day cache header. Safe to use directly in <img src> without your own caching layer.
  • The full response size with inspection populated runs 8-25KB. Keep that in mind if you’re streaming many details client-side.

16. Verification checklist

Before you ship your rendering, verify each of these against the reference UI:
1

Empty state renders correctly

Hit a freshly-scraped Glovis listing where inspection hasn’t been filed yet (body_condition and inspection_report both null). Confirm a single neutral message appears, not an empty card.
2

Dealer-source renders correctly

Hit encar_* ID. Confirm:
  • No overall_grade badge (slate )
  • “Encar Dealer Inspection” source label
  • Dealer summary block at bottom (vehicle info, overall status, photos, certification, insurance history)
  • Rank breakdown table under diagrams
  • Mechanical checklist[] present (EN-translated); inspector notes present; no auction-only accident-cost summary
3

Glovis rich auction renders correctly

Hit glovis_* ID with frame damage. Confirm:
  • overall_grade badge in correct color band
  • Red “Accident History” pill
  • All category rows render with correct status colors
  • Checklist with 17 items, collapsible
  • Accident History with at least one entry
  • Accident Cost section with USD amounts
  • Inspector notes as quote block
  • image_url rendered as <img>, not SVG
4

Severity coloring matches

For at least 3 cars with mixed damage:
  • High-severity panels show red markers
  • Medium-severity show amber
  • Low-severity show yellow outline
  • CHANGE panels have an × overlay
  • Count boxes color-match their max severity
5

Unknown panel fallback works

Manually inject a panel_id not in your PANEL_COORDS (e.g., temporarily delete one entry). Confirm the panel appears in the “X affected panels not shown on diagram” expandable list, not dropped silently.
6

Korean fallback works

For a dealer car, confirm raw Korean frame_status / panel_status either translates correctly or displays as-is (no undefined, no empty render).
7

USD amounts not re-converted

For an auction with accident_cost_summary, confirm the values render exactly as returned — no client-side division by FX, no rounding errors.
8

Refresh behavior

Hit the same car twice within 30 seconds. The second render should produce identical output. If your client adds metadata (timestamp, request ID), exclude it from the comparison.

17. FAQ

Glovis ships a pre-rendered SVG/PNG with damage markers as part of their inspection package; we mirror it to GCS. SK, AJ, Lotte, KCar provide only structured panel data — no diagram image — so we expect the client to render. Encar dealer follows the same pattern (structured outers[] from their API, no diagram). If you can’t build SVG rendering, fall back to listing damaged panels by label and skipping the diagram entirely; the count boxes still convey the high-signal info.
Encar’s inspection API doesn’t return an overall letter grade. They publish the panel attributes and statuses but no composite grade. We could synthesize one (“Letter equivalent to RANK_X count”) but chose not to — it would mix our editorial judgment with raw data, and partners are better served by the raw numbers and a clear “no overall grade” signal.
It’s only as accurate as what Encar’s dealer ecosystem self-reports. Encar inspectors do physically examine cars, and the response now carries near-full detail: vehicle info, overall status, the mechanical checklist[] (engine, transmission, steering, braking, electrical, …), inspection photos, certification, insurance history, and inspector notes. The remaining gap versus an LMN auction inspector’s report is the auction-only accident_history[] per-incident breakdown and accident_cost_summary. For high-stakes decisions (export, customs), encourage your customer to request an LMN secondary inspection — that’s available on the auction tab but not for dealer listings.
Yes — server-side we always emit in this order: frame, exterior, engine, transmission, brakes, suspension, electrical, interior, glass, lighting. Categories not applicable to the source are omitted. Don’t sort client-side; just render in array order.
has_accident = there’s at least one accident in the car’s history (could be a long-ago repair, or a current visible issue). has_frame_damage = there’s structural (frame) damage currently visible. A repaired car may have has_accident: true but has_frame_damage: false. Use both signals for nuanced messaging — “previously repaired” vs “currently damaged” are very different stories to a buyer.
By date descending (most recent first). If a record has a null date (rare), it sorts to the end.
That shouldn’t happen — we dedupe server-side by panel_id. If you see it, file a bug; meanwhile, render the first occurrence and ignore subsequent.
Render the English from accident_reason, exterior_summary, etc. directly. For fields that are raw Korean (dealer_inspection.frame_status, checklist[].result), show both: {translateKR(value)} ({value}) — gives Korean speakers the original and English speakers the translation simultaneously.
Use panel.severity directly; do not infer from panel_type or damage_code. Severity is set server-side per inspector source — each source has its own code-to-severity table at ingest time, and frame-panel promotion (when it happens) varies by source. Local re-derivation will drift from server behavior as we tune the per-source tables. See section 4.7. The stable contract is the set of possible values ("high" \| "medium" \| "low" \| "none") and the color you pick for each, not the rule that produced it.
For auction sources we maintain a Korean-to-English mapping for panel names; when a panel name isn’t in the mapping (typically a niche or recently-added panel), the Korean falls through to panel.label. For dealer sources, panel.label is what Encar’s API returns — usually English or the raw camelCase ID. In both cases, your client should display label as-is and not assume it is always English. If you spot consistently-untranslated values, email integrations@lmnauto.com — additions are quick.
This guide is for v1.18+ (the unified inspection shape that landed alongside the dealer-inspection enrichment). Earlier versions used a flatter structure; consult the Changelog for the migration table.

18. Versioning and stability

This is part of GET /v1/vehicles/{id} and follows our versioning policy:
  • Additive changes (new fields on body_condition.panels[], new fields on inspection_report, new fields on dealer_inspection) ship without a version bump. Your renderer must ignore unknown fields safely.
  • New panel IDs ship without notice (additive). Your PANEL_COORDS should have a graceful fallback.
  • New damage codes ship without notice (additive). Your damage legend should tolerate unknown codes by falling back to panels[].description for display.
  • Removing a field is a breaking change → new major version + 90-day deprecation window + changelog notice.
  • Renaming a field is a breaking change → same policy.
  • Changing a severity rule is treated as additive (the rule is server-side; you receive the computed value). We may move panels between severity buckets — the partner-visible contract is the field name and type, not the computation.
The inspection_report.dealer_inspection sub-object is new in v1.18 (shipped 2026-05-20). Earlier versions of the doc may not show it.

19. Where to look on lmnauto.com

For pixel-faithful comparison, open the same ID in both places — the consumer site at lmnauto.com and the partner API at sandbox-api.lmnauto.com — and diff the JSON against the rendered UI. The IDs in the worked examples are real listings drawn from sandbox at the time of writing; they may roll out of the active inventory window. For a fresh comparison, pick any current ID from GET /v1/vehicles?source=<src>&limit=1 and use that same ID in both URLs. If your rendering ever looks materially different from the lmnauto.com reference, diff against the JSON returned from GET /v1/vehicles/{id} for the same ID rather than trying to reverse-engineer the UI. The JSON is the contract; the UI is one possible rendering of it.

20. Support

If you encounter rendering edge cases this guide doesn’t cover, or you find an inconsistency between the JSON and the reference UI, email integrations@lmnauto.com with:
  • The vehicle ID (auction or dealer)
  • The raw JSON response from GET /v1/vehicles/{id} (paste in full)
  • A screenshot or description of how your UI rendered it
  • A link or screenshot of the corresponding lmnauto.com page
We’ll diagnose within one business day and either patch the rendering guide, fix the data, or both.