Skip to content

Switch from Synsbasen API to Motorbay: endpoints, fields and a checklist

You call the Synsbasen API today and are considering moving plate and VIN lookups to Motorbay. Here are the differences in access, response shape and fields, what Synsbasen offers beyond Motorbay, code before and after, and a plan for switching without guessing.

By · Last checked

Who this is for and what changes

This guide is for you if you call the Synsbasen API and mostly use a vehicle's basic data: plate, VIN, status, make, model, variant, latest inspection and technical data. Then you can usually move to Motorbay in an afternoon. If you use Synsbasen's debt data, insurance, appraisals, monitoring or statistics, read the section on what Synsbasen offers beyond Motorbay before you go on.

We read Synsbasen's documentation and front page on 9 Oct 2026, and everything here about Synsbasen 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 we name is in the OpenAPI document, which is the API's contract.

Synsbasen Motorbay
Base URLhttps://api.synsbasen.dk/v1https://api.motorbay.app/v1
KeyAuthorization: Bearer <APIKEY> and Content-Type: application/jsonX-Api-Key: <key>
Plate lookupGET /v1/vehicles/registration/:registrationGET /v1/vehicles/plate/{plate}
VIN lookupGET /v1/vehicles/vin/:vinGET /v1/vehicles/vin/{vin}
ID lookupGET /v1/vehicles/:id, the ID is an integerGET /v1/vehicles/{id}, the ID is a string
Response shapeThe object is inside dataThe vehicle is the response itself. Lists have data and metadata
Field namessnake_case, for example first_registration_datecamelCase, for example firstRegisteredOn
More informationexpand[]=emission and other expansions in the same callSeparate endpoints per vehicle, for example /engine and /inspection
DatesStrings like yyyy-mm-ddDays as …On and UTC instants as …At
ErrorsHTTP status codes 400, 401, 403, 404, 429 and 500application/problem+json with a stable code, for example VehicleNotFound

Same source, different corrections

Both build on Motorstyrelsen's weekly extract. Synsbasen says it mainly relies on the extract and adds debt, insurance and inspections from other sources. Motorbay imports the extract as it is, without correcting or filling in values. Synsbasen, on the other hand, says it corrects and fills in values such as model year and EC type approval. So a value can differ between the two even though both come from the same file.

Data is data as of the extract's date, not real-time. Every Motorbay response has the Motorbay-Data-As-Of header with the time of the extract you are getting. 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.

Field map: from Synsbasen to Motorbay

The tables follow Synsbasen's vehicle object and its expansions. The Endpoint column says where the Motorbay field lives: Vehicle is the response to a lookup by plate, VIN or ID, and the others are endpoints under /v1/vehicles/{vehicleId}. Where it says Closest field, it is the best match in both sets of documentation, but neither says it is the same thing. Compare them on a sample before you rely on them.

The vehicle

Synsbasen Motorbay Endpoint Note
ididVehicleAn integer at Synsbasen, a string at Motorbay. Don't assume the values are equal. Look up by plate or VIN and store Motorbay's ID.
registrationregistrationNumberVehiclenull when the vehicle has no plate.
vinvinVehicleSame name.
first_registration_datefirstRegisteredOnVehicleA day, or null.
statusstatusVehicleDanish strings at Synsbasen, fixed values at Motorbay. See the value table.
status_updated_atstatusUpdatedAtVehicleAn instant in UTC, not only a day.
registration_statusregistrationStatusVehicleSee the value table.
registration_status_updated_atregistrationStatusUpdatedAtVehicleAn instant in UTC, or null.
kindkindVehicleAn object with id, name and originalName. The name is Danish, for example Personbil, so read kind.name.
usageprimaryUsageVehicleClosest field. An object like kind. Motorbay also has GET /v1/vehicles/{vehicleId}/secondary-usages.
brandmakeVehicleAn object, read make.name.
model, variantmodel, variantVehicleObjects, or null when the vehicle has none.
versiondesignationTypeVehicleClosest field. Motorstyrelsen's type designation, an object or null.
brand_id, model_id, variant_idmakeId, modelId, variantIdVehicleStrings in both. Compare the values before you use them as keys.
color (under expand[]=body)colorVehicleAn object, read color.name. At Motorbay the color is on the vehicle itself.
model_yearmodelYear/technical-detailsAt Motorbay the value from the extract. Synsbasen corrects and fills it in.
categorytypeApprovedCategory/technical-detailsClosest field.
fuel_typefuelType.name/fuel-typesOne value at Synsbasen, a list at Motorbay with the primary fuel first. The names are Danish, for example Benzin.
mileageodometerReading/engineClosest field. Motorbay gives thousands of km: 228 means about 228,000 km. Synsbasen's unit is km.
ncap_fivehasFiveStarNcapRating/technical-detailsTrue or false.
eu_version, eu_varianteuVersion, euVariant/technical-detailsSame content, new names.
ec_type_approvaltypeApprovalNumber/technical-detailsClosest field. Motorbay has no corrected version like ec_type_approval_corrected.
extra_equipmentadditionalEquipment/technical-detailsClosest field.
body_typebodyType/technical-detailsA fixed list of values, for example sedan, hatchback and stationcar.

