OEM incentives
GEThttps://api.motorsdynamic.com/api/v2/offers
Plan and price
| Plan | Access | Price |
|---|
| Free | No | not included |
| Growth | Yes | $0.005 per call |
| Scale | Yes | $0.003 per call |
| Enterprise | Yes | contract |
A call is billed when it answers 2xx. See pricing.
Parameters
| Name | In | Type | Required | Description |
|---|
make | query | string | no | |
model | query | string | no | |
year | query | integer | no | |
zip | query | string | no | |
offer_type | query | string | no | |
status | query | active or all | no | |
updated_since | query | string (date-time) | no | |
include | query | history | no | history adds each offer's last 50 term changes. |
limit | query | integer | no | |
cursor | query | string | no | page.next_cursor from the previous page, unchanged. |
Example request
curl "https://api.motorsdynamic.com/api/v2/offers?make=Honda&zip=15205&include=history" \
-H "x-api-key: $MD_API_KEY"
const res = await fetch("https://api.motorsdynamic.com/api/v2/offers?make=Honda&zip=15205&include=history", {
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);
import os, requests
res = requests.get(
"https://api.motorsdynamic.com/api/v2/offers?make=Honda&zip=15205&include=history",
headers={"x-api-key": os.environ["MD_API_KEY"]},
timeout=10,
)
res.raise_for_status()
print(res.json())
Example response
{
"data": [
{
"id": 1,
"offer_key": "honda-crv-1",
"make": "Honda",
"model": "CR-V",
"model_year": 2025,
"trim": [
"EX",
"EX-L"
],
"body_style": null,
"model_code": null,
"offer_type": "lease",
"condition": null,
"title": "Lease a 2025 CR-V",
"description": null,
"disclaimer": "Closed-end lease...",
"value_display": "$300/mo",
"image": null,
"geography": {
"postal_code": "15205",
"region": null
},
"terms": {
"cash_amount": null,
"apr": 2.9,
"apr_term_months": null,
"lease_payment": 300,
"lease_term": 36,
"lease_due": 2999,
"msrp": 35000,
"selling_price": null
},
"valid": {
"start_date": "2026-09-01",
"end_date": "2026-09-30"
},
"status": "active",
"removed_at": null,
"version": {
"number": 3,
"last_changed_at": "2026-09-10T00:00:00.000000Z"
},
"first_seen_at": "2026-08-01T00:00:00.000000Z",
"freshness": {
"last_seen_at": "2026-09-24T05:00:00.000000Z",
"observed_at": "2026-09-24T05:00:00.000000Z"
},
"provenance": {
"source": "oem_offers",
"source_id": 4,
"program_id": null,
"vendor": 1
},
"history": [
{
"change_type": "updated",
"field": "apr",
"old_value": "3.9",
"new_value": "2.9",
"changed_at": "2026-09-10T00:00:00.000000Z"
}
]
}
],
"page": {
"limit": 100,
"has_more": false,
"next_cursor": null
},
"meta": {}
}
Response fields
| Field | Type | Description |
|---|
data[] | array of object | |
data[].id | integer | |
data[].offer_key | string or null | |
data[].make | string | |
data[].model | string or null | |
data[].model_year | integer or null | |
data[].trim | object | Trim list or object as published by the OEM. |
data[].body_style | string or null | |
data[].model_code | string or null | |
data[].offer_type | string or null | |
data[].condition | string or null | |
data[].title | string or null | |
data[].description | string or null | |
data[].disclaimer | string or null | |
data[].value_display | string or null | |
data[].image | string or null | |
data[].geography | object | |
data[].geography.postal_code | string or null | |
data[].geography.region | string or null | |
data[].terms | object | |
data[].terms.cash_amount | number or null | |
data[].terms.apr | number or null | |
data[].terms.apr_term_months | integer or null | |
data[].terms.lease_payment | number or null | |
data[].terms.lease_term | integer or null | |
data[].terms.lease_due | number or null | |
data[].terms.msrp | number or null | |
data[].terms.selling_price | number or null | |
data[].valid | object | |
data[].valid.start_date | string or null | |
data[].valid.end_date | string or null | |
data[].status | active or removed | |
data[].removed_at | string or null | RFC 3339 UTC with microseconds. |
data[].version | object | |
data[].version.number | integer | 1 + recorded term changes. |
data[].version.last_changed_at | string or null | RFC 3339 UTC with microseconds. |
data[].first_seen_at | string or null | RFC 3339 UTC with microseconds. |
data[].freshness | object | |
data[].freshness.last_seen_at | string or null | RFC 3339 UTC with microseconds. |
data[].freshness.observed_at | string or null | RFC 3339 UTC with microseconds. |
data[].freshness.age_seconds | integer or null | |
data[].provenance | object | |
data[].provenance.source | oem_offers | |
data[].provenance.source_id | integer or null | |
data[].provenance.program_id | integer or null | |
data[].provenance.vendor | integer or null | |
data[].history[] | array of object | |
data[].history[].change_type | string | |
data[].history[].field | string or null | |
data[].history[].old_value | string or null | |
data[].history[].new_value | string or null | |
data[].history[].changed_at | string or null | RFC 3339 UTC with microseconds. |
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. |
| 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. Full list: errors.