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 like cars added by hand.

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 {link}, 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.

This is the complete set: 45 fields — the same ones the Add-Vehicle form offers — with 12 enumerations, 106 equipment values and 6 parking aids. Every accepted value is listed on this page and in GET /v1/options; nothing else is accepted.
FieldTypeCreateDescription
Identity
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.
license_platestring ≤20noMust be unique across the platform.
vinstring (17)noChassis number, unique across the platform. Stored upper-case.
Make, model & registration
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.
first_registrationdatenoYYYY-MM-DD.
colorstring ≤50noUse a value from the color enumeration to get it translated; other words are shown as sent.
whiteblacksilvergrayblueredgreenyelloworangebrownbeigegoldpurplepinkotherlabels ↓
mileageintegernoOdometer reading, in mileage_unit.
mileage_unitenumnokm (default) or mi. Use mi for US/UK cars sold abroad; the site shows the unit as sent.
Engine & drivetrain
motor_typestring ≤100noEngine designation, e.g. "2.0 TDI 150hp".
fuel_typeenumnoSee enumerations.
petroldieselelectrichybrid_petrolhybrid_dieselphev_petrolphev_diesellpgcnghydrogenmild_hybridotherlabels ↓
power_hp / power_kwintegernoSend either; the other is derived.
cylinder_capacityinteger ccnoEngine displacement in cm³, e.g. 1998.
gearbox_typeenumnoManual, automatic, semi-automatic, CVT or single-speed (electric).
manualautomaticcvtdctsemi_autolabels ↓
drivetrainenumnofront, rear or 4wd.
4wdfrontrearlabels ↓
emission_standardenumnoEuro class.
euro0euro1euro2euro3euro4euro5euro6euro6beuro6ceuro6deuro6d_tempotherlabels ↓
co2_gkmintegernoCO₂ in g/km.
battery_capacity_kwhdecimal kWhnoElectric vehicles: usable battery capacity, e.g. 77.4. Shown instead of the Euro norm when fuel_type is electric.
battery_soh_pctinteger 0–100noBattery state of health in %.
battery_certificate_urlurlnoLink to the battery health certificate; shown as a clickable link on the listing.
Body, dimensions & wheels
body_typeenumnoBody style as shown in the listing filters.
sedanhatchbackestatecoupeconvertiblesuvcrossovermpvpickupvanotherlabels ↓
num_doors / num_seatsintegernoDoors 1–9, seats 1–99.
weightinteger kgnoKerb weight.
steering_positionenumnolhd or rhd.
tyre_size / bolt_pattern / et_offsetstringnoe.g. "225/45R17", "5x112", "+35".
Interior & comfort
interior_colorstring ≤50noFree text, e.g. "black".
interior_materialenumnoUpholstery.
alcantarafabricartificial_leatherpartial_leatherfull_leathervelourlabels ↓
air_conditioningenumnoNone, manual or automatic climate control (1–4 zones).
acNoneacManualac2Zoneac3Zoneac4Zonelabels ↓
airbagsenumnoHow many airbags are fitted.
airbagDriverairbagFrontairbagFrontSideairbagFulllabels ↓
Equipment
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.
Sale & condition
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_conditionenumnoNew, demo, used, damaged…
factory_newnew_conditionnew_with_damageusedused_with_damagepartslabels ↓
num_ownersintegernoPrevious owners, 0–99.
maintenance_historyenumnoService book status.
nonedealershipplatformbothlabels ↓
carpass_urlurlnoCar-Pass document link (Belgium).
short_descriptionstring ≤120noOne-liner on listing cards.
seller_descriptiontextnoFull description.
Photos
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 {link}.

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 parking_assist

6
cam_360360° Camera
cam_frontFront camera
cam_rearRear camera
self_steeringSelf-steering systems
sens_frontFront parking sensors
sens_rearRear parking sensors

Exterior features 78

Electronics

10
absABS
espESP
immobiliserElectronic immobiliser
centralLockingCentral locking
keylessKeyless central locking
rainSensorRain sensor
lightSensorLight sensor
tyrePressureMonitorTyre pressure monitoring
startStopStart/stop system
electricTailgateElectric tailgate

Lighting

6
fogLightsFog lights
ledDrlLED daytime running lights
drlDaytime running lights
corneringLightCornering light
headlightWasherHeadlight washer
dynamicIndicatorsDynamic / sweeping / sliding indicators

Headlights

7
biXenonHeadlightsBi-xenon headlights
xenonHeadlightsXenon headlights
ledHeadlightsLED headlights
laserLightLaser light
highBeamAssistHigh beam assist
nightVisionNight vision assistant
matrixLightsIntelligent / matrix lights

Driving Assistants

12
distanceWarnerDistance warning
hillStartAssistHill start assist
speedLimiterSpeed limiter
emergencyBrakeAssistEmergency brake assist
laneAssistLane assist
blindSpotMonitorBlind spot monitor
tractionControlTraction control
trafficSignRecognitionTraffic sign recognition
adaptiveCorneringAdaptive cornering light
cruiseControlCruise control
adaptiveCruiseControlAdaptive cruise control
fatigueWarnerFatigue warning system

Comfort & Other

