A full vehicle report for one VIN: decode, recalls, Crit'Air

One paid call returns the VIN decode, the candidate recall campaigns and a Crit'Air class — each block with its own provenance, and an explicit coverage map.

By Matthias Begot · · Updated

An agent vetting a vehicle end-to-end asks three questions: what is this VIN, really? — which recall campaigns may concern it? — where is it allowed to drive? Each has its own Invoket endpoint. When the agent wants all three for the same vehicle, GET /vehicle/report composes them into one response for one x402 settlement: the VIN decode as the anchor, candidate recalls and a Crit’Air class as secondary blocks, each carrying its own provenance, plus an explicit coverage map of anything that could not be produced. Three answers, one payment loop.

Why a composite endpoint exists

For a machine buyer, every paid call is a full loop — receive the 402 challenge, sign, replay, verify. That per-call overhead is fine when the agent has one question; it is pure friction when the questions always travel together, as they do when vetting a single used-car listing or auditing one fleet unit.

The report removes that friction without inventing anything new. It is not a new dataset: internally it orchestrates the same three cores documented on their own pages — VIN decode, recalls and Crit’Air — over local stores and pure calculation, with no network call and no secret at runtime. What the single settlement buys is the composition: one grounded answer per VIN, with a per-block provenance and a coverage map instead of three separate envelopes.

The call: a VIN anchor, optional declared characteristics

The vin is required — it is the anchor of the report, and there is no lookup by licence plate. The Crit’Air characteristics are optional and follow the same declarative contract as the standalone endpoint: supply at least fuel (plus euro_norm or first_registration) to obtain the critair block.

GET /vehicle/report?vin=1HGCM82633A004352&fuel=petrol&euro_norm=euro6

The three blocks have three different contracts:

BlockContractWhat it means
vin_decodeAnchorAlways present; if the VIN cannot decode, there is no report at all
recallsBest-effortSearched by the decoded make and model year; degrades to a coverage.missing entry, never an error
critairConditionalPresent only when usable characteristics were declared

Each block has exactly the shape of its standalone endpoint, provenance included — nhtsa-vpic for the decode, the recall sources for recalls, the regulatory grid and ZFE reference for critair. The root provenance mirrors the anchor; the per-block provenances are what stand for each block. An agent that already parses the standalone responses parses the report for free.

A partial report is a successful, billed answer

The report’s honesty lives in coverage. As soon as the anchor decodes, the call is a 200 and is billed — even when a secondary block is absent. Every absent block is listed in coverage.missing as { block, reason }: "declared characteristics not provided" for a skipped Crit’Air, a make absent from every recall source, a store that was unavailable. The map is never a silent error, and a block is never invented to look complete.

Three consequences worth designing around:

  • Only the anchor can fail the call. A missing or malformed VIN, or a well-formed VIN whose manufacturer is absent from the vPIC tables, leaves the 200 range and is not billed — without a decode there is no report.
  • Secondary blocks never produce a 5xx. Store trouble degrades the block into coverage.missing; the report still ships with what it has.
  • An empty recall list is a present block. “No known recall in the covered sources” is data, not a miss — the missing array is reserved for blocks that could not be produced at all.

Every scope limit of the underlying cores still holds: recalls are candidate campaigns matched on make and year, never a per-VIN verdict; the Crit’Air class is computed from declared, not verified characteristics; sources and freshness are dated per block.

Where it sits in the x402 loop

One report is one standard loop — 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. Read — the decoded identity, the recall candidates, the Crit’Air verdict, and coverage for what is missing and why.
  4. Branch — clear the vehicle, flag campaigns to confirm with the manufacturer, or re-call with declared characteristics to fill the critair block.

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.

Report or standalone calls?

The rule of thumb is the number of questions:

Used for what it is — a composition of three honestly-scoped cores under a single settlement — /vehicle/report turns vetting a vehicle from three payment loops into one. For the full block shapes, coverage semantics and error codes, see the GET /vehicle/report documentation; for how agents discover and call Invoket endpoints, see For agents.