Driv.one · Import API
checking…
Developer documentation

Import API

Keep your Driv.one inventory in step with your DMS or stock system. Create and update vehicles, push complete inventories, manage photos — through a versioned REST API scoped to your workshop.

REST + JSONPredictable endpoints, JSON in and out, stable error codes.
Workshop scopedEvery key belongs to one workshop and can only see that workshop's cars.
Same vocabulary as the siteAccepted values are exactly what the Add-Vehicle form offers, labelled in five languages.
Safe syncAll-or-nothing validation, stale-update protection, unlist-never-delete in complete syncs.

The API is for professional sellers, dealer groups, DMS vendors and integration partners. Records you create appear on driv.one under your workshop, exactly as if they had been added by hand — and they can still be edited by hand afterwards.

Scope. API records are scoped to the authenticated workshop. A key can never read or change another workshop's inventory, and a workshop owner with several workshops needs one key per workshop.

Quickstart

1. Create an API key

Sign in to driv.one → Dashboard → API keys, pick the workshop, give the key a name and copy it. The key is shown once; if you lose it, revoke it and create another.

2. Test authentication

curl https://api.driv.one/v1/me \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Accept: application/json"

3. Create a vehicle

curl -X POST https://api.driv.one/v1/vehicles \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "external_id": "STOCK-4821",
  "external_updated_at": "2026-09-05T08:30:00Z",
  "make": "Volkswagen",
  "model": "Golf",
  "year": 2022,
  "vin": "WVWZZZAUZNW123456",
  "license_plate": "1-ABC-123",
  "mileage": 41200,
  "first_registration": "2022-03-15",
  "fuel_type": "petrol",
  "gearbox_type": "dct",
  "body_type": "hatchback",
  "power_hp": 150,
  "num_doors": 5,
  "num_seats": 5,
  "color": "gray",
  "interior_material": "fabric",
  "vehicle_condition": "used",
  "asking_price": 24950,
  "is_tax_vehicle": true,
  "short_description": "Golf 1.5 TSI Life, first owner, full history",
  "seller_description": "Serviced at the dealership, two keys, winter tyres included.",
  "features": [
    "appleCarplay",
    "androidAuto",
    "adaptiveCruiseControl",
    "ledHeadlights",
    "alloyWheels"
  ],
  "parking_assist": [
    "sens_front",
    "sens_rear",
    "cam_rear"
  ],
  "image_urls": [
    "https://cdn.example-dealer.be/stock/4821/front.jpg",
    "https://cdn.example-dealer.be/stock/4821/interior.jpg"
  ]
}'

The response is the stored vehicle including its uuid, public_url, currency and photos, plus a warnings array when something non-fatal happened (a photo that could not be fetched, a model that was created).

Base URL & versioning

https://api.driv.one/v1

The major version is part of the path. Backwards-incompatible changes get a new major version; /v1 keeps its behaviour. Additive changes (new optional fields, new enumeration values) can appear within v1 — read GET /v1/options rather than hard-coding lists.

Paths are shown without a trailing slash; one is accepted.

Authentication

Bearer-token authentication with a workshop API key. Keys start with wsk_.

Authorization: Bearer wsk_…

X-API-Key: wsk_… is accepted as an alternative header. A key is either read-write or read-only; a read-only key gets 403 read_only_key on any write.

Credential security. Never put an API key in browser-side JavaScript, a public repository, a screenshot or a support ticket. Revoke a key the moment you suspect it leaked — revocation is immediate.

Request headers

HeaderValuePurpose
AuthorizationBearer wsk_…Authenticates the workshop.
Content-Typeapplication/jsonFor JSON bodies. Photo file uploads use multipart/form-data.
Acceptapplication/jsonResponses are always JSON.

Vehicle data model

Fields accepted on POST, PUT and PATCH. Responses return the same names, plus read-only uuid, status (published / unlisted), public_url, currency, images, for_sale_since and created_at.

