API operational
AutoHands.be ↗
Developer documentation

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.

REST + JSON Predictable HTTP endpoints using JSON payloads.
Source scoped Every API credential is isolated to its inventory source.
Safe synchronisation Snapshot, stale-update and photo ownership protection are built in.

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.

Important: API records are scoped to the authenticated inventory source. One integration cannot manipulate inventory belonging to another source.

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
curl https://api.autohands.be/v1/me \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

3. Create a vehicle

cURL
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:

Base URL
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.

HTTP header
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.

Credential security: do not include API tokens in browser-side JavaScript, public repositories, screenshots or support tickets.

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.

Recommended identifier: use a permanent ID from the dealer or DMS. Do not use a mutable field such as a stock position or display order.
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

POST /v1/vehicles
Creates a new vehicle or updates the vehicle identified by the same source and external vehicle ID.

Newly created API inventory starts in draft state until applicable AutoHands publication requirements are satisfied.

Get vehicle

GET /v1/vehicles/{external_vehicle_id}
Returns one vehicle belonging to the authenticated inventory source.

Update vehicle

PATCH /v1/vehicles/{external_vehicle_id}
Partially updates an existing vehicle.

Fields omitted from a PATCH request retain their current values.

Replace vehicle

PUT /v1/vehicles/{external_vehicle_id}
Performs a complete replacement of an existing vehicle payload.

Archive vehicle

DELETE /v1/vehicles/{external_vehicle_id}
Removes the vehicle from active inventory without physically deleting its database record.
AutoHands uses archive semantics rather than hard deletion for API vehicle removal.

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

POST /v1/vehicles/snapshot
Synchronises a complete source inventory in one logical operation.
JSON
{
  "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.

Empty snapshot protection: an empty complete vehicle snapshot requires explicit 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

GET /v1/sync-runs/{snapshot_id}
Retrieves the recorded status of an inventory synchronisation run.

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.

API-managed photos carry their own ownership marker. Manually managed AutoHands photos are kept separate from dealer-feed photo ownership.

Multipart photo upload

POST /v1/vehicles/{external_vehicle_id}/photos
Uploads an image file to a source-managed vehicle.
cURL
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

POST /v1/vehicles/{external_vehicle_id}/photos/from-url
Securely downloads and imports one remote image.
JSON
{
  "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

GET /v1/vehicles/{external_vehicle_id}/photos
Returns the vehicle's current photo set.

Update photo

PATCH /v1/vehicles/{external_vehicle_id}/photos/{photo_id}
Updates photo ordering and primary-photo state.

Delete photo

DELETE /v1/vehicles/{external_vehicle_id}/photos/{photo_id}
Removes the selected photo and normalises the remaining photo ordering.

Photo snapshots

PUT /v1/vehicles/{external_vehicle_id}/photos/snapshot
Replaces the complete API-managed remote photo set for one vehicle.
JSON
{
  "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"
    }
  ]
}
An empty complete photo snapshot is rejected unless 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.

Dynamic reference: do not hardcode the available feature list permanently in an integration. Use GET /v1/features to retrieve the current active AutoHands feature catalog.
GET /v1/features
Returns all currently active vehicle equipment values accepted by the Inventory API.

Request

cURL
curl https://api.autohands.be/v1/features \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Response

JSON
{
  "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:

JSON
{
  "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.

Update behaviour: when 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

Values
passenger_car
oldtimer
light_commercial
camper

Condition

Values
new
used
demonstration

Fuel

Values
petrol
diesel
electric
hybrid
plug_in_hybrid
lpg
cng
hydrogen
other

Transmission

Values
manual
automatic
semi_automatic

Body type

Values
city_car
hatchback
sedan
station_wagon
suv
crossover
coupe
convertible
monovolume
pickup
van
other

Drivetrain

Values
front_wheel_drive
rear_wheel_drive
all_wheel_drive
four_wheel_drive
unknown

Listing status

Values
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.

Unknown or unsupported values are rejected instead of being silently converted to an unrelated value.

Errors

API errors are returned as JSON.

Example
{
  "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.