# Open recalls

Asks the manufacturer's own VIN recall lookup which safety recalls are open on this car, and which it reports as repaired. Unlike `/recalls/{vin}` this is about the VIN (`scope: vin`, `vin_specific: true`).
The manufacturer is asked when the car has not been checked in the last 7 days; the answer is stored and served until then (`freshness.cached`). Covered makes: Honda, Acura, Chevrolet, GMC, Buick, Cadillac; any other make is `404 open_recalls_not_supported`.
"None open" is only ever a manufacturer answer inside that window: when the manufacturer cannot be reached the answer is `502 source_unavailable`, and a VIN it does not know is `404 vin_not_recognized_by_maker`. Neither is billed. Always show `provenance.manufacturer` and `freshness.checked_at` with the result.

## Endpoint

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

## Plan and price

| Plan | Access | Price |
| --- | --- | --- |
| Free | No | not included |
| Growth | No | not included |
| 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). |

## Example request

curl:

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

JavaScript:

```javascript
const res = await fetch("https://api.motorsdynamic.com/api/v2/openrecalls/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/openrecalls/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.scope` | `vin` |  |
| `data.vin_specific` | `true` |  |
| `data.open_count` | integer | Safety recalls not reported as repaired on this car (unknown statuses included). |
| `data.remedied_count` | integer | Safety recalls the manufacturer reports as repaired. Some manufacturers list only open ones. |
| `data.recalls[]` | array of object | Safety recalls filed with NHTSA, open ones first. |
| `data.recalls[].campaign_id` | string | The manufacturer's own campaign number. |
| `data.recalls[].nhtsa_campaign` | string or null | NHTSA campaign number, for example 21V050000. |
| `data.recalls[].status` | `open` or `remedied` or `unknown` | unknown = the manufacturer gave a status we could not read; never treat it as repaired. |
| `data.recalls[].title` | string or null |  |
| `data.recalls[].description` | string or null |  |
| `data.recalls[].safety_risk` | string or null |  |
| `data.recalls[].remedy` | string or null |  |
| `data.recalls[].recall_date` | string or null |  |
| `data.recalls[].repair_date` | string or null |  |
| `data.recalls[].maker_status` | string or null | The manufacturer's own wording of the status. |
| `data.recalls[].nhtsa_url` | string or null |  |
| `data.other_campaigns[]` | array of object | Special coverage, emission and customer programs. Not safety recalls. |
| `data.other_campaigns[].campaign_id` | string | The manufacturer's own campaign number. |
| `data.other_campaigns[].nhtsa_campaign` | string or null | NHTSA campaign number, for example 21V050000. |
| `data.other_campaigns[].status` | `open` or `remedied` or `unknown` | unknown = the manufacturer gave a status we could not read; never treat it as repaired. |
| `data.other_campaigns[].title` | string or null |  |
| `data.other_campaigns[].description` | string or null |  |
| `data.other_campaigns[].safety_risk` | string or null |  |
| `data.other_campaigns[].remedy` | string or null |  |
| `data.other_campaigns[].recall_date` | string or null |  |
| `data.other_campaigns[].repair_date` | string or null |  |
| `data.other_campaigns[].maker_status` | string or null | The manufacturer's own wording of the status. |
| `data.other_campaigns[].nhtsa_url` | string or null |  |
| `data.notice` | string |  |
| `data.freshness` | object |  |
| `data.freshness.checked_at` | string | When the manufacturer was asked. |
| `data.freshness.cached` | boolean |  |
| `data.freshness.source_updated` | string or null | The manufacturer's own data date, when it gives one. |
| `data.freshness.cache_days` | integer |  |
| `data.provenance` | object |  |
| `data.provenance.source` | `manufacturer_recall_lookup` |  |
| `data.provenance.manufacturer` | string |  |
| `data.provenance.source_url` | 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. |
| 502 | `error` | See the message. |
| 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).