FieldTypeCreateDescription
external_idstring ≤120recommendedYour own stable id for the vehicle (stock number, DMS id). Lets you address the car by it and enables upsert and inventory sync.
external_updated_atdatetimenoWhen your system last changed the vehicle. An older timestamp than the one stored is rejected with 409 stale_update.
make / make_idstring / integeryesBrand, by name (case-insensitive) or id. GET /v1/makes.
model / model_idstring / integeryesModel within the make. Unknown names are rejected unless create_missing_model is true.
create_missing_modelbooleannoAdd an unknown model name under the make instead of failing. Default false.
vehicle_type / vehicle_type_idstring / integernoCar, Motorcycle, SUV, Truck, Van. Default Car.
yearintegeryesModel year, 1990–2027.
license_platestring ≤20noMust be unique across the platform.
vinstring (17)noChassis number, unique across the platform. Stored upper-case.
colorstring ≤50noUse a value from the color enumeration to get it translated; other words are shown as sent.
mileageinteger kmnoOdometer.
first_registrationdatenoYYYY-MM-DD.
motor_typestring ≤100noEngine designation, e.g. "2.0 TDI 150hp".
fuel_typeenumnoSee enumerations.
emission_standardenumnoEuro class.
co2_gkmintegernoCO₂ in g/km.
power_hp / power_kwintegernoSend either; the other is derived.
gearbox_typeenumno
body_typeenumno
num_doors / num_seatsintegerno
drivetrainenumnofront, rear or 4wd.
steering_positionenumnolhd or rhd.
cylinder_capacityinteger ccno
tyre_size / bolt_pattern / et_offsetstringnoe.g. "225/45R17", "5x112", "+35".
weightinteger kgno
airbagsenumno
air_conditioningenumno
interior_colorstring ≤50no
interior_materialenumno
featuresarray[string]noEquipment slugs from the catalogue below. Unknown slugs are rejected. Sending [] clears the list.
parking_assistarray[string]noParking aid slugs from the catalogue below.
is_for_salebooleannoDefault true on create. false takes the car off the marketplace but keeps it.
asking_pricedecimalnoIn the workshop's currency (returned as `currency`). Plain number, not cents.
is_margin_vehicle / is_tax_vehiclebooleannoVAT treatment: margin scheme or VAT-deductible.
vehicle_conditionenumno
short_descriptionstring ≤120noOne-liner on listing cards.
seller_descriptiontextnoFull description.
num_ownersintegerno
maintenance_historyenumno
carpass_urlurlnoCar-Pass document link (Belgium).
image_urlsarray[url] ≤30noPhotos to download from your servers, in display order. When present it replaces the whole photo set; omit to leave photos alone.
Identifier. Use a permanent id from your DMS as external_id — never a stock position or display order. It is what makes upsert, GET /v1/vehicles/{ref} by your id, and inventory sync work.

Endpoints

Account

GET/v1/meWho am IThe workshop behind the key, sale-slot usage, vehicle counts.
GET/healthHealthNo authentication.

Reference (no key needed)

GET/v1/optionsAll accepted valuesEvery enumeration, equipment slug, parking value and vehicle type, labelled in en/nl/fr/es/pt.
GET/v1/featuresEquipment catalogueJust the equipment slugs with their groups.
GET/v1/makes?search=MakesOptional `search` and `vehicle_type_id`.
GET/v1/makes/{make_id}/modelsModels of a make

Vehicles

GET/v1/vehiclesList`status=published|unlisted|all`, `external_id=`, `limit` (≤200), `offset`.
POST/v1/vehiclesCreate or upsert201 on create. If `external_id` already exists for your workshop the vehicle is updated and 200 is returned.
GET/v1/vehicles/{ref}Get one`ref` is our uuid or your external_id.
PATCH/v1/vehicles/{ref}Update some fieldsOmitted fields keep their value.
PUT/v1/vehicles/{ref}ReplaceOmitted optional fields are cleared.
DELETE/v1/vehicles/{ref}DeletePermanent, photos included. Prefer PATCH {"is_for_sale": false} to unlist.
POST/v1/vehicles/syncSync a whole inventoryUp to 200 vehicles per call, all-or-nothing validation, optional `complete` mode.

Photos

GET/v1/vehicles/{ref}/imagesList photosOrder 0 is the main photo.
POST/v1/vehicles/{ref}/imagesAdd a photoJSON `{"url": …}` or multipart `image` file; optional `order`.
PUT/v1/vehicles/{ref}/images/orderReorder`{"ids": […]}` — every photo id exactly once.
DELETE/v1/vehicles/{ref}/images/{id}Delete a photoRemaining photos are renumbered.

Full request and response schemas, with every enumeration inlined: Swagger UI · ReDoc · openapi.json.

List response

{
  "count": 37, "limit": 50, "offset": 0, "next_offset": null,
  "results": [ { "uuid": "…", "external_id": "STOCK-4821", "status": "published", … } ]
}

Upsert & stale updates