Latest inspection

Synsbasen Motorbay Endpoint Note
last_inspection_dateinspectedOn/inspectionA day.
last_inspection_resultresult/inspectionSee the value table.
last_inspection_kindtype/inspectionSee the value table.
mileage (on /v1/inspections/:id)odometerReading/inspectionClosest field. Synsbasen gives km, Motorbay thousands of km.
Not in the same objectstatus, statusUpdatedOn/inspectionThe inspection's status and the day it changed. The value is always active today.

At Synsbasen the three last_inspection_* fields sit on the vehicle. At Motorbay the latest inspection is a call of its own, and it answers 204 with no content when there is no inspection to show. Treat 204 as "no inspection", not as an error.

Engine, environment and fuels

Synsbasen Motorbay Endpoint Note
emission.co2co2Emission/fuel-typesClosest field. g/km per fuel. Don't use co2Emission from /environmental-information, it is a figure for lorries in g/tkm.
emission.cocoEmission/environmental-informationmg/km.
emission.hc_plus_noxhcPlusNoxEmission/environmental-informationmg/km.
emission.noxnoxEmission/environmental-informationmg/km.
emission.particlesparticleEmission/environmental-informationmg/km.
emission.particle_filterhasParticleFilter/environmental-informationTrue or false.
emission.smoke_density, emission.smoke_density_engine_speedsmokeDensity, smokeDensityRpm/environmental-informationThe same two quantities.
emission.euronormemissionStandardVehicleAn object, read emissionStandard.name. The spelling can differ: Synsbasen's documentation shows Euro V, Motorbay's OpenAPI gives Euro 6 as an example.
engine.engine_powermaximumPower/enginekW in both.
engine.engine_displacementdisplacement/enginecm³ in both.
engine.cylinderscylinderCount/engineSame content.
engine.engine_codeengineMarking/engineClosest field.
engine.top_speedmaximumSpeed/technical-detailskm/h.
engine.gearsnumberOfGears/technical-detailsSame content.
engine.fuel_efficiencykilometersPerLiter/fuel-typeskm/l. Synsbasen gives one combined figure, Motorbay one per fuel.
engine.electricity_efficiencyelectricConsumption/fuel-typesWh/km at Motorbay. Synsbasen's documentation uses Wh/km under engine and km/kWh under fuel_types, so check the unit.
fuel_types[].name, primary_fuel, fuel_cellfuelType.name, isPrimary, hasFuelCell/fuel-typesA paged list, primary fuel first.

Weight, dimensions and equipment

