Cost of Ownership

What a car actually costs to run — depreciation, fuel, insurance, maintenance and taxes over a holding period

GET Request
~5ms cached, several seconds cold
1 credit per request

Endpoint

GET https://api.carapi.dev/v1/cost-of-ownership

The third question in the set: Vehicle Valuation answers what is it worth, Time to Sell answers how fast will it move, and this answers what will it cost me to keep.

Read the breakdown, not just the total

Every component carries its own confidence, and they are not equal within a single answer. Collapsing the response to one number throws away the only signal that separates a figure backed by a published dataset from one backed by an authored constant.

ValueWhat it meansTypically
measuredA published dataset covers this exact vehicle — EEA or EPA consumption for the model, year and kW band, an official fuel-price series, a depreciation curve fitted across live comparable listings.depreciation, fuel
estimatedAuthored constants, or data stretched to fit the cohort. Still useful for comparing cars against each other; weaker as an absolute figure.insurance, maintenance, taxesAndFees

The same component can flip between the two across vehicles: fuel is measured for a mainstream diesel with an EEA record and estimated for a rare import that only matched on a neighbouring model year. sampleSize and modelYearUsed on the fuel component tell you which happened.

What's included, what's excluded

ComponentIncludedNot included
depreciationValue lost between today’s market price and the resale price at the end of the horizon, fitted across live comparable listings.Any assumption that you sell at trade-in or auction rather than privately.
fuelEnergy for the resolved drivetrain at the annual distance, priced from a published series and held flat.Price inflation or forecast movement — see fuelPriceFlat.
insuranceThe mandatory cover only: MTPL in CZ/SK/PL, liability at state minimums in the US.Collision, comprehensive, GAP, and any driver-specific loading or no-claims discount.
maintenanceScheduled servicing, wear parts and tyres, rising with age and distance.Accident repairs, unscheduled failures, and warranty work.
taxesAndFeesStatutory charges, itemised: vignettes and roadworthiness tests in CZ/SK/PL; sales tax, registration and title in the US.City entry and congestion charges, tolls, and parking.

Financing interest is never included, in any market. A car bought on credit costs more than this endpoint says, and by an amount only you know.

Query Parameters

ParameterTypeRequiredDescription
makestringRequiredVehicle manufacturer, 1-50 characters (case-insensitive). Common aliases are resolved for you (volkswagen → vw).
modelstringRequiredVehicle model, 1-100 characters. Matched as a base model; trim codes are folded to their series (320d → 3-series).
yearintegerRequiredModel year, 1990 to next year. Required — depreciation is a function of the car’s age, so there is no cohort-wide answer to fall back on.
countryenumRequiredCZ, SK, PL or US (case-insensitive).
fuelenumOptionalpetrol, diesel, electric, hybrid, phev or lpg. Omit it and the drivetrain is inferred from what the market sells for this model and year. lpg is rejected for US.
kwintegerOptionalEngine power in kW, 1-2000. Narrows the depreciation cohort and picks the CZ/SK/PL insurance band. Ignored for US insurance.
kmPerYearintegerOptionalAnnual distance in km, 1,000-200,000. Defaults to 15,000 (CZ/SK/PL) or 19,300 (US, i.e. 12,000 miles).
yearsintegerOptionalHolding period in whole years, 1-15. Default 5.
currencyenumOptionalEUR, CZK, PLN or USD. Defaults to EUR for CZ/SK/PL and USD for US. Not constrained by country.
tokenstringRequiredAPI authentication token.

Every rule above is enforced before the upstream call, so a malformed request fails fast rather than after a round trip.

Request Examples

cURL

curl -X GET \
  "https://api.carapi.dev/v1/cost-of-ownership?make=skoda&model=octavia&year=2019&country=CZ&kw=110&token=YOUR_API_KEY"

JavaScript

const params = new URLSearchParams({
  token: 'YOUR_API_KEY',
  make: 'skoda',
  model: 'octavia',
  year: '2019',
  country: 'CZ',
  fuel: 'diesel',
  kw: '110',
  kmPerYear: '20000',
  years: '3',
  currency: 'CZK'
});

const response = await fetch(
  `https://api.carapi.dev/v1/cost-of-ownership?${params.toString()}`
);
const data = await response.json();

const { currency } = data.assumptions;
console.log(`${data.totals.perMonth} ${currency}/month over ${data.assumptions.years} years`);

// Show the components, not just the total — each carries its own confidence.
for (const [name, part] of Object.entries(data.breakdown)) {
  console.log(`  ${name}: ${part.total} ${currency} (${part.confidence})`);
}

Python

import requests

