GET /vehicle/co2

Resolves a European vehicle into its type-approval CO2 emissions and the technical characteristics published alongside them: WLTP grams per kilometre, fuel, engine capacity, power and mass in running order. The answer is served from a local store built from the official EU CO2 monitoring dataset (Regulation (EU) 2019/631, new registrations reported by member states), so a lookup resolves in milliseconds with no network call and no secret at request time.

Use it when an agent needs a grounded figure before pricing, importing or comparing a vehicle — “what CO2 was this car type-approved at?”, “what does it weigh?” — typically as the technical base of a French registration tax costing, which is priced on exactly these two figures. See the live /catalog for the authoritative endpoint listing and price.

The differentiator is not the number, it is the precision the number was matched at. Every response opens with a match_level that says whether the figure belongs to one type-approval or to a whole model-year population — and at model-year level it carries a p10/p50/p90 dispersion instead of pretending a single figure fits every powertrain sold under that name. A European VIN does not carry the type-approval variant, so a VIN can never buy the precise form: that limit is stated, never worked around.

x402 golden rule: the agent pays for the answer to its question. A key the dataset matches is a billed 200 — including a genuine 0 g/km for a battery electric vehicle. Only requests the service cannot answer — no key, both key forms at once, an incomplete approximate key, a year outside the ingested window, a vehicle absent from the dataset — leave the 200 range and are not billed.

Parameters

Two mutually exclusive key forms, as query parameters. Mixing them is a 400, and the approximate form needs all three of its parts.

ParameterTypeRequiredDescription
type_approvalstringprecise formEU type-approval number as published (e.g. e2*2007/46*0624*10) — the precise key
variantstringno (precise form)Narrows the type-approval to one variant
versionstringno (precise form)Narrows the type-approval to one version
makestringapproximate formMake; short forms and member-state spellings are folded (VW reaches VOLKSWAGEN VW)
modelstringapproximate formCommercial name as reported to the EU registry (Clio); case and accents folded
yearintapproximate formRegistration year (YYYY) within the ingested window; outside it is a 404 naming the years served
GET /vehicle/co2?make=Renault&model=Clio&year=2021
GET /vehicle/co2?type_approval=e2*2007/46*0624*10

make, model and year go together: two of the three is a 400 naming the one that is missing. A year outside the window is a 404 that names the years actually served rather than returning a silent miss.

200 response — UnifiedResponse

{
  "data": {
    "match_level": "model_year",
    "vehicle": { "...": "..." },
    "co2": { "...": "..." },
    "coverage": { "...": "..." },
    "limits": ["..."]
  },
  "provenance": {
    "source": "eea-co2-monitoring",
    "fetched_at": "2026-07-30T18:29:19Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-07-28T00:00:00Z" }
  }
}

Fields of data

FieldTypeDescription
match_levelstringRead this first: the precision the figures were matched at (see below)
vehicleobjectThe matched vehicle: make, commercial_name, year, fuel, engine_capacity_cm3, engine_power_kw, mass_kg, plus manufacturer / type_approval / wheelbase_mm on the precise form
co2objectThe emission figures (see below)
coverageobjectyears_covered (the ingested window), years_observed for the matched key, versions_aggregated, min_sample
limitsstring[]The four fixed reading limits carried by every answer

A field the source does not carry is omitted, never served null — a Tesla has no engine_capacity_cm3, and that absence is the fact.

match_level — the precision you bought

ValueMeaning
type_approval_exactOne type-approval, narrowed by variant/version — unique published values
type_approval_partialVersions of one type-approval, aggregated by registration-weighted median; variant and version are then omitted on purpose
model_yearSeveral powertrains sold under one make/model/year — the only level that carries p10/p90

co2

FieldTypeDescription
wltpobjectp50 always; p10 and p90 at model_year, where a single figure would be wrong at both ends
nedcintCorrelated NEDC value, only where the source publishes it (registrations before the WLTP switchover) — absent is not zero
unitstringg/km
sample_sizeintNumber of registrations behind the aggregate
low_samplebooltrue when the aggregate sits below coverage.min_samplekept but stated, never presented as a measurement

0 is a real value, an absent block is not. A battery electric vehicle is type-approved at 0 g/km and the response says so; a vehicle with no WLTP measurement omits the wltp block entirely. Never read one as the other.

Example — an approximate key, aggregated over a model year

GET /vehicle/co2?make=Renault&model=Clio&year=2021 — one commercial name covering many powertrains, so the answer is a model_year aggregate with its dispersion:

{
  "data": {
    "match_level": "model_year",
    "vehicle": {
      "make": "RENAULT",
      "commercial_name": "CLIO",
      "year": 2021,
      "fuel": "PETROL",
      "engine_capacity_cm3": 999,
      "engine_power_kw": 67,
      "mass_kg": 1171
    },
    "co2": {
      "wltp": { "p50": 118, "p10": 99, "p90": 120 },
      "unit": "g/km",
      "sample_size": 200122,
      "low_sample": false
    },
    "coverage": {
      "years_covered": [2018, 2019, 2020, 2021, 2022],
      "versions_aggregated": 427,
      "min_sample": 5
    },
    "limits": [
      "type-approval values under the WLTP procedure, not real-world fuel consumption (OBFCM data is out of scope)",
      "statistical aggregate of new registrations reported by member states, not a manufacturer datasheet",
      "no VIN to variant/version link: a European VIN does not carry the variant outside manufacturer databases",
      "regulated pollutants (NOx, particulates) are not covered"
    ]
  },
  "provenance": {
    "source": "eea-co2-monitoring",
    "fetched_at": "2026-07-30T18:29:19Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-07-28T00:00:00Z" }
  }
}