POST /v1/vehicles with an external_id that your workshop already uses updates that vehicle (HTTP 200) instead of creating a second one (HTTP 201). This makes a naive "push everything every night" integration idempotent.

When you also send external_updated_at, an update whose timestamp is older than the one stored is refused with 409 stale_update, so a delayed event can never overwrite a newer one. Inside a sync such a vehicle is reported as skipped_stale and the rest proceeds.

PATCH changes only the fields you send. PUT is a full replacement: optional fields you leave out are cleared. Both accept the same body as create.

Inventory sync

POST /v1/vehicles/sync upserts a whole inventory in one call (≤200 vehicles; call it repeatedly for more). Every vehicle needs an external_id.

{
  "complete": true,
  "vehicles": [
    {
      "external_id": "STOCK-4821",
      "make": "Volkswagen",
      "model": "Golf",
      "year": 2022,
      "asking_price": 24950,
      "fuel_type": "petrol",
      "mileage": 41200
    },
    {
      "external_id": "STOCK-4835",
      "make": "Audi",
      "model": "A4",
      "year": 2021,
      "asking_price": 28900,
      "fuel_type": "diesel",
      "body_type": "estate"
    }
  ]
}
  • All-or-nothing validation. The whole payload is validated first. One invalid vehicle rejects the call with 422 and a per-vehicle vehicles map; nothing is written.
  • complete: true declares the payload to be your entire stock. API-managed vehicles (those carrying one of your external ids) that are missing from it are unlisted, never deleted — they stay in your dashboard and come back if you send them again.
  • Empty protection. A complete sync with zero vehicles needs allow_empty: true, otherwise 409 empty_snapshot.
  • dry_run: true returns would_create, would_update, would_unlist and writes nothing.
  • Slots. Vehicles beyond your sale-slot allowance are saved unlisted with a sale_limit_reached warning instead of failing the sync.

Vehicles added by hand on the website are never touched by a sync.

Sale slots

Each workshop account has an allowance of vehicles that may be for sale at the same time (free tier, subscription tiers, or an amount assigned by Driv.one). GET /v1/me returns slots.used, slots.limit and slots.available.

A single create or update that would exceed the allowance fails with 403 sale_limit_reached. To free a slot, PATCH {"is_for_sale": false} a vehicle — it stays stored and can be re-listed later. More slots can be bought on driv.one.

Photos

Photos are ordered; order 0 is the main photo shown on listing cards. Large images are resized to a 2560 px long edge and re-encoded; anything above 15 MB after that is refused.

With the vehicle

Send image_urls in create/update. The photos are downloaded from your servers in the order given and replace the whole photo set. Omit the field to leave photos untouched. If none of the URLs can be fetched the existing photos are kept and a warning is returned.

One at a time

curl -X POST https://api.driv.one/v1/vehicles/STOCK-4821/images \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://cdn.example-dealer.be/stock/4821/rear.jpg", "order": 1}'
curl -X POST https://api.driv.one/v1/vehicles/STOCK-4821/images \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "image=@rear.jpg" -F "order=1"

Reorder

curl -X PUT https://api.driv.one/v1/vehicles/STOCK-4821/images/order \
  -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"ids": [912, 910, 911]}'
Remote URLs must be public http(s) addresses. Local, private and reserved network destinations are refused at every redirect hop. Content is checked to be a real image regardless of the Content-Type the host claims.

Equipment (106 values)

Send equipment as slugs in features, and parking aids in parking_assist. Only the values below are accepted; unknown slugs return 422 naming them. Omitting the field on PATCH keeps the equipment; sending [] clears it. Labels in every language: GET /v1/options.

Parking assist