response = requests.get(
    "https://api.carapi.dev/v1/cost-of-ownership",
    params={
        "token": "YOUR_API_KEY",
        "make": "toyota",
        "model": "camry",
        "year": 2021,
        "country": "US",
        "kmPerYear": 19300,
        "years": 5,
    },
)
data = response.json()

print(f"{data['totals']['total']} {data['assumptions']['currency']} over 5 years")
for name, part in data["breakdown"].items():
    print(f"  {name:15} {part['total']:>7} ({part['confidence']})")

Response Examples

2019 Skoda Octavia in CZ, 5 years (200)

The EU shape: MTPL insurance banded on kW, EEA consumption, no annual passenger-car road tax.

{
  "vehicle": {
    "make": "Skoda",
    "model": "Octavia",
    "year": 2019,
    "fuel": "diesel",
    "kw": 110,
    "requested": { "make": "skoda", "model": "octavia" }
  },
  "country": "CZ",
  "assumptions": {
    "kmPerYear": 15000,
    "years": 5,
    "currentValue": 12800,
    "currency": "EUR",
    "fuelPriceFlat": true
  },
  "totals": { "total": 18092, "perYear": 3618, "perMonth": 302, "perKm": 0.241 },
  "breakdown": {
    "depreciation": {
      "total": 6400,
      "confidence": "measured",
      "method": "market-cross-section",
      "valueBasis": "median",
      "notes": ["Fitted across 1,180 CZ listings of this model aged 4-13 years."]
    },
    "fuel": {
      "total": 5112,
      "confidence": "measured",
      "consumptionL100km": 4.8,
      "consumptionKwh100km": null,
      "provider": "eea",
      "fuelKey": "diesel",
      "modelYearUsed": 2019,
      "kwBand": [100, 120],
      "sampleSize": 42,
      "pricePerUnit": 1.42,
      "priceUnit": "litre",
      "priceCurrency": "EUR",
      "notes": ["Type-approval consumption; real-world use typically runs 10-20% higher."]
    },
    "insurance": {
      "total": 2100,
      "confidence": "estimated",
      "annualPremium": 420,
      "kwBand": [92, 120],
      "notes": ["A comprehensive policy typically runs 2-3x this."]
    },
    "maintenance": {
      "total": 3900,
      "confidence": "estimated",
      "notes": ["Servicing, wear parts and tyres, rising with age. Excludes accident repairs."]
    },
    "taxesAndFees": {
      "total": 580,
      "confidence": "estimated",
      "items": [
        { "label": "Motorway vignette", "total": 460, "recurring": true },
        { "label": "Technical + emissions inspection", "total": 120, "recurring": true }
      ],
      "notes": ["Passenger cars have paid no annual road tax in CZ since 2022."]
    }
  },
  "perYear": [
    { "year": 1, "calendarYear": 2026, "vehicleAge": 7, "depreciation": 1700, "fuel": 1022, "insurance": 420, "maintenance": 620, "taxesAndFees": 116, "total": 3878 },
    { "year": 2, "calendarYear": 2027, "vehicleAge": 8, "depreciation": 1450, "fuel": 1022, "insurance": 420, "maintenance": 700, "taxesAndFees": 116, "total": 3708 },
    { "year": 3, "calendarYear": 2028, "vehicleAge": 9, "depreciation": 1250, "fuel": 1023, "insurance": 420, "maintenance": 780, "taxesAndFees": 116, "total": 3589 },
    { "year": 4, "calendarYear": 2029, "vehicleAge": 10, "depreciation": 1050, "fuel": 1022, "insurance": 420, "maintenance": 880, "taxesAndFees": 116, "total": 3488 },
    { "year": 5, "calendarYear": 2030, "vehicleAge": 11, "depreciation": 950, "fuel": 1023, "insurance": 420, "maintenance": 920, "taxesAndFees": 116, "total": 3429 }
  ]
}

2021 Toyota Camry in US, 5 years (200)

Same shape, different regime — abbreviated to the parts that change. EPA consumption, liability-only insurance that ignores kw, and sales tax landing entirely in year 1.

{
  "vehicle": { "make": "Toyota", "model": "Camry", "year": 2021, "fuel": "petrol", "kw": 151, "requested": { "make": "toyota", "model": "camry" } },
  "country": "US",
  "assumptions": { "kmPerYear": 19300, "years": 5, "currentValue": 21500, "currency": "USD", "fuelPriceFlat": true },
  "totals": { "total": 27490, "perYear": 5498, "perMonth": 458, "perKm": 0.285 },
  "breakdown": {
    "insurance": {
      "total": 3900,
      "confidence": "estimated",
      "annualPremium": 780,
      "kwBand": null,
      "notes": ["US premiums are not power-rated, so kw does not affect this component."]
    },
    "taxesAndFees": {
      "total": 2090,
      "confidence": "estimated",
      "items": [
        { "label": "Sales tax on vehicle value (~6%)", "total": 1290, "recurring": false },
        { "label": "Registration and title", "total": 800, "recurring": true }
      ],
      "notes": [
        "National expected values across 50 state regimes — not a bill for any one state.",
        "Sales tax falls entirely in year 1, following the Edmunds True Cost to Own convention."
      ]
    }
  }
}