Synsbasen Motorbay Endpoint Note
weight.technical_total_weighttechnicalTotalWeight/technical-detailskg.
weight.total_weighttotalWeight/technical-detailskg.
weight.vehicle_weightownWeight/technical-detailsClosest field. kg.
weight.driveable_weight_minimum, weight.driveable_weight_maximumminimumRoadWorthyWeight, maximumRoadWorthyWeight/technical-detailsClosest field. Kerb weight, kg.
weight.road_train_weightroadTrainWeight/technical-detailskg.
weight.coupling_deviceisCouplingPossible/technical-detailsClosest field. True or false.
weight.trailer_with_brakes_weight_maximum, weight.trailer_without_brakes_weight_maximumcouplingWeightWithBrakes, couplingWeightWithoutBrakes/technical-detailskg.
weight.trailer_total_weight_maximumtrailerTotalWeight/technical-detailskg.
axle.axlesaxleCount/technical-detailsSame content.
axle.axle_trackaxleDistance/technical-detailsClosest field. mm.
axle.pulling_axlesdrivingAxles/technical-detailsClosest field. String.
body.doors, body.passengersnumberOfDoors, passengerCount/technical-detailsIntegers.
body.seats_minimum, body.seats_maximumminimumSeats, maximumSeats/technical-detailsIntegers.
body.track_width_front, body.track_width_rearfrontTrackWidth, rearTrackWidth/technical-detailsmm.
body.vin_placement, body.rims_and_tiresvinPlacement, wheelAndTire/technical-detailsClosest field for rims and tires. Strings.
equipment[].name, equipment[].quantityname, count/equipmentA paged list (page, pageSize). The name is Motorstyrelsen's, and originalName never changes. Compare the spelling before you match on text.

Values

Synsbasen uses Motorstyrelsen's Danish strings as values. Motorbay uses fixed values in camelCase. The names of kind, usage, make, color and fuel are still Danish strings in name. Motorbay's lists of values are in the OpenAPI document.

Field Synsbasen Motorbay
statusOprettetcreated
statusRegistreretregistered
statusAfmeldtderegistered
statusSkrottetscrapped
statusEksporteretexported
statusSlettetdeleted
statusUnderOprettelseunderCreation
statusDelvistOprettetpartiallyCreated
statusAdministrativOprettelseadministrativeCreation
statusHarGennemførtRegistreringssyncompletedRegistrationInspection
registration_statusRegistreretregistered
registration_statusAfmeldtderegistered
registration_statusUnderUdarbejdelsepending
last_inspection_resultGodkendtapproved
last_inspection_resultIkkeFuldstaendigtSynincomplete
last_inspection_resultIkkeGodkendtrejected
last_inspection_resultIkkeGodkendtKanGenfremstillesrejectedReinspectionAllowed
last_inspection_resultKanGodkendesVedOmsynAfOmsynsvirksomhedreinspectionCompanyReinspectionAllowed
last_inspection_resultKanGodkendesVedOmsynAfSynsvirksomhedinspectionCompanyReinspectionAllowed
last_inspection_kindKontrolSynscrutiny
last_inspection_kindMOTmot
last_inspection_kindPeriodiskSynperiodic
last_inspection_kindRegistreringsSynregistration
last_inspection_kindRegistreringssynToldsyncustoms

Motorbay's status has three values that Synsbasen's documented list doesn't show: exportMarking, declaredByImporter and declaredByImporterAndDealer. Motorbay's registrationStatus also has unknown. So write a default branch when you translate the values in your code.

What Synsbasen offers beyond Motorbay

You may use these today. Motorbay doesn't have them, so read the list before you move anything.

  • Debt: tinglysning_data returns liabilities and notices from Tinglysningen, for example about bankruptcy. Motorbay has no debt data.
  • Insurance and next inspection: dmr_data looks up DMR live and returns the insurance company and insurance status, the date of the next periodic inspection and inspection invocations. Motorbay has neither.
  • Appraisals: appraisals returns valuations of value and registration tax. Motorbay has no valuations.
  • Same-week lookups: dmr_fallback=true looks up new or changed plates live before the next extract is fetched. Motorbay answers only from the latest extract and is not real-time.
  • Monitoring and webhooks: with watched_vehicles and webhooks you are told when a vehicle changes or a new inspection arrives. Motorbay has no webhooks. You can read Motorbay-Data-As-Of or GET /v1/dataset to see whether a new extract has been imported.
  • Search and statistics: POST /v1/vehicles/search has search predicates, COUNT, averages and grouping. Motorbay's GET /v1/vehicles filters on make, kind, usage, color, model year and plate, but doesn't count or group.
  • All inspections: /v1/inspections returns each inspection with test center, error codes, PDF and documentation. Motorbay returns only the latest inspection, with type, day, result and odometer reading.
  • Blocks, permits and leasing: registration_blocks, permits, leasing_periods and leasing_period_start. Motorbay doesn't have them yet. They are being built.
  • Corrected and calculated fields: corrected model year and EC type approval, energy class, environmental zone status, horsepower, kilometers per year, age and estimated next inspection. Motorbay gives the values as they are in the extract.
  • Other expansions: periodic taxes, EU Safety Gate alerts, plate recognition from images, dealer plates and widgets for dealer sites. Motorbay has none of these.

