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.
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.
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.
Request headers
| Header | Value | Purpose |
|---|---|---|
Authorization | Bearer wsk_… | Authenticates the workshop. |
Content-Type | application/json | For JSON bodies. Photo file uploads use multipart/form-data. |
Accept | application/json | Responses 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.
GET /v1/options; nothing else is accepted.| Field | Type | Create | Description |
|---|---|---|---|
| Identity | |||
external_id | string ≤120 | recommended | Your 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_at | datetime | no | When your system last changed the vehicle. An older timestamp than the one stored is rejected with 409 stale_update. |
license_plate | string ≤20 | no | Must be unique across the platform. |
vin | string (17) | no | Chassis number, unique across the platform. Stored upper-case. |
| Make, model & registration | |||
make / make_id | string / integer | yes | Brand, by name (case-insensitive) or id. GET /v1/makes. |
model / model_id | string / integer | yes | Model within the make. Unknown names are rejected unless create_missing_model is true. |
create_missing_model | boolean | no | Add an unknown model name under the make instead of failing. Default false. |
vehicle_type / vehicle_type_id | string / integer | no | Car, Motorcycle, SUV, Truck, Van. Default Car. |
year | integer | yes | Model year, 1990–2027. |
first_registration | date | no | YYYY-MM-DD. |
color | string ≤50 | no | Use a value from the color enumeration to get it translated; other words are shown as sent. |
mileage | integer | no | Odometer reading, in mileage_unit. |
mileage_unit | enum | no | km (default) or mi. Use mi for US/UK cars sold abroad; the site shows the unit as sent. |
| Engine & drivetrain | |||
motor_type | string ≤100 | no | Engine designation, e.g. "2.0 TDI 150hp". |
fuel_type | enum | no | See enumerations.petroldieselelectrichybrid_petrolhybrid_dieselphev_petrolphev_diesellpgcnghydrogenmild_hybridotherlabels ↓ |
power_hp / power_kw | integer | no | Send either; the other is derived. |
cylinder_capacity | integer cc | no | Engine displacement in cm³, e.g. 1998. |
gearbox_type | enum | no | Manual, automatic, semi-automatic, CVT or single-speed (electric). |
drivetrain | enum | no | front, rear or 4wd. |
emission_standard | enum | no | Euro class. |
co2_gkm | integer | no | CO₂ in g/km. |
battery_capacity_kwh | decimal kWh | no | Electric vehicles: usable battery capacity, e.g. 77.4. Shown instead of the Euro norm when fuel_type is electric. |
battery_soh_pct | integer 0–100 | no | Battery state of health in %. |
battery_certificate_url | url | no | Link to the battery health certificate; shown as a clickable link on the listing. |
| Body, dimensions & wheels | |||
body_type | enum | no | Body style as shown in the listing filters. |
num_doors / num_seats | integer | no | Doors 1–9, seats 1–99. |
weight | integer kg | no | Kerb weight. |
steering_position | enum | no | lhd or rhd. |
tyre_size / bolt_pattern / et_offset | string | no | e.g. "225/45R17", "5x112", "+35". |
| Interior & comfort | |||
interior_color | string ≤50 | no | Free text, e.g. "black". |
interior_material | enum | no | Upholstery. |
air_conditioning | enum | no | None, manual or automatic climate control (1–4 zones). |
airbags | enum | no | How many airbags are fitted. |
| Equipment | |||
features | array[string] | no | Equipment slugs from the catalogue below. Unknown slugs are rejected. Sending [] clears the list. |
parking_assist | array[string] | no | Parking aid slugs from the catalogue below. |
| Sale & condition | |||
is_for_sale | boolean | no | Default true on create. false takes the car off the marketplace but keeps it. |
asking_price | decimal | no | In the workshop's currency (returned as `currency`). Plain number, not cents. |
is_margin_vehicle / is_tax_vehicle | boolean | no | VAT treatment: margin scheme or VAT-deductible. |
vehicle_condition | enum | no | New, demo, used, damaged… |
num_owners | integer | no | Previous owners, 0–99. |
maintenance_history | enum | no | Service book status. |
carpass_url | url | no | Car-Pass document link (Belgium). |
short_description | string ≤120 | no | One-liner on listing cards. |
seller_description | text | no | Full description. |
| Photos | |||
image_urls | array[url] ≤30 | no | Photos to download from your servers, in display order. When present it replaces the whole photo set; omit to leave photos alone. |
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
Reference (no key needed)
Vehicles
Photos
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
422and a per-vehiclevehiclesmap; nothing is written. complete: truedeclares 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, otherwise409 empty_snapshot. dry_run: truereturnswould_create,would_update,would_unlistand writes nothing.- Slots. Vehicles beyond your sale-slot allowance are saved unlisted with a
sale_limit_reachedwarning 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]}'
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
6cam_360360° Cameracam_frontFront cameracam_rearRear cameraself_steeringSelf-steering systemssens_frontFront parking sensorssens_rearRear parking sensorsExterior features 78
Electronics
10absABSespESPimmobiliserElectronic immobilisercentralLockingCentral lockingkeylessKeyless central lockingrainSensorRain sensorlightSensorLight sensortyrePressureMonitorTyre pressure monitoringstartStopStart/stop systemelectricTailgateElectric tailgateLighting
6fogLightsFog lightsledDrlLED daytime running lightsdrlDaytime running lightscorneringLightCornering lightheadlightWasherHeadlight washerdynamicIndicatorsDynamic / sweeping / sliding indicatorsHeadlights
7biXenonHeadlightsBi-xenon headlightsxenonHeadlightsXenon headlightsledHeadlightsLED headlightslaserLightLaser lighthighBeamAssistHigh beam assistnightVisionNight vision assistantmatrixLightsIntelligent / matrix lightsDriving Assistants
12distanceWarnerDistance warninghillStartAssistHill start assistspeedLimiterSpeed limiteremergencyBrakeAssistEmergency brake assistlaneAssistLane assistblindSpotMonitorBlind spot monitortractionControlTraction controltrafficSignRecognitionTraffic sign recognitionadaptiveCorneringAdaptive cornering lightcruiseControlCruise controladaptiveCruiseControlAdaptive cruise controlfatigueWarnerFatigue warning systemComfort & Other
43tintedWindowsTinted 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 mirrorsInterior features 28
Infotainment
17androidAutoAndroid AutoappleCarplayApple CarPlaybluetoothBluetoothboardComputerOn-board computercdPlayerCD playerheadUpDisplayHead-up displayinductiveChargingInductive charging for smartphonesmusicStreamingIntegrated music streamingnavigationNavigation systemradioDabDAB radiosoundSystemSound systemtouchscreenTouchscreentunerRadioTuner/RadiotvTVvoiceControlVoice controlwifiHotspotWi-Fi hotspotdigitalInstrumentClusterFully digital instrument clusterSeats
11armrestArmrestelectricSeatAdjustElectric seat adjustmentelectricSeatAdjustMemoryElectric seat adjustment with memoryelectricSeatAdjustRearElectric rear seat adjustmentlumbarSupportLumbar supportmassageSeatsMassage seatsseatVentilationSeat ventilationseatHeatingSeat heatingseatHeatingRearRear seat heatingsportSeatsSport seatsfoldablePassengerSeatFoldable passenger seatEnumerations
Labels shown in the selected language; every language is in GET /v1/options. Unknown values are rejected rather than guessed.
vehicle_type
year
1990 – 2027
fuel_type
12| Value | Label | English |
|---|---|---|
petrol | Petrol / Gasoline | Petrol / Gasoline |
diesel | Diesel | Diesel |
electric | Electric | Electric |
hybrid_petrol | Hybrid (Petrol) | Hybrid (Petrol) |
hybrid_diesel | Hybrid (Diesel) | Hybrid (Diesel) |
phev_petrol | PHEV (Petrol) | PHEV (Petrol) |
phev_diesel | PHEV (Diesel) | PHEV (Diesel) |
lpg | LPG | LPG |
cng | CNG | CNG |
hydrogen | Hydrogen | Hydrogen |
mild_hybrid | Mild Hybrid | Mild Hybrid |
other | Other | Other |
gearbox_type
5| Value | Label | English |
|---|---|---|
manual | Manual | Manual |
automatic | Automatic | Automatic |
cvt | CVT | CVT |
dct | Dual-Clutch (DCT) | Dual-Clutch (DCT) |
semi_auto | Semi-automatic | Semi-automatic |
body_type
11| Value | Label | English |
|---|---|---|
sedan | Sedan | Sedan |
hatchback | Hatchback | Hatchback |
estate | Estate / Break | Estate / Break |
coupe | Coupé | Coupé |
convertible | Cabriolet / Convertible | Cabriolet / Convertible |
suv | SUV | SUV |
crossover | Crossover | Crossover |
mpv | MPV / Minivan | MPV / Minivan |
pickup | Pickup | Pickup |
van | Van | Van |
other | Other | Other |
drivetrain
3| Value | Label | English |
|---|---|---|
4wd | 4 wheel drive | 4 wheel drive |
front | Front drive | Front drive |
rear | Rear drive | Rear drive |
steering_position
2| Value | Label | English |
|---|---|---|
lhd | Left-hand drive | Left-hand drive |
rhd | Right-hand drive | Right-hand drive |
emission_standard
12| Value | Label | English |
|---|---|---|
euro0 | Euro 0 | Euro 0 |
euro1 | Euro 1 | Euro 1 |
euro2 | Euro 2 | Euro 2 |
euro3 | Euro 3 | Euro 3 |
euro4 | Euro 4 | Euro 4 |
euro5 | Euro 5 | Euro 5 |
euro6 | Euro 6 | Euro 6 |
euro6b | Euro 6b | Euro 6b |
euro6c | Euro 6c | Euro 6c |
euro6d | Euro 6d | Euro 6d |
euro6d_temp | Euro 6d-temp | Euro 6d-temp |
other | Other | Other |
color
15color is free text; these values are the ones the site translates.
| Value | Label | English |
|---|---|---|
white | White | White |
black | Black | Black |
silver | Silver | Silver |
gray | Gray | Gray |
blue | Blue | Blue |
red | Red | Red |
green | Green | Green |
yellow | Yellow | Yellow |
orange | Orange | Orange |
brown | Brown | Brown |
beige | Beige | Beige |
gold | Gold | Gold |
purple | Purple | Purple |
pink | Pink | Pink |
other | Other | Other |
interior_material
6| Value | Label | English |
|---|---|---|
alcantara | Alcantara | Alcantara |
fabric | Fabric | Fabric |
artificial_leather | Artificial leather | Artificial leather |
partial_leather | Partial leather | Partial leather |
full_leather | Full leather | Full leather |
velour | Velour | Velour |
vehicle_condition
6| Value | Label | English |
|---|---|---|
factory_new | Factory New | Factory New |
new_condition | New Condition | New Condition |
new_with_damage | New Condition with Damage | New Condition with Damage |
used | Used | Used |
used_with_damage | Used with Damage | Used with Damage |
parts | Used for Parts | Used for Parts |
maintenance_history
4| Value | Label | English |
|---|---|---|
none | No | No |
dealership | Yes, with dealership | Yes, with dealership |
platform | Yes, with the platform | Yes, with the platform |
both | Yes, with dealership and the platform | Yes, with dealership and the platform |
airbags
4| Value | Label | English |
|---|---|---|
airbagDriver | Driver airbag | Driver airbag |
airbagFront | Front airbags | Front airbags |
airbagFrontSide | Front & side airbags | Front & side airbags |
airbagFull | Front, side & rear airbags | Front, side & rear airbags |
air_conditioning
5| Value | Label | English |
|---|---|---|
acNone | None | None |
acManual | Manual | Manual |
ac2Zone | 2-zone automatic | 2-zone automatic |
ac3Zone | 3-zone automatic | 3-zone automatic |
ac4Zone | 4-zone automatic | 4-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."
]
}
}
| HTTP | error | Meaning |
|---|---|---|
| 401 | invalid_api_key | Missing, unknown or revoked key. |
| 403 | read_only_key | The key may only read. |
| 403 | workshop_blocked / workshop_inactive | The workshop may not publish at the moment. |
| 403 | sale_limit_reached | All for-sale slots are in use. Body carries used, limit, available. |
| 404 | vehicle_not_found / image_not_found / make_not_found | Not found within this workshop. |
| 409 | duplicate_vin / duplicate_license_plate | Another vehicle already has that identifier. |
| 409 | stale_update | The stored external_updated_at is newer than the one sent. |
| 409 | empty_snapshot | A complete sync with no vehicles needs allow_empty: true. |
| 422 | validation_error | Field errors under `fields` (or `vehicles` for a sync). Nothing was written. |
| 422 | image_url_* / image_too_large / image_unreadable | A photo could not be fetched. On create/update these are warnings, not failures. |
| 429 | — | Rate 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.