427 versions sit behind that median, and p10: 99 / p90: 120 say how far apart they are. An agent that needs one exact figure must buy the precise form — not round the median.

Example — the precise key

GET /vehicle/co2?type_approval=e2*2007/46*0624*10 matches one type-approval whose versions are aggregated, so variant and version are omitted on purpose and no dispersion is served:

{
  "data": {
    "match_level": "type_approval_partial",
    "vehicle": {
      "type_approval": { "number": "e2*2007/46*0624*10" },
      "manufacturer": "PSA AUTOMOBILES SA",
      "manufacturer_eu": "PSA",
      "make": "CITROEN",
      "commercial_name": "BERLINGO",
      "fuel": "DIESEL",
      "fuel_mode": "M",
      "engine_capacity_cm3": 1499,
      "engine_power_kw": 75,
      "mass_kg": 1505,
      "wheelbase_mm": 2785
    },
    "co2": {
      "wltp": { "p50": 140 },
      "unit": "g/km",
      "sample_size": 23118,
      "low_sample": false
    },
    "coverage": {
      "years_covered": [2018, 2019, 2020, 2021, 2022],
      "years_observed": { "from": 2021, "to": 2022 },
      "versions_aggregated": 61,
      "min_sample": 5
    }
  },
  "provenance": {
    "source": "eea-co2-monitoring",
    "fetched_at": "2026-07-30T18:29:19Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-07-28T00:00:00Z" }
  }
}

years_observed reports the registration years actually seen for that key — narrower than years_covered, and never confused with it.

Example — a battery electric, and a correlated NEDC value

GET /vehicle/co2?make=Tesla&model=Model 3&year=2021 returns a genuine zero, served as a figure like any other:

"co2": {
  "wltp": { "p50": 0, "p10": 0, "p90": 0 },
  "nedc": 0,
  "unit": "g/km",
  "sample_size": 99158,
  "low_sample": false
}

GET /vehicle/co2?make=VW&model=Golf&year=2019 shows the same block on a pre-switchover year, where the source publishes both procedures — and the short make folded to the registry spelling ("make": "VOLKSWAGEN VW"):

"co2": {
  "wltp": { "p50": 138, "p10": 128, "p90": 169 },
  "nedc": 113,
  "unit": "g/km",
  "sample_size": 535576,
  "low_sample": false
}

The 41-gram gap between nedc and wltp is exactly why a model that quotes “the CO2 of a 2019 Golf” from memory is unusable for a tax computation: the two procedures do not answer the same question, and only the WLTP figure feeds the French registration tax.

What this endpoint refuses to do

The four limits are returned with every answer, because they are the reading instructions, not a disclaimer:

  • type-approval values under the WLTP procedure, not real-world fuel consumption (OBFCM data is out of scope);
  • a statistical aggregate of new registrations reported by member states, not a manufacturer datasheet;
  • no VIN → variant/version link: a European VIN does not carry the variant outside manufacturer databases, so a VIN-keyed answer is always model_year;
  • no regulated pollutants (NOx, particulates).

Nor is this a market valuation, a price quote or a purchase recommendation.

Freshness

Answers are served from a snapshot of the EU monitoring dataset, dated by freshness.as_of. The ingested window (coverage.years_covered) is the machine truth of which registration years are served — a request outside it is a 404 that names them, never a silent miss and never a 5xx.

Errors

Only requests the service cannot answer leave the 200 range — none of them are billed.

StatuscodeCase
400INVALID_INPUTNo key; type_approval combined with make/model/year; an incomplete approximate key
404YEAR_OUT_OF_WINDOWThe requested year is outside the ingested window (the message names the window)
404NOT_FOUNDNo aggregate for that make/model/year, or no record for that type-approval
500INTERNALInternal error (detail logged, not exposed)
{ "error": "the approximate key needs all of 'make', 'model' and 'year' (missing: year)", "code": "INVALID_INPUT" }
{ "error": "year 2030 is outside the ingested window (covered years: 2018-2022)", "code": "YEAR_OUT_OF_WINDOW" }
{ "error": "no type-approval record for 'e2*2007/46*0624*10' (variant 'ZZZZ') in the ingested window", "code": "NOT_FOUND" }

Attribution

Emission and characteristic data are derived from the EU CO2 monitoring dataset published under Regulation (EU) 2019/631 (European Environment Agency / European Commission), reused under its open licence.

See also

  • GET /vehicle/tax — what registering that vehicle costs in France, priced on exactly these figures.
  • GET /vehicle/report — one VIN, one settlement: decode, recalls, CO2, registration tax and Crit’Air in a single report.
  • GET /vehicle/critair — Crit’Air class and low-emission-zone restrictions from declared characteristics.
  • For agents — discovery surfaces, the live /catalog and how settlement works.