# Total cost of ownership

Depreciation from market asking prices of the model by model year, EPA fuel cost, and insurance and maintenance assumptions that are labelled and can be replaced. Taxes and fees are added with `zip`, loan interest with `apr`.

## Endpoint

```
GET https://api.motorsdynamic.com/api/v2/tco/{vin}
```

## Plan and price

| Plan | Access | Price |
| --- | --- | --- |
| Free | No | not included |
| Growth | Yes | $0.05 per call |
| Scale | Yes | $0.03 per call |
| Enterprise | Yes | contract |

A call is billed when it answers 2xx. See [pricing](https://developers.motorsdynamic.com/pricing.md).

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `vin` | path | string | yes | 17-character VIN (case-insensitive). |
| `zip` | query | string | no | 5-digit ZIP code of a US state or DC. |
| `price` | query | number | no | Price to compute on. Default: the dealer's advertised price. |
| `annualMiles` | query | integer | no | Miles driven a year. |
| `insuranceAnnual` | query | number | no | Annual insurance premium. Default: a published national average. |
| `maintenancePerMile` | query | number | no | Maintenance, repair and tire cost per mile. Default: a published national average. |
| `apr` | query | number | no | APR in percent. Default: the market estimate for the credit tier. |
| `term` | query | integer | no | Loan term in months. |
| `down` | query | number | no | Cash down payment. |
| `tradeIn` | query | number | no | Trade-in value. |
| `rebate` | query | number | no | Manufacturer rebate applied to the price. |
| `docFee` | query | number | no | Dealer documentation fee. Default: the fee crawled with the car's listing. |

## Example request

curl:

```bash
curl "https://api.motorsdynamic.com/api/v2/tco/1HGCM82633A004352" \
  -H "x-api-key: $MD_API_KEY"
```

JavaScript:

```javascript
const res = await fetch("https://api.motorsdynamic.com/api/v2/tco/1HGCM82633A004352", {
  headers: { "x-api-key": process.env.MD_API_KEY },
});
if (!res.ok) throw new Error(`${res.status} ${(await res.json()).error}`);
const data = await res.json();
console.log(data);
```

Python:

```python
import os, requests

res = requests.get(
    "https://api.motorsdynamic.com/api/v2/tco/1HGCM82633A004352",
    headers={"x-api-key": os.environ["MD_API_KEY"]},
    timeout=10,
)
res.raise_for_status()
print(res.json())
```

## Response fields

| Field | Type | Description |
| --- | --- | --- |
| `meta` | object |  |
| `data` | object |  |
| `data.vin` | string |  |
| `data.vehicle` | object |  |
| `data.vehicle.year` | integer or null |  |
| `data.vehicle.make` | string or null |  |
| `data.vehicle.model` | string or null |  |
| `data.vehicle.trim` | string or null |  |
| `data.zip` | string or null |  |
| `data.state` | string or null |  |
| `data.estimate` | `true` |  |
| `data.years[]` | array of object |  |
| `data.years[].year` | integer |  |
| `data.years[].depreciation` | number |  |
| `data.years[].depreciation_basis` | `market` or `default_curve` |  |
| `data.years[].value_end_of_year` | number |  |
| `data.years[].fuel` | number or null |  |
| `data.years[].insurance` | number |  |
| `data.years[].maintenance_and_repairs` | number |  |
| `data.years[].taxes_and_fees` | number |  |
| `data.years[].finance_interest` | number |  |
| `data.years[].total` | number |  |
| `data.total` | object |  |
| `data.total.depreciation` | number |  |
| `data.total.fuel` | number or null |  |
| `data.total.insurance` | number |  |
| `data.total.maintenance_and_repairs` | number |  |
| `data.total.taxes_and_fees` | number |  |
| `data.total.finance_interest` | number |  |
| `data.total.total` | number |  |
| `data.total.cost_per_mile` | number |  |
| `data.terms` | object |  |
| `data.terms.ownership_years` | integer |  |
| `data.terms.price` | number |  |
| `data.terms.price_source` | `query` or `dealer_advertised` |  |
| `data.terms.annual_miles` | object | One input of the ownership-cost estimate, with where it came from. |
| `data.terms.insurance_annual` | object | One input of the ownership-cost estimate, with where it came from. |
| `data.terms.maintenance_per_mile` | object | One input of the ownership-cost estimate, with where it came from. |
| `data.terms.fuel` | object |  |
| `data.terms.depreciation` | object |  |
| `data.terms.taxes_and_fees` | object |  |
| `data.terms.financing` | object |  |
| `data.disclosure` | string |  |

## Errors

| Status | Code | When |
| --- | --- | --- |
| 400 | `invalid_parameter` | A parameter is missing or malformed. The message names it. |
| 401 | `invalid_api_key` | The key is missing, revoked or mistyped. |
| 402 | `plan_required` | The endpoint is on a higher plan. The body names the plan and links to the upgrade. |
| 403 | `not_entitled` | The key may not read this dealer or source. |
| 404 | `not_found` | Nothing matches the identifier in the path. |
| 429 | `rate_limited or quota_exceeded` | Slow down (see `Retry-After`), or the Free monthly calls are used up. |
| 503 | `error` | See the message. |
| 504 | `query_timeout` | The query passed its 4 second budget. Narrow the filters. Not billed. |

Every error has the same body: `{ "error": "<code>", "message": "..." }`. Full list: [errors](https://developers.motorsdynamic.com/docs/errors.md).
