For dealers
Dealer API and lead webhook
Dealers on the Pro and Group plans can connect their own system to Caravan Domain: keep ads in step with the yard, send photos, and read leads as they arrive.
Keys
A manager or the owner makes a key under API keys in the dealer console. The key starts with bd_live_ and is shown once: we keep only a fingerprint of it. Send it on every request as Authorization: Bearer followed by the key. A key may do one or both of:
listings:write: list, add, change and withdraw your ads, send their photos, and read the result of each change;leads:read: read your leads and their messages.
Each key may make 600 requests an hour; past that the answer is 429 with a Retry-After header. Every call is logged against the key. Revoke a key from the console and it stops at once. Keys stop working while the dealership has no Pro or Group plan, and start again when it does.
Endpoints
All answers are JSON. Times are ISO 8601.
| Request | Scope | What it does |
|---|---|---|
GET /api/v1/listings?limit=50&cursor= | listings:write | Your ads, newest first, 100 at most a page. Pass next_cursor back as cursor for the next page; status=active narrows the list. |
PUT /api/v1/listings/{stock_no} | listings:write | Adds or changes the ad with this stock number, through the same checks as a file import. A new ad starts as a draft and goes to our checks once its photos are in and your page is approved. A live ad takes changes to its price, odometer, colour, registration and description; other changes need a new ad. |
DELETE /api/v1/listings/{stock_no} | listings:write | Withdraws a live ad. |
PUT /api/v1/listings/{stock_no}/photos | listings:write | {"photos": [up to 12 https links in order]}, and vin_plate_photo for damaged stock. We fetch them in the background. Photos of a live ad do not change this way (a new photo is checked before it is shown). |
GET /api/v1/leads?since= | leads:read | Leads with activity after since, oldest first, with their messages. Pass next_since back as since, exactly as given, for the next page. has_more is true while another page is waiting; on the last page, keep next_since and send it on your next poll to get only the leads with newer activity. A page with no leads returns a null next_since: keep the since you sent. The buyer's email address is included only when they agreed to share it with you. |
GET /api/v1/runs/{id} | listings:write | The result of a change or an import: counts, errors and warnings. |
Adding or changing an ad
PUT /api/v1/listings/A1234
Authorization: Bearer bd_live_...
Content-Type: application/json
{
"make": "Jayco",
"model": "Journey",
"year": 2021,
"price": 58990,
"condition": "used",
"category": "caravans",
"atm_kg": 2900,
"tare_kg": 2400,
"length": "19'6"",
"axle_config": "tandem",
"berths": 4,
"ensuite": true,
"water_l": 190,
"colour": "White",
"rego_status": "registered",
"rego_no": "ABC123",
"description": "One owner, serviced by us, new tyres. Comes with the spare key and books.",
"photo": ["https://images.dealer.example/a1234-1.jpg", "https://images.dealer.example/a1234-2.jpg"]
}201 {"status": "created", "listing_id": 100512, "run_id": 88, "warnings": []}
202 {"status": "invalid", "run_id": 89, "errors": [{"field": "year", "code": "year_out_of_range", "message": "..."}], "warnings": []}An ad that fails the checks is answered 202 with an errors list, one entry per field, and nothing is saved. The VIN, chassis number and engine number are stored encrypted and never returned by the API. Only a dealer's ad shows one, and only where the dealer's state requires it.
Fields
| Field | Required | Notes |
|---|---|---|
stock_noStock number | Yes | Unique for each vehicle in your yard. It is how we match a row to its ad next time. |
makeMake | Yes | For example Jayco, Avida, Lotus Caravans. |
modelModel | Yes | For example Journey. |
yearYear | Yes | The model year, four digits. |
priceDrive-away price | Yes | One all-inclusive price in dollars (dealer ads must show the drive-away price). |
conditionCondition | Yes | New, demo, used, damaged (repairable write-off), statutory write-off or parts only. |
variantVariant | No | For example Outback. |
odometer_kmOdometer (km) | No | Whole kilometres. Needed for motorhomes, campervans and buses; left out for anything towed. |
atm_kgATM (kg) | No | Aggregate trailer mass in kg, from the compliance plate. Needed for caravans, pop tops, hybrids, camper trailers and toy haulers. |
tare_kgTare (kg) | No | In kg, from the compliance plate. |
ball_weight_kgBall weight (kg) | No | In kg. |
gtm_kgGTM (kg) | No | Gross trailer mass in kg, from the compliance plate, 1 to 10,000 kg. Caravans, pop tops, hybrids, camper trailers and toy haulers only. |
axle_configAxles | No | Single axle, Tandem axle or Tri-axle. Caravans, pop tops, hybrids, camper trailers and toy haulers only. |
terrain_ratingBuilt for | No | On-road, Semi off-road or Off-road. Caravans, pop tops, hybrids, camper trailers and toy haulers only. |
annexeAnnexe | No | Yes or no. Caravans, pop tops, hybrids, camper trailers and toy haulers only. |
gvm_kgGVM (kg) | No | Gross vehicle mass in kg (motorhomes, campervans and buses). |
licence_classLicence needed | No | Car licence, Light rigid (LR), Medium rigid (MR) or Heavy rigid (HR). A GVM of 4,500 kg or less is a car licence. Motorhomes, campervans and buses only. |
fuelFuel | No | Diesel, Petrol, LPG or Electric. Motorhomes, campervans and buses only. |
transmissionTransmission | No | Manual, Semi-automatic or Automatic. Motorhomes, campervans and buses only. |
engine_lEngine (litres) | No | The engine size in litres with at most one decimal place, for example 2.3. Motorhomes, campervans and buses only. |
chassis_makeBase vehicle | No | The make the motorhome, campervan or bus is built on: Fiat, Ford, Hino, Hyundai, Isuzu, Iveco, LDV, Mercedes-Benz, Mitsubishi, Nissan, Renault, Toyota, Volkswagen. Motorhomes, campervans and buses only. |
chassis_modelBase vehicle model | No | For example Ducato or Sprinter, up to 100 characters. Shown in the ad. Motorhomes, campervans and buses only. |
lengthLength | No | Body length in feet (21 or 21'6"), or with a unit (6550 mm, 6.55 m). |
berthsSleeps | No | How many it sleeps, 1 to 12. |
bunksBunks | No | How many bunks, 0 to 6. |
ensuiteEnsuite | No | Yes or no. |
airconAir conditioning | No | Yes or no. |
solarSolar | No | Yes or no. The panels' watts go in "Solar panels (watts)". |
water_lFresh water (litres) | No | Whole litres, 0 to 5,000 L. |
battery_ahBattery (Ah) | No | Whole amp hours, 0 to 10,000 Ah. |
solar_wSolar panels (watts) | No | Whole watts, 0 to 20,000 W. |
fridgeFridge | No | As you would describe it, up to 100 characters. Shown in the ad. |
hot_waterHot water | No | As you would describe it, up to 100 characters. Shown in the ad. |
island_bedIsland bed | No | Yes or no. |
colourColour | No | |
categoryCategory | No | Caravans, pop tops, hybrids, camper trailers, motorhomes, campervans and so on. Taken from the model when left out. |
descriptionDescription | No | Plain text. Leave the VIN out: it goes in the VIN column. Only a dealer's ad shows a VIN, and only where the dealer's state requires it. |
photoPhoto URLs | No | Up to 12 https:// links, in order: one per column, or several in one cell separated by | , or spaces. |
rego_noRegistration number | No | The plate number. Shown on the ad where the state requires it. |
rego_statusRegistered? | No | Registered, unregistered, recreational or cannot be registered. Taken as registered when a plate is given. |
vinVIN | No | Stored encrypted and never shown in a report or a download. Only a dealer's ad shows it, and only where the dealer's state requires it. |
chassis_noChassis number | No | Where there is no VIN. Stored encrypted and never shown in a report or a download. Only a dealer's ad shows it, and only where the dealer's state requires it. |
engine_noEngine number | No | Stored encrypted and never shown in a report or a download. Only a dealer's ad shows it, and only where the dealer's state requires it. |
suburbSuburb | No | Where the vehicle is. Your dealership's suburb when left out. |
postcodePostcode | No | |
price_typePrice basis | No | Leave out, or "drive away". Prices plus government charges are not accepted. |
writeoff_statusWritten-off status (WOVR) | No | Not recorded, repairable, statutory or unknown. Needed for damaged stock. |
writeoff_stateWritten off in (state) | No | NSW, VIC, QLD, WA, SA, TAS, ACT or NT. |
sold_asSold as | No | Whole, parts only, or not for use on public roads. Needed for damaged stock. |
runs_towsRuns and tows? | No | Runs and drives or can be towed, cannot be driven or towed, does not run (a motorhome, campervan or bus), or unknown. Needed for damaged stock. |
damage_typesDamage | No | Any of: cosmetic, crash, chassis, engine, mechanical, flood, fire, hail, stolen recovered, missing parts, project. |
damage_descriptionDamage report | No | What is damaged, in plain words. |
vin_plate_photoVIN or compliance plate photo URL | No | Needed for damaged stock. Never shown in the ad. |
has_spare_keyKeys present | No | Yes or no. |
Answers you may get
400a request we cannot read;401a missing, unknown or revoked key;403a key without the scope, or a dealership that is not verified or has no Pro or Group plan;404not one of your ads or runs;409an ad in a state that does not allow it;413a body over 64 KB;429too many requests;503Caravan Domain is read-only for a moment (try again later).
Lead webhook
On the Pro and Group plans you can give us an https address under your dealership profile. We post each new lead there as JSON. If your address does not answer with a 2xx status we try again three times, after 1, 5 and 25 minutes. We never follow a redirect, and addresses on private or internal networks are refused.
POST (your address)
Content-Type: application/json
X-CaravanDomain-Event: lead.created
X-CaravanDomain-Delivery: 5521
X-CaravanDomain-Signature: t=1790000000,v1=5f0c...
{
"event": "lead.created",
"id": "8d5e...",
"created_at": "2026-10-01T09:30:00.000Z",
"listing": {"id": 100512, "stock_no": "A1234", "title": "2021 Jayco Journey", "year": 2021,
"make": "Jayco", "model": "Journey", "price_cents": 5899000, "url": "https://caravandomain.com.au/caravan/..."},
"customer": {"name": "Sam", "phone": "+61400000000"},
"message": "Hi, is this van still available?"
}Each post is signed with your webhook secret (shown once when you set the address; make a new one from your profile at any time). Check the X-CaravanDomain-Signature header before you trust the body, and refuse one older than five minutes:
import { createHmac, timingSafeEqual } from 'node:crypto';
// header: the X-CaravanDomain-Signature value, body: the raw request body as received
export function verify(secret, body, header, nowSeconds) {
const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header);
if (!m || Math.abs(nowSeconds - Number(m[1])) > 300) return false;
const want = createHmac('sha256', secret).update(m[1] + '.' + body).digest();
const got = Buffer.from(m[2], 'hex');
return got.length === want.length && timingSafeEqual(got, want);
}ADF lead emails
Any dealer can also have each new lead emailed to their dealer system in the ADF 1.0 format, one lead per email. Set the address under your dealership profile and send a test lead from there. The buyer's email address is in it only when they agreed to share it.
