Inventory API
Integrate dealer inventory directly with AutoHands. Create and update vehicles, synchronise complete inventories, manage vehicle photos and monitor synchronisation runs through a versioned REST API.
Overview
The AutoHands Inventory API is intended for professional vehicle sellers, dealer groups, DMS providers, middleware platforms and inventory integration partners.
The API allows an authorised inventory source to maintain its AutoHands vehicle inventory without interacting with the AutoHands back office manually.
Quickstart
1. Obtain an API token
AutoHands issues a bearer token for a specific inventory source. Store this credential securely and never expose it in frontend code.
2. Test authentication
curl https://api.autohands.be/v1/me \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
3. Create a vehicle
curl -X POST https://api.autohands.be/v1/vehicles \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"external_vehicle_id": "DMS-123456",
"brand": "Abarth",
"model": "124 Spider",
"title": "Abarth 124 Spider",
"category": "passenger_car",
"condition": "used",
"body_type": "convertible",
"price_cents": 2999000,
"currency": "EUR",
"manufacture_year": 2021,
"mileage_km": 32000,
"fuel_type": "petrol",
"transmission": "manual",
"description": "Vehicle supplied by dealer inventory."
}'
Base URL & versioning
All production Inventory API endpoints use:
https://api.autohands.be/v1
The major API version is included in the URL. Backwards-incompatible changes will not silently replace the behaviour of an existing major version.
Authentication
The API uses bearer-token authentication.
Authorization: Bearer YOUR_API_TOKEN
Credentials can have separate read and write abilities.
Endpoints requiring a capability that is not assigned to
the client return HTTP 403.
Request headers
| Header | Value | Purpose |
|---|---|---|
Authorization |
Bearer … |
Authenticates the API client. |
Accept |
application/json |
Requests JSON responses. |
Content-Type |
application/json |
Required for JSON request bodies. |
Vehicle data model
Every external vehicle is identified within an inventory
source by external_vehicle_id.
| Field | Type | Description |
|---|---|---|
external_vehicle_id |
string | Stable vehicle identity within the source. |
external_updated_at |
datetime | Source-system modification timestamp. |
brand |
string | Vehicle manufacturer. |
model |
string | Vehicle model. |
title |
string | Public listing title. |
category |
enum | Vehicle category. |
condition |
enum | New, used or demonstration. |
body_type |
enum | Body configuration. |
price_cents |
integer | Price represented in euro cents. |
currency |
string | Currency code, normally EUR. |
manufacture_year |
integer | Year of manufacture. |
mileage_km |
integer | Mileage in kilometres. |
fuel_type |
enum | Normalised fuel type. |
transmission |
enum | Transmission type. |
drivetrain |
enum | Driven wheels / drivetrain. |
features |
array[string] |
Active AutoHands equipment slugs.
Use GET /v1/features to retrieve
the current accepted values.
|
description |
string | Vehicle description. |
vin |
string | Vehicle identification number when supplied. |
stock_number |
string | Dealer stock reference when supplied. |
Create vehicle
Newly created API inventory starts in
draft state until applicable AutoHands
publication requirements are satisfied.
Get vehicle
Update vehicle
Fields omitted from a PATCH request retain their current values.
Replace vehicle
Archive vehicle
Stale update protection
When external_updated_at is supplied,
AutoHands protects a newer vehicle version from being
overwritten by an older source-system event.
A stale update is rejected with HTTP
409 Conflict.
Inventory snapshots
{
"snapshot_id": "dms-export-2026-09-01-001",
"complete": true,
"vehicles": [
{
"external_vehicle_id": "DMS-123456",
"brand": "Abarth",
"model": "124 Spider",
"title": "Abarth 124 Spider",
"category": "passenger_car",
"condition": "used",
"body_type": "convertible",
"price_cents": 2999000,
"currency": "EUR",
"manufacture_year": 2021,
"mileage_km": 32000,
"fuel_type": "petrol",
"transmission": "manual",
"description": "Dealer inventory vehicle."
}
]
}
In a complete snapshot, source-managed vehicles missing from the incoming set are archived rather than hard deleted.
Snapshot safety
The complete flag is intentionally explicit.
A complete snapshot represents the authoritative inventory
state of that source.
allow_empty: true.
Snapshot processing is transactional. If a child vehicle fails validation, the snapshot is rejected instead of partially applying the inventory.
Idempotency
Vehicle snapshots use snapshot_id as their
idempotency identity.
Repeating the same snapshot ID with the same canonical
payload can be recognised safely. Reusing that same
snapshot ID with a different payload produces
409 Conflict.
Sync runs
Photo overview
Vehicle photos can be uploaded as multipart files, imported from HTTPS URLs or synchronised as a complete remote photo set.
Images are processed by AutoHands and stored as optimised WebP variants including a main image and thumbnail.
Multipart photo upload
curl -X POST \
https://api.autohands.be/v1/vehicles/DMS-123456/photos \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json" \
-F "photo=@vehicle-front.jpg" \
-F "external_photo_id=dealer-photo-001" \
-F "sort_order=0" \
-F "is_primary=1"
Upload photo from URL
{
"external_photo_id": "dealer-photo-002",
"url": "https://dealer.example/images/vehicle-123.jpg",
"sort_order": 1,
"is_primary": false
}
Remote-photo downloads reject unsafe local, private and reserved network destinations.
List photos
Update photo
Delete photo
Photo snapshots
{
"complete": true,
"primary_index": 0,
"photos": [
{
"external_photo_id": "dealer-photo-001",
"url": "https://dealer.example/images/front.jpg"
},
{
"external_photo_id": "dealer-photo-002",
"url": "https://dealer.example/images/rear.jpg"
}
]
}
allow_empty: true is explicitly supplied.
Photo ownership
Inventory API photo snapshots only replace photos marked as API-managed.
Photos added manually through AutoHands remain intact, including their physical files and database records.
API photos can carry:
external_photo_id,
source_url,
source_checksum and
managed_by_inventory_api.
Features / equipment
Vehicle equipment is exchanged using AutoHands feature slugs. Only features that are currently active in AutoHands are accepted by the Inventory API.
GET /v1/features
to retrieve the current active AutoHands feature catalog.
Request
curl https://api.autohands.be/v1/features \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
Response
{
"features": [
{
"slug": "automatische-airconditioning",
"name": "Automatische airconditioning",
"group": "comfort"
},
{
"slug": "apple-carplay",
"name": "Apple CarPlay",
"group": "infotainment"
}
],
"count": 80
}
Vehicle payload
Supply equipment in the optional
features array:
{
"features": [
"automatische-airconditioning",
"apple-carplay"
]
}
Unknown or inactive feature slugs are rejected with
HTTP 422. The API never automatically
creates new equipment values from an incoming payload.
features is omitted from a PATCH
request, the existing equipment remains unchanged.
Sending "features": [] explicitly removes
all equipment from that vehicle.
Vehicle GET responses include the currently active
feature slugs assigned to that vehicle in the
features array.
Enumerations
Vehicle category
passenger_car
oldtimer
light_commercial
camper
Condition
new
used
demonstration
Fuel
petrol
diesel
electric
hybrid
plug_in_hybrid
lpg
cng
hydrogen
other
Transmission
manual
automatic
semi_automatic
Body type
city_car
hatchback
sedan
station_wagon
suv
crossover
coupe
convertible
monovolume
pickup
van
other
Drivetrain
front_wheel_drive
rear_wheel_drive
all_wheel_drive
four_wheel_drive
unknown
Listing status
draft
published
paused
sold
expired
archived
Value normalization
The Inventory API can normalise supported partner vocabulary for selected enum fields before validation.
This is intended to reduce unnecessary mapping work for dealer systems while preserving AutoHands' canonical internal values.
Errors
API errors are returned as JSON.
{
"message": "External photo ID already exists for this vehicle.",
"error": "external_photo_id_conflict",
"external_photo_id": "dealer-photo-001"
}
Integrations should use HTTP status codes and stable machine-readable error identifiers where supplied.
HTTP status codes
| Status | Meaning |
|---|---|
200 |
Successful request or update. |
201 |
Resource created. |
401 |
Missing or invalid authentication. |
403 |
Credential lacks the required ability. |
404 |
Resource does not exist for this source. |
409 |
Conflict, stale update or identity conflict. |
422 |
Validation or snapshot safety rejection. |
429 |
Rate limit exceeded. |
Rate limits
Inventory endpoints are rate limited to protect service availability.
Clients receiving HTTP 429 should back off
rather than immediately repeating requests in a tight
loop.
Security
Integrations must use HTTPS. API tokens should be treated as secrets and stored only in secure server-side configuration.
Remote image import includes protection against requests to local, private and reserved network destinations.
Credentials can be revoked independently without removing the inventory source itself.
Integration guidelines
Use stable identities
Keep external_vehicle_id and
external_photo_id stable for the lifetime of
their corresponding source records.
Prefer snapshots for authoritative feeds
When your DMS exports the complete current inventory, use the snapshot endpoint instead of maintaining complex local deletion logic.
Send source timestamps
Supplying external_updated_at allows stale
events to be detected and rejected.
Retry carefully
Network failures can be retried, but integrations should respect idempotency, conflicts and rate limits.
Do not infer publication
Successful inventory ingestion does not necessarily mean that a listing satisfies every AutoHands publication or regulatory requirement.
Changelog
v1
Initial Inventory API with source-scoped authentication, vehicle CRUD, complete inventory snapshots, stale-update protection, sync-run logging, photo management, remote photo import and ownership-safe photo snapshots.