43
tintedWindowsTinted windows
adaptiveSuspensionAdaptive suspension
allWeatherTyresAll-weather tyres
heatedWindscreenHeated windscreen
disabledAccessDisabled access
roofRailsRoof rails
airSuspensionAir suspension
spareWheelSpare wheel
tyreSealantTyre sealant kit
fullSizeSpareFull-size spare wheel
powerSteeringPower steering
summerTyresSummer tyres
sportSuspensionSport suspension
sportPackageSport package
steelWheelsSteel wheels
alloyWheelsAlloy wheels
winterPackageWinter package
winterTyresWinter tyres
panoramicRoofPanoramic roof
slidingRoofSliding roof
foldingRoofFolding roof
towHitchTow hitch
alarmSystemAlarm system
ambientLightingAmbient lighting
electricWindowsElectric windows
handsFreeHands-free system
cargoPartitionCargo area partition
isofixIsofix
isofixPassengerIsofix passenger seat
emergencyCallSystemEmergency call system
smokersPackageSmoker's package
rightHandDriveRight-hand drive
skiStorageSki storage
auxiliaryHeatingAuxiliary heating
usbUSB
heatedSteeringWheelHeated steering wheel
leatherSteeringWheelLeather steering wheel
multifunctionSteeringWheelMultifunction steering wheel
paddleShiftersPaddle shifters
electricMirrorsElectric mirrors
electricFoldingMirrorsElectric folding mirrors
autoGlareFreeMirrorAuto-dimming interior mirror
virtualMirrorsVirtual side mirrors

Interior features 28

Infotainment

17
androidAutoAndroid Auto
appleCarplayApple CarPlay
bluetoothBluetooth
boardComputerOn-board computer
cdPlayerCD player
headUpDisplayHead-up display
inductiveChargingInductive charging for smartphones
musicStreamingIntegrated music streaming
navigationNavigation system
radioDabDAB radio
soundSystemSound system
touchscreenTouchscreen
tunerRadioTuner/Radio
tvTV
voiceControlVoice control
wifiHotspotWi-Fi hotspot
digitalInstrumentClusterFully digital instrument cluster

Seats

11
armrestArmrest
electricSeatAdjustElectric seat adjustment
electricSeatAdjustMemoryElectric seat adjustment with memory
electricSeatAdjustRearElectric rear seat adjustment
lumbarSupportLumbar support
massageSeatsMassage seats
seatVentilationSeat ventilation
seatHeatingSeat heating
seatHeatingRearRear seat heating
sportSeatsSport seats
foldablePassengerSeatFoldable passenger seat

Enumerations

Labels shown in the selected language; every language is in GET /v1/options. Unknown values are rejected rather than guessed.

vehicle_type

Carid 1Motorcycleid 2Truckid 3Vanid 4SUVid 5

year

19902027

fuel_type

12
ValueLabelEnglish
petrolPetrol / GasolinePetrol / Gasoline
dieselDieselDiesel
electricElectricElectric
hybrid_petrolHybrid (Petrol)Hybrid (Petrol)
hybrid_dieselHybrid (Diesel)Hybrid (Diesel)
phev_petrolPHEV (Petrol)PHEV (Petrol)
phev_dieselPHEV (Diesel)PHEV (Diesel)
lpgLPGLPG
cngCNGCNG
hydrogenHydrogenHydrogen
mild_hybridMild HybridMild Hybrid
otherOtherOther

gearbox_type

5
ValueLabelEnglish
manualManualManual
automaticAutomaticAutomatic
cvtCVTCVT
dctDual-Clutch (DCT)Dual-Clutch (DCT)
semi_autoSemi-automaticSemi-automatic

body_type

11
ValueLabelEnglish
sedanSedanSedan
hatchbackHatchbackHatchback
estateEstate / BreakEstate / Break
coupeCoupéCoupé
convertibleCabriolet / ConvertibleCabriolet / Convertible
suvSUVSUV
crossoverCrossoverCrossover
mpvMPV / MinivanMPV / Minivan
pickupPickupPickup
vanVanVan
otherOtherOther

drivetrain

3
ValueLabelEnglish
4wd4 wheel drive4 wheel drive
frontFront driveFront drive
rearRear driveRear drive

steering_position

2
ValueLabelEnglish
lhdLeft-hand driveLeft-hand drive
rhdRight-hand driveRight-hand drive

emission_standard

12
ValueLabelEnglish
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
otherOtherOther

color

15

color is free text; these values are the ones the site translates.

ValueLabelEnglish
whiteWhiteWhite
blackBlackBlack
silverSilverSilver
grayGrayGray
blueBlueBlue
redRedRed
greenGreenGreen
yellowYellowYellow
orangeOrangeOrange
brownBrownBrown
beigeBeigeBeige
goldGoldGold
purplePurplePurple
pinkPinkPink
otherOtherOther

interior_material

6
ValueLabelEnglish
alcantaraAlcantaraAlcantara
fabricFabricFabric
artificial_leatherArtificial leatherArtificial leather
partial_leatherPartial leatherPartial leather
full_leatherFull leatherFull leather
velourVelourVelour

vehicle_condition

6
ValueLabelEnglish
factory_newFactory NewFactory New
new_conditionNew ConditionNew Condition
new_with_damageNew Condition with DamageNew Condition with Damage
usedUsedUsed
used_with_damageUsed with DamageUsed with Damage
partsUsed for PartsUsed for Parts

maintenance_history

4
ValueLabelEnglish
noneNoNo
dealershipYes, with dealershipYes, with dealership
platformYes, with the platformYes, with the platform
bothYes, with dealership and the platformYes, with dealership and the platform

airbags

4
ValueLabelEnglish
airbagDriverDriver airbagDriver airbag
airbagFrontFront airbagsFront airbags
airbagFrontSideFront & side airbagsFront & side airbags
airbagFullFront, side & rear airbagsFront, side & rear airbags

air_conditioning

5
ValueLabelEnglish
acNoneNoneNone
acManualManualManual
ac2Zone2-zone automatic2-zone automatic
ac3Zone3-zone automatic3-zone automatic
ac4Zone4-zone automatic4-zone automatic

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.