Switch from MotorAPI.dk to Motorbay: endpoints, fields and a checklist
You call MotorAPI.dk today and are considering moving plate and VIN lookups to Motorbay. Here are the differences in access and endpoints, what MotorAPI's documentation says about fields, where the fields live at Motorbay, code before and after, and a plan for switching without guessing.
By Motorbay · Last checked
Who this is for and what changes
This guide is for you if you call MotorAPI for plate or VIN lookups and want to move to Motorbay. Three things change in your code: the address and the key, that plate and VIN lookups are two endpoints, and that environment and equipment are fetched with the vehicle's ID instead of the plate.
We read MotorAPI's documentation and front page on 9 Oct 2026, and everything here about MotorAPI comes from there. Motorbay is a REST API for Danish vehicle data from Motorstyrelsen's public weekly extract. The Danish Motor Register as an API explains what the extract is. Every Motorbay field and path we name is in the OpenAPI document, which is the API's contract.
| MotorAPI | Motorbay | |
|---|---|---|
| Base URL | https://v1.motorapi.dk | https://api.motorbay.app/v1 |
| Key | The X-AUTH-TOKEN header | The X-Api-Key header |
| Plate or VIN lookup | GET /vehicles/{reg-no-or-vin}, one endpoint for both | GET /v1/vehicles/plate/{plate} and GET /v1/vehicles/vin/{vin} |
| Environment | GET /vehicles/{reg-no-or-vin}/environment | GET /v1/vehicles/{vehicleId}/environmental-information and /fuel-types |
| Equipment | GET /vehicles/{reg-no-or-vin}/equipment | GET /v1/vehicles/{vehicleId}/equipment, a paged list |
| List of vehicles | GET /vehicles with registration_number and optional status | GET /v1/vehicles?registrationNumber=, a paged list with no status filter |
| Not found | 404 | 404 with the code VehicleNotFound |
| Usage | GET /usage, free and not counted | No endpoint for your own usage in the OpenAPI document |
| Errors | The documentation mentions 404 and, for /usage, 401 | application/problem+json with a stable code |
What the documentation says about data
MotorAPI's documentation doesn't say where its data comes from or how often it is updated. So we write nothing about that here. Motorbay imports Motorstyrelsen's weekly extract as it is, without correcting or filling in values. Data is data as of the extract's date, not real-time, and every Motorbay response has the Motorbay-Data-As-Of header with the time of the extract you are getting.
If two values don't come from the same date, they can differ. That is the first thing to look for when you compare. Motorstyrelsen gives no support on using the extract and can't guarantee that the updates happen.
Motorbay is not affiliated with Motorstyrelsen. Motorbay serves technical data about vehicles, not about people.
Fields: what is documented, and where they live at Motorbay
MotorAPI's documentation page describes endpoints, key and errors, but not the fields of a response. So we can't give you a table that pairs MotorAPI's field names with Motorbay's without guessing, and we don't. You have the field names in your own code and in the responses you have stored. Use them with the table below, which shows where Motorbay puts each kind of information.
| Information | Motorbay fields | Endpoint |
|---|---|---|
| Plate and VIN | registrationNumber, vin | Vehicle |
| Status | status, statusUpdatedAt, registrationStatus, registrationStatusUpdatedAt | Vehicle |
| First registration | firstRegisteredOn | Vehicle |
| Kind and usage | kind, primaryUsage | Vehicle |
| Make, model and variant | make, model, variant, designationType | Vehicle |
| Color | color | Vehicle |
| Emission standard | emissionStandard | Vehicle |
| Model year, weights, axles, seats, doors and dimensions | modelYear, totalWeight, ownWeight, axleCount, minimumSeats, maximumSeats, numberOfDoors, isCouplingPossible and more | /technical-details |
| Body type | bodyType | /technical-details |
| Cylinders, displacement and power | cylinderCount, displacement, maximumPower | /engine |
| Odometer reading | odometerReading, in thousands of km | /engine |
| Fuels, consumption and CO₂ | fuelType, isPrimary, kilometersPerLiter, electricConsumption, co2Emission | /fuel-types |
| Emissions and particle filter | coEmission, hcPlusNoxEmission, noxEmission, particleEmission, hasParticleFilter | /environmental-information |
| Latest inspection | inspectedOn, type, result, odometerReading | /inspection |
| Equipment | name, originalName, count | /equipment |
How to pair the fields
- Store responses. Take a few hundred responses from MotorAPI from your own log, or call the API for a sample of plates.
- Write down the fields your code reads. Those are the ones that must exist at Motorbay, not every field MotorAPI sends.
- Find each field in the table, and look it up in the OpenAPI document for unit and format.
- Compare the values for the same plates at both, field by field.
Formats at Motorbay
- Names: camelCase. Kind, usage, make, model, variant, color and emission standard are objects with
id,nameandoriginalName.nameis Motorstyrelsen's Danish text, for example Personbil. - Dates: days are named
…Onand areyyyy-mm-dd. Instants are named…Atand are UTC. - Values: status and inspection use fixed values such as
registered,deregistered,approvedandperiodic. They are listed in the OpenAPI document. - IDs: strings. Treat them as opaque.
- Odometer reading: in thousands of km. 228 means about 228,000 km.
- Empty responses:
/inspection,/engineand/environmental-informationanswer 204 with no content when there is nothing to show.
What MotorAPI offers beyond Motorbay
It isn't much, but read the list before you move. Everything here is from MotorAPI's documentation.
- One endpoint for plate and VIN. MotorAPI takes both in
GET /vehicles/{reg-no-or-vin}. At Motorbay you pick the endpoint, so if your code doesn't know what it was given, it has to decide first. - Environment and equipment straight from the plate. At MotorAPI,
/environmentand/equipmenttake the plate or VIN. At Motorbay you look the vehicle up first and use itsid, so a lookup with environment and equipment is three calls. - A status filter on the list. MotorAPI can filter
GET /vehiclesonregistreretorafmeldt. Motorbay'sGET /v1/vehiclesfilters on make, kind, usage, color, model year and plate. ReadregistrationStatuson each vehicle and filter in your code. - A usage endpoint.
GET /usagereturns today's usage and the monthly history without counting against the quota. The OpenAPI document has no endpoint for your own usage.
The two sets of documentation describe a plate lookup differently. MotorAPI describes /vehicles/{reg-no-or-vin} as a lookup of a vehicle that is registered now. Motorbay returns the vehicle registered with the plate now, and if none is, the vehicle with the newest registration status date, where registrationStatus says it is not registered. So include plates of deregistered vehicles in your sample, and read registrationStatus.
Motorbay's OpenAPI document has no webhooks, debt data or insurance data, and MotorAPI's documentation lists none of them either. If you need one of them, that is a different choice, not a switch.
A plate lookup before and after
The examples use the plate AB12345 as a placeholder. First curl. At Motorbay you fetch environment and equipment with the vehicle's id from the first response.
curl -i -H "X-AUTH-TOKEN: $MOTORAPI_TOKEN" \
"https://v1.motorapi.dk/vehicles/AB12345" curl -i -H "X-Api-Key: $MOTORBAY_API_KEY" \
"https://api.motorbay.app/v1/vehicles/plate/AB12345"
# Environment and equipment use the vehicle id from the response above:
curl -H "X-Api-Key: $MOTORBAY_API_KEY" \
"https://api.motorbay.app/v1/vehicles/$VEHICLE_ID/environmental-information"
curl -H "X-Api-Key: $MOTORBAY_API_KEY" \
"https://api.motorbay.app/v1/vehicles/$VEHICLE_ID/equipment" Then JavaScript with fetch. Both functions return null when the plate isn't found. MotorAPI's documentation doesn't say what happens when a limit is reached, so the old code checks only 404 and otherwise res.ok. At Motorbay the code waits for Retry-After once on RateLimitExceeded (60 a minute per key) and gives up on QuotaExceeded, because the month's requests are then used.
async function lookupPlate(plate) {
const res = await fetch("https://v1.motorapi.dk/vehicles/" + encodeURIComponent(plate), {
headers: { "X-AUTH-TOKEN": process.env.MOTORAPI_TOKEN },
});
if (res.status === 404) return null;
if (!res.ok) throw new Error("MotorAPI: HTTP " + res.status);
return res.json(); // the whole object, with the field names you use today
} const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function lookupPlate(plate, retried = false) {
const res = await fetch("https://api.motorbay.app/v1/vehicles/plate/" + encodeURIComponent(plate), {
headers: { "X-Api-Key": process.env.MOTORBAY_API_KEY },
});
if (res.status === 404) return null; // VehicleNotFound
if (res.status === 429) {
const problem = await res.json();
if (problem.code === "QuotaExceeded" || retried) throw new Error("Motorbay: " + problem.code);
await sleep(Number(res.headers.get("Retry-After") ?? 1) * 1000);
return lookupPlate(plate, true);
}
if (!res.ok) throw new Error("Motorbay: HTTP " + res.status);
const vehicle = await res.json();
return {
id: vehicle.id, // use it for /engine, /equipment and the other sub-resources
plate: vehicle.registrationNumber,
vin: vehicle.vin,
registrationStatus: vehicle.registrationStatus, // 'registered', 'deregistered', ...
make: vehicle.make.name,
model: vehicle.model?.name ?? null,
};
} Plates are reused, so a plate can have been on several vehicles. To see them all, use GET /v1/vehicles?registrationNumber=.
Price at your volume
MotorAPI shows its prices on its front page, along with how lookups are counted and billed. Read them there for the current figures. The front page also offers 100 free lookups a day. Which plans Motorbay has, and what they cost, is on Motorbay's pricing page.
At Motorbay you start free with no card, and the paid plans have a set price per month with requests included and then a set price per request. The prices and a calculator are on the pricing page, and they are read from the API, so they aren't typed here.
- Count calls, not lookups. A plate lookup plus environment and equipment is three calls at Motorbay, and each call is a request.
- Call only the endpoints you use. If you only need make, model and VIN, the plate lookup is enough.
- Enter the numbers in the calculator. Take the number of calls per month from your own log, not from an estimate.
Switch in an afternoon: checklist
Run both APIs side by side until you have seen that the differences are the ones you expect.
- Create an account and an API key, and run the curl example with a plate from your own tests.
- Put the lookup in one place. Write a function that returns your own field names, so the rest of your code knows neither MotorAPI's nor Motorbay's names.
- Pair the fields with the table and the steps above, and add only the sub-endpoints you use.
- Split plate and VIN, if your code sends both to the same endpoint today.
- **Read
registrationStatus,** so deregistered vehicles aren't treated as registered. - Run both in parallel. Look up a sample of a few hundred plates from your own log at both, and compare field by field.
- Sort the differences. Typical causes are the extract's date, thousands of km, the spelling of emission standards and equipment, and plates with several vehicles.
- Handle 404, 429 and 204. 404 is
VehicleNotFound, 429 can beRateLimitExceededorQuotaExceeded, and 204 means the sub-resource is empty. - **Store
Motorbay-Data-As-Of** next to what you store, so you know how old your data is. - Move traffic gradually, for example behind a feature flag, and leave the MotorAPI key in place until at least one new extract has arrived.
The sources are Motorstyrelsen's own pages, Motorstyrelsen's extract and Motorbay's API docs.