cam_360360° Cameracam_frontFront cameracam_rearRear cameraself_steeringSelf-steering systemssens_frontFront parking sensorssens_rearRear parking sensors
Electronics · exterior · 10
absABSespESPimmobiliserElectronic immobilisercentralLockingCentral lockingkeylessKeyless central lockingrainSensorRain sensorlightSensorLight sensortyrePressureMonitorTyre pressure monitoringstartStopStart/stop systemelectricTailgateElectric tailgate
Lighting · exterior · 6
fogLightsFog lightsledDrlLED daytime running lightsdrlDaytime running lightscorneringLightCornering lightheadlightWasherHeadlight washerdynamicIndicatorsDynamic / sweeping / sliding indicators
Headlights · exterior · 7
biXenonHeadlightsBi-xenon headlightsxenonHeadlightsXenon headlightsledHeadlightsLED headlightslaserLightLaser lighthighBeamAssistHigh beam assistnightVisionNight vision assistantmatrixLightsIntelligent / matrix lights
Driving Assistants · exterior · 12
distanceWarnerDistance warninghillStartAssistHill start assistspeedLimiterSpeed limiteremergencyBrakeAssistEmergency brake assistlaneAssistLane assistblindSpotMonitorBlind spot monitortractionControlTraction controltrafficSignRecognitionTraffic sign recognitionadaptiveCorneringAdaptive cornering lightcruiseControlCruise controladaptiveCruiseControlAdaptive cruise controlfatigueWarnerFatigue warning system
Comfort & Other · exterior · 43
tintedWindowsTinted windowsadaptiveSuspensionAdaptive suspensionallWeatherTyresAll-weather tyresheatedWindscreenHeated windscreendisabledAccessDisabled accessroofRailsRoof railsairSuspensionAir suspensionspareWheelSpare wheeltyreSealantTyre sealant kitfullSizeSpareFull-size spare wheelpowerSteeringPower steeringsummerTyresSummer tyressportSuspensionSport suspensionsportPackageSport packagesteelWheelsSteel wheelsalloyWheelsAlloy wheelswinterPackageWinter packagewinterTyresWinter tyrespanoramicRoofPanoramic roofslidingRoofSliding rooffoldingRoofFolding rooftowHitchTow hitchalarmSystemAlarm systemambientLightingAmbient lightingelectricWindowsElectric windowshandsFreeHands-free systemcargoPartitionCargo area partitionisofixIsofixisofixPassengerIsofix passenger seatemergencyCallSystemEmergency call systemsmokersPackageSmoker's packagerightHandDriveRight-hand driveskiStorageSki storageauxiliaryHeatingAuxiliary heatingusbUSBheatedSteeringWheelHeated steering wheelleatherSteeringWheelLeather steering wheelmultifunctionSteeringWheelMultifunction steering wheelpaddleShiftersPaddle shifterselectricMirrorsElectric mirrorselectricFoldingMirrorsElectric folding mirrorsautoGlareFreeMirrorAuto-dimming interior mirrorvirtualMirrorsVirtual side mirrors
Infotainment · interior · 17
androidAutoAndroid AutoappleCarplayApple CarPlaybluetoothBluetoothboardComputerOn-board computercdPlayerCD playerheadUpDisplayHead-up displayinductiveChargingInductive charging for smartphonesmusicStreamingIntegrated music streamingnavigationNavigation systemradioDabDAB radiosoundSystemSound systemtouchscreenTouchscreentunerRadioTuner/RadiotvTVvoiceControlVoice controlwifiHotspotWi-Fi hotspotdigitalInstrumentClusterFully digital instrument cluster
Seats · interior · 11
armrestArmrestelectricSeatAdjustElectric seat adjustmentelectricSeatAdjustMemoryElectric seat adjustment with memoryelectricSeatAdjustRearElectric rear seat adjustmentlumbarSupportLumbar supportmassageSeatsMassage seatsseatVentilationSeat ventilationseatHeatingSeat heatingseatHeatingRearRear seat heatingsportSeatsSport seatsfoldablePassengerSeatFoldable passenger seat

Enumerations

English and Dutch labels shown; French, Spanish and Portuguese are in GET /v1/options. Unknown values are rejected rather than guessed.

vehicle_type

Carid 1Motorcycleid 2Truckid 3Vanid 4SUVid 5

year

19902027

fuel_type

ValueEnglishNederlands
petrolPetrol / GasolineBenzine
dieselDieselDiesel
electricElectricElektrisch
hybrid_petrolHybrid (Petrol)Hybride (Benzine)
hybrid_dieselHybrid (Diesel)Hybride (Diesel)
phev_petrolPHEV (Petrol)PHEV (Benzine)
phev_dieselPHEV (Diesel)PHEV (Diesel)
lpgLPGLPG
cngCNGCNG
hydrogenHydrogenWaterstof
mild_hybridMild HybridMild Hybride
otherOtherOverig

gearbox_type

ValueEnglishNederlands
manualManualHandgeschakeld
automaticAutomaticAutomatisch
cvtCVTCVT
dctDual-Clutch (DCT)Dubbelkoppeling (DCT)
semi_autoSemi-automaticSemi-automatisch

body_type

