posted 2026-07-26 · enrich.vin/blog/how-to-decode-and-enrich-a-spreadsheet-of-vins
How do I decode and enrich a spreadsheet of VINs?
Upload a CSV or XLSX with a VIN column to enrich.vin — every row comes back decoded with the licensed record appended. Reading the structure is free.
Upload a CSV or XLSX with a VIN column to enrich.vin and the file comes back the file it was, plus the record: every row's VIN decoded, and the licensed catalog fields appended — specs, values, history flags, whatever the catalog binds — each with its value, its source, and its timestamp. Reading the format and the per-row structure is free and needs no account; you pay only for the licensed data you append, at a per-row fee stated before the tier transacts. There is no integration to build, no export to reconcile: the columns you sent stay yours, and the record joins them beside column A.
That is the whole no-code path — upload, enrich, download — and the rest of this page is what actually happens to a row in between.
What a row is before you upload it
A spreadsheet of VINs is a spreadsheet of unanswered questions. Ten thousand VINs sit in column A and nothing sits beside them: no trim, no value, no flag. The portfolio gets priced, insured, or floored on rows nobody resolved — the wrong trim valued, the branded title missed, the open recall carried into the book unread. The classic patch is a VLOOKUP against a stale export, which is only as current as the day someone last pulled it and only as complete as the columns that export happened to carry.
Enrichment closes that gap in a single pass. The VIN is the key; the catalog is the join; the returned file is your same rows with the record attached. Nothing about your sheet is restructured — your headers, your order, your extra columns all survive. The append is additive.
What appends per row
The columns people check first append first — the free faces lead, and the cost-bearing faces are the deepening step, never the front door. Concretely, a resolved row can carry:
- decode — year, make, model, trim, style, and drivetrain, resolved to the vehicle the VIN actually encodes. Decode always appends; it is a zero-marginal face read from VIN's own database, and its structure reads free.
- specs — the factory numbers for the trim the car actually is, where the catalog licenses them; this is the same record that reads singly at specs.vin.
- values — the market numbers with the basis behind them, where licensed; the same numbers that read singly at values.vin.
- listings — the live for-sale state of the row, where licensed.
- sticker — the birth-record fields, MSRP and factory options as originally printed, where licensed.
- flags — recall status (free), plus title-brand and odometer-consistency flags where licensed. The full history report is itself a deepening step, priced at its own door, never bundled silently into a row.
Which of these actually render depends entirely on what the catalog licenses for that field, and this page states structure, not coverage. Every appended field carries its value, its source, and its timestamp; a field without a bound license comes back as a stated gap, never a guess. That discipline is the point — an enriched row you cannot trace is worse than an empty one, because it invites a decision you cannot defend.
What happens to a row that does not resolve
Not every VIN is clean. Some are mistyped, some are off by a check digit, some name a vehicle the catalog has no record for. Enrich types those outcomes rather than hiding them: a row comes back resolved, INVALID_VIN, or no record — a stated result in a column, not a silent drop and not an error page. INVALID_VIN is an answer. A no-record row tells you the catalog has nothing bound for that key, which is itself information: you now know which rows to chase by hand instead of assuming the whole file enriched. The check digit certifies the VIN; it never sells you a field it cannot stand behind.
The precision ladder, applied to a batch
VIN's data merchandises the same way whether you read one row or ten thousand. The anonymous base answer — the decode and the per-row structure — is free. An account deepens what a value-class field can say, moving from a point number toward a range with its confidence. Build-level accuracy, with licensed book overlays priced through, is the paid step. In a batch, that ladder shows up as the difference between the columns that always append (decode, structure) and the columns that append only where a license is bound and a fee is stated. You are never charged for the shape of the answer — only for the licensed data inside it.
What it costs, and what it does not keep
Reading the format and the per-row structure costs $0 and needs no account. The batch tier carries a per-row fee, stated on the door before anything transacts, and it does not transact until its compliance gate clears — no price is claimed before then. What appends is what the catalog licenses, and that coverage and price are cataloged at data.vin, not promised here. Your rows are your rows: the enrichment appends and returns the file; it does not retain your portfolio.
If your file is keyed to a provider's own vehicle IDs instead of VINs, the crosswalk comes first — vindex.vin maps provider identifiers to the one YMMTS spine with coverage stated per provider pair, and enrichment runs from the resolved keys. And when you want the same append run programmatically rather than by upload, the identical capability runs by API and MCP — that is the developer-and-agent path, and it returns the same record from the same catalog. Everything appended here traces back to a source you can read at data.vin.
The record, at its other addresses
- data.vinThe pillar door: every field a row can carry, cataloged — coverage, license, price, posted.
- apis.vinThe same enrichment by API and MCP — one key, batch or row at a time.
- vindex.vinRows keyed to a provider's IDs instead of VINs — the crosswalk maps them to the spine.
- values.vinOne row's numbers, read singly: the posted values for any VIN and their basis.
- vhr.vinOne row's history, read in full: what happened to any VIN, posted.
- all.vinEvery door, one record: all.vin/