A component could not be estimated (404)

missing names which one, and is one of make, model, consumption, fuelPrice, depreciation or insurance.

{
  "error": "Insufficient data to estimate cost of ownership for this vehicle",
  "missing": "consumption",
  "hint": "No EEA consumption record for this model, year and kW band. Omit kw, or try an adjacent model year."
}

Response Fields

FieldTypeDescription
vehicleobjectThe car the figures describe as the upstream resolved it (make, model, year, fuel, kw), plus requested — the make and model as you sent them, after case and alias normalization (volkswagen → vw) but before the upstream’s own resolution. Match against requested, not vehicle.make
countrystringMarket the figures describe
assumptionsobjectWhat the numbers were computed against: kmPerYear, years, currentValue, currency, and fuelPriceFlat. Enough to reproduce or re-scale them
totalsobjecttotal, perYear, perMonth and perKm. Integers except perKm, which carries 3 decimals. total is the sum of the five components and of the perYear rows
breakdownobjectThe five components — depreciation, fuel, insurance, maintenance, taxesAndFees — each with its own total, confidence and notes
perYeararrayOne row per requested year, with the five components and the row total. Not the average repeated: depreciation is steepest early, and one-off charges land in year 1

All money values are integers in assumptions.currency, with one exception: totals.perKm carries 3 decimals.

Market Coverage (4 countries)

Narrower than Time to Sell's 13 markets, and far narrower than Vehicle Valuation's 24. A total needs all five components to exist locally — a fuel-price series, an insurance premium model and the tax regime encoded — not just enough listings to fit a curve.

MarketsInsurance scopeTaxes and feesConsumption
CZ, SK, PLMTPL (third-party liability), banded on engine power — so kw moves this figureVignettes and roadworthiness tests. No annual passenger-car road taxEEA
USLiability-only at state minimums. Not power-rated, so kw is ignored here~6% sales tax on the car's value plus registration and titleEPA

US tax and fee figures are national expected values across 50 state regimes, following the Edmunds True Cost to Own convention — including roughly 6% sales tax on the car's value, charged once in year 1. Sales tax actually ranges from 0% (Oregon, Montana, New Hampshire, Delaware) to over 7%, and registration varies just as widely. Treat the US total as a basis for comparing cars, not as a bill for your state.

Error Codes

400

Bad Request

Missing make/model/year/country, an unsupported country, fuel type or currency, a fuel type the market does not support (lpg in US), or a numeric parameter out of range

403

Forbidden

Invalid or missing API token

404

Insufficient data

A whole component could not be estimated. Act on missing and hint — the answer is cached per query, so retrying the same request unchanged returns the same 404

502

Bad Gateway

The upstream cost-data service answered with an unexpected status or payload

503

Service Unavailable

The upstream cost-data service was unreachable or timed out

Important Notes

  • These are estimates, not quotes. Nothing here is priced for a specific vehicle, driver or policy — insurance in particular assumes a clean record and mandatory cover only, and a real quote will differ.
  • Render confidence per component. A total whose depreciation is measured and whose insurance is estimated is not the same object as one where both are measured, and only the breakdown says which you have.
  • perYear is not totals.perYear repeated. Depreciation is steepest in the first years and one-off charges (US sales tax, registration) land in year 1, so a 1-year horizon is never one fifth of a 5-year one. Use the rows for a cash-flow view and totals for a headline.
  • fuelPriceFlat is always true today: the pump price is held at its observed value for the whole horizon rather than forecast. A rising-price scenario is yours to model, and pricePerUnit gives you the base to model it from.
  • Consumption figures are type-approval (EEA) or combined-cycle (EPA) ratings. Real-world use typically runs 10-20% higher, so the fuel component is a floor rather than a mid-point.
  • Prices are quoted per litre even in the US, so markets stay directly comparable. Divide by 3.785 to sanity-check against a per-gallon price.
  • vehicle.requested echoes the make and model you sent in canonical form — lowercased, aliases resolved (volkswagen → vw), trim codes folded (320d → 3-series) — while vehicle.make/vehicle.model carry the car the upstream resolved. Match your own records against requested, allowing for that normalization.
  • Each request consumes 1 API credit from your monthly allowance, including the 404s and the 400s. Validation happens before the upstream call, so a bad request fails in milliseconds — but it still counts.