Synsbasen also offers a Postman collection and a Ruby gem. Motorbay has an OpenAPI document, so you can generate a client in your own language. If you use something from the list in production, you can run both: keep Synsbasen for what Motorbay lacks, and move the basic-data lookups.

A plate lookup before and after

The examples use the plate AB12345 as a placeholder. First curl. Synsbasen's response comes with everything you ask for through expand. At Motorbay you fetch engine and environment from one endpoint each, with the vehicle's id.

GET
curl -i -H "Authorization: Bearer $SYNSBASEN_API_KEY" \
  "https://api.synsbasen.dk/v1/vehicles/registration/AB12345"
GET
curl -i -H "X-Api-Key: $MOTORBAY_API_KEY" \
  "https://api.motorbay.app/v1/vehicles/plate/AB12345"

# What Synsbasen returns with expand[]=engine and expand[]=emission
# you fetch per vehicle, with the id from the response above:
curl -H "X-Api-Key: $MOTORBAY_API_KEY" \
  "https://api.motorbay.app/v1/vehicles/$VEHICLE_ID/engine"
curl -H "X-Api-Key: $MOTORBAY_API_KEY" \
  "https://api.motorbay.app/v1/vehicles/$VEHICLE_ID/environmental-information"

Then JavaScript with fetch. Both functions return the same object, and both return null when the plate isn't found. 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.

GET
async function lookupPlate(plate) {
  const res = await fetch("https://api.synsbasen.dk/v1/vehicles/registration/" + encodeURIComponent(plate), {
    headers: {
      Authorization: "Bearer " + process.env.SYNSBASEN_API_KEY,
      "Content-Type": "application/json",
    },
  });
  if (res.status === 404) return null;
  if (res.status === 429) throw new Error("Synsbasen: too many requests");
  if (!res.ok) throw new Error("Synsbasen: HTTP " + res.status);
  const { data } = await res.json();
  return {
    plate: data.registration,
    vin: data.vin,
    firstRegistered: data.first_registration_date,
    make: data.brand,
    model: data.model,
  };
}
GET
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(); // no data wrapper
  return {
    plate: vehicle.registrationNumber,
    vin: vehicle.vin,
    firstRegistered: vehicle.firstRegisteredOn,
    make: vehicle.make.name,
    model: vehicle.model?.name ?? null,
  };
}

Plates are reused. At Motorbay the lookup returns the vehicle registered with the plate now. Synsbasen says its lookup returns the most recent vehicle with the plate, so compare the two on plates that have been on several vehicles. To see every vehicle that has carried the plate, use GET /v1/vehicles?registrationNumber=.

Price at your volume

Synsbasen sells monthly plans with 500, 2,500 or 12,500 requests included. Requests beyond that cost a set amount each, and some expansions cost tokens. Current prices are on Synsbasen's site. Synsbasen says only requests that return 200 count toward the quota.

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. One Synsbasen call with expand can be several calls at Motorbay. A plate lookup plus engine and latest inspection is three calls, 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 Synsbasen's nor Motorbay's names.
  • Translate the fields with the tables here, and add only the sub-endpoints you use: /inspection, /engine, /technical-details, /environmental-information, /fuel-types and /equipment.
  • 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, fields corrected at Synsbasen, 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 be RateLimitExceeded or QuotaExceeded, 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 Synsbasen key in place until at least one new extract has arrived.
  • Cancel afterwards, if you use nothing Synsbasen offers beyond Motorbay.

The sources are Motorstyrelsen's own pages, Motorstyrelsen's extract and Motorbay's API docs.

Make your first lookup today

Create an account, make an API key and send your first call. The quickstart takes about five minutes. Your first 1,000 requests every month are free, and you need no card.