# New units and in-transit

The new cars that belong to one physical store, wherever they are listed. Group sites list the
whole group's pooled inventory, so each car is attributed to its store by the per-car rooftop on
the listing (rooftop_attribution), not by the site. Status comes from the store's OEM inventory row
when that brand's feed was read in the last 36 hours, else from the dealer site's own per-car flag,
else `unknown`. `in_transit` covers cars in production and on the way (`stock_status_detail` says
which). `expected_arrival` is the source's date when it gives one (OEM delivery date, or the start
of the dealer site's ETA window); `expected_arrival_end` is the end of that window. Dealer sites do not
always update a car's ETA, so `arrival_overdue` is true for a car the source still calls in transit
after its whole window (or its single date) has passed: treat that date as stale. Sorted by VIN.

## Endpoint

```
GET https://api.motorsdynamic.com/api/v2/dealers/{domainId}/new-units
```

## Plan and price

| Plan | Access | Price |
| --- | --- | --- |
| Free | No | not included |
| Growth | No | not included |
| Scale | No | not included |
| 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 |
| --- | --- | --- | --- | --- |
| `domainId` | path | integer | yes | Site id (`id` from GET /dealers). |
| `stock_status` | query | `in_stock` or `in_transit` or `unknown` | no |  |
| `make` | query | string | no | Case-insensitive exact match. |
| `limit` | query | integer | no |  |
| `cursor` | query | string | no | `page.next_cursor` from the previous page, unchanged. |

## Example request

curl:

```bash
curl "https://api.motorsdynamic.com/api/v2/dealers/101/new-units" \
  -H "x-api-key: $MD_API_KEY"
```

JavaScript:

```javascript
const res = await fetch("https://api.motorsdynamic.com/api/v2/dealers/101/new-units", {
  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/dealers/101/new-units",
    headers={"x-api-key": os.environ["MD_API_KEY"]},
    timeout=10,
)
res.raise_for_status()
print(res.json())
```

## Response fields

| Field | Type | Description |
| --- | --- | --- |
| `data[]` | array of object |  |
| `data[].vin` | string |  |
| `data[].year` | integer or null |  |
| `data[].make` | string or null |  |
| `data[].model` | string or null |  |
| `data[].trim` | string or null |  |
| `data[].stock_number` | string or null |  |
| `data[].stock_status` | `in_stock` or `in_transit` or `unknown` |  |
| `data[].stock_status_detail` | `in_stock` or `in_transit` or `in_production` or `null` |  |
| `data[].status_source` | string or null | 'oem:<feed>' (for example oem:kia.com) or 'dealer_site'; null when unknown. |
| `data[].expected_arrival` | string or null |  |
| `data[].expected_arrival_end` | string or null | End of the dealer site's ETA window; null when the source gives a single date or none. |
| `data[].arrival_overdue` | boolean | True when the car is still in transit after expected_arrival_end (or expected_arrival) has passed. |
| `data[].store_domain_id` | integer |  |
| `data[].store_name` | string or null |  |
| `data[].listed_on[]` | array of integer | Every MD site id whose dealer-site listing shows this VIN. |
| `data[].url` | string or null |  |
| `data[].last_seen_at` | string or null |  |
| `page` | object |  |
| `page.limit` | integer |  |
| `page.has_more` | boolean |  |
| `page.next_cursor` | string or null |  |
| `meta` | object |  |

## 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. |
| 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).