ValueEnglishNederlands
sedanSedanSedan
hatchbackHatchbackHatchback
estateEstate / BreakStationwagen
coupeCoupéCoupé
convertibleCabriolet / ConvertibleCabriolet
suvSUVSUV
crossoverCrossoverCrossover
mpvMPV / MinivanMPV / Minivan
pickupPickupPickup
vanVanBestelwagen
otherOtherOverig

drivetrain

ValueEnglishNederlands
4wd4 wheel drive4-wielaandrijving
frontFront driveVoorwielaandrijving
rearRear driveAchterwielaandrijving

steering_position

ValueEnglishNederlands
lhdLeft-hand driveLinksgestuurd
rhdRight-hand driveRechtsgestuurd

emission_standard

ValueEnglishNederlands
euro0Euro 0Euro 0
euro1Euro 1Euro 1
euro2Euro 2Euro 2
euro3Euro 3Euro 3
euro4Euro 4Euro 4
euro5Euro 5Euro 5
euro6Euro 6Euro 6
euro6bEuro 6bEuro 6b
euro6cEuro 6cEuro 6c
euro6dEuro 6dEuro 6d
euro6d_tempEuro 6d-tempEuro 6d-temp
otherOtherOverig

color

ValueEnglishNederlands
whiteWhiteWit
blackBlackZwart
silverSilverZilver
grayGrayGrijs
blueBlueBlauw
redRedRood
greenGreenGroen
yellowYellowGeel
orangeOrangeOranje
brownBrownBruin
beigeBeigeBeige
goldGoldGoud
purplePurplePaars
pinkPinkRoze
otherOtherAnder

interior_material

ValueEnglishNederlands
alcantaraAlcantaraAlcantara
fabricFabricStof
artificial_leatherArtificial leatherKunstleer
partial_leatherPartial leatherDeelleder
full_leatherFull leatherVolleder
velourVelourVelours

vehicle_condition

ValueEnglishNederlands
factory_newFactory NewFabriek nieuw
new_conditionNew ConditionNieuwe staat
new_with_damageNew Condition with DamageNieuwe staat met schade
usedUsedGebruikt
used_with_damageUsed with DamageGebruikt met schade
partsUsed for PartsGebruikt voor onderdelen

maintenance_history

ValueEnglishNederlands
noneNoNee
dealershipYes, with dealershipJa, bij dealer
platformYes, with the platformJa, via the platform
bothYes, with dealership and the platformJa, bij dealer en via the platform

airbags

ValueEnglishNederlands
airbagDriverDriver airbagBestuurdersairbag
airbagFrontFront airbagsFront airbags
airbagFrontSideFront & side airbagsFront & zijairbags
airbagFullFront, side & rear airbagsFront, zij en achter airbags

air_conditioning

ValueEnglishNederlands
acNoneNoneGeen
acManualManualHandmatig
ac2Zone2-zone automaticAutomatisch 2-zones
ac3Zone3-zone automaticAutomatisch 3-zones
ac4Zone4-zone automaticAutomatisch 4-zones

Errors

Errors are JSON with a stable error code and a human message; some carry extra keys.

{
  "error": "validation_error",
  "message": "One or more fields are invalid.",
  "fields": {
    "fuel_type": [
      "\"gasoline\" is not a valid choice."
    ],
    "features": [
      "Unknown features: sunroof. GET /v1/options lists the accepted values."
    ]
  }
}
HTTPerrorMeaning
401invalid_api_keyMissing, unknown or revoked key.
403read_only_keyThe key may only read.
403workshop_blocked / workshop_inactiveThe workshop may not publish at the moment.
403sale_limit_reachedAll for-sale slots are in use. Body carries used, limit, available.
404vehicle_not_found / image_not_found / make_not_foundNot found within this workshop.
409duplicate_vin / duplicate_license_plateAnother vehicle already has that identifier.
409stale_updateThe stored external_updated_at is newer than the one sent.
409empty_snapshotA complete sync with no vehicles needs allow_empty: true.
422validation_errorField errors under `fields` (or `vehicles` for a sync). Nothing was written.
422image_url_* / image_too_large / image_unreadableA photo could not be fetched. On create/update these are warnings, not failures.
429Rate limit. Retry after the `Retry-After` header.

Successful responses: 200 read or update, 201 created, 204 deleted.

Rate limits

Each key may make 3 000 requests per hour. Above that the API answers 429 with a Retry-After header. A full nightly sync of a few hundred cars uses a handful of calls; if you need more, contact Driv.one.

Photo downloads count against the same budget through the calls that trigger them, not per image.