Decode a VIN before an agent vets a used-car listing

A 17-character VIN encodes manufacturer, assembly country and model year. One offline call decodes it from the public NHTSA vPIC tables, pay per call.

By Matthias Begot ·

An agent vetting a used-car listing holds one strong identifier: the 17-character VIN. Before it trusts anything else the listing claims, it can decode that VIN into grounded facts — who built the vehicle, in which country and region, what model year, and whether the check digit is even consistent. One offline call, GET /vehicle/vin/decode, answers all of that in milliseconds from the public NHTSA vPIC tables, with no account, no API key, and one x402 settlement per answer.

The problem: listings assert, VINs encode

A used-car listing is a set of unverified assertions: a make, a model year, a country of origin, typed by whoever wrote the ad. The VIN printed on the same page is different in kind — it is a structured code whose format is fixed by ISO 3779 and, in the US, 49 CFR Part 565:

  • Positions 1–3 are the World Manufacturer Identifier (WMI) — the registered code for the manufacturer and its region.
  • Position 9 is a check digit, computed from the other sixteen characters, whose purpose is to catch transcription errors.
  • Position 10 encodes the model year, on a code table that repeats every 30 years.

So the cheapest first move for an agent is to decode the VIN and compare: does the listing’s “2019 German-built” claim match what the identifier itself says? A mismatch — a model year off by a decade, a WMI registered to a different manufacturer, a check digit that does not add up — is a red flag the agent gets before spending anything on deeper checks.

The friction is access. Classic auto-data APIs sit behind B2B contracts, sales calls, and monthly minimums — onboarding an autonomous agent cannot complete. Yet the underlying decode data is public: NHTSA publishes the vPIC dataset in the US public domain, including standalone database dumps refreshed monthly. What the agent lacks is not the data but a callable, maintained, pay-per-answer surface over it.

The call: one VIN in, structured facts out

GET /vehicle/vin/decode takes a single vin parameter — 17 characters over the VIN alphabet (no I, O or Q) — and answers from a local snapshot of the vPIC tables. The runtime makes no network call and holds no secret; that is why it responds in milliseconds and is cheap enough to run on every listing.

GET /vehicle/vin/decode?vin=1HGCM82633A004352

The data object carries the decoded facts:

FieldWhat the agent learns
wmiThe resolved World Manufacturer Identifier
manufacturerGlobal manufacturer — always present once a WMI resolves
makeMarque, when it resolves unambiguously
country, regionWhere the vehicle was assembled
model_yearModel year from position 10
check_digit_validWhether the position-9 check digit is consistent
attributesDeterministic positional attributes the tables resolve
coverageWhat could — and could not — be resolved for this VIN

Every response is a UnifiedResponse with provenance: source is nhtsa-vpic, and freshness.kind is snapshot with as_of naming the store dump date that backed the answer. The agent always knows how fresh the tables behind its answer are.

Reading the result honestly

The endpoint is deliberate about what it does and does not claim:

  • A partial decode is a successful answer. If the WMI and a few attributes resolve but the model year cannot be disambiguated, the response is a 200 — billed — with the unresolved fields omitted, never guessed, and coverage.complete: false naming exactly what is missing. The agent paid for the honest state of the tables, not for an invented value.
  • An unknown manufacturer is not sold as an answer. A well-formed VIN whose WMI is absent from the vPIC tables returns a 404 (UNKNOWN_WMI) and is not billed — per the x402 golden rule, the service only settles when it actually answered the question. Malformed VINs (INVALID_VIN) are likewise outside the 200 range and unbilled.
  • The check digit is information, not a gate. check_digit_valid: false does not reject the request; the VIN is still decoded and the call still returns 200. The field exists so the agent can flag a possibly mistyped or altered VIN in the listing — which, for vetting, is precisely the signal worth paying for.
  • Lookup is by VIN only. There is no lookup by licence plate, and no paid B2B registry behind the endpoint — the scope is what the public tables decode deterministically.

Where it sits in the x402 loop

The call follows the same loop as every Invoket endpoint — no signup precedes it:

  1. Discover the endpoint via the live catalog and call it; receive the 402 challenge.
  2. Pay — sign the chosen rail and replay the request.
  3. Decode — read manufacturer, country, model_year, check_digit_valid.
  4. Branch — cross-check the listing’s claims against the decoded facts; flag mismatches; escalate the plausible listings to deeper checks.

The Quickstart walks the full discover → 402 → pay → replay cycle with runnable snippets. Price and accepted rails are not pinned here — they are served live by the catalog; see the endpoint reference for the current figure.

Decode first, then dig deeper

The decode is the entry point to the vehicle family, and its output feeds the next questions an agent asks about the same listing:

  • GET /vehicle/recalls — which recall campaigns may apply, looked up by make/model/year or directly by VIN.
  • GET /vehicle/report — the composite: decode, candidate recalls and Crit’Air in a single x402 settlement.

Used for what it is — a fast, offline, honest decode of a public identifier — /vehicle/vin/decode gives an agent grounded facts about a vehicle before it trusts a listing’s prose. For the full field reference, coverage semantics and error codes, see the GET /vehicle/vin/decode documentation; for how agents discover and call Invoket endpoints, see For agents.