For dealers
Dealer API and lead webhook
Dealers on the Pro and Group plans can connect their own system to Car 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": "Toyota",
"model": "Corolla",
"year": 2021,
"price": 28990,
"condition": "used",
"category": "hatchbacks",
"odometer_km": 42000,
"fuel": "petrol",
"drive_type": "fwd",
"transmission": "auto",
"engine_l": 2.0,
"power_kw": 125,
"tare_kg": 1340,
"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 Toyota, Mazda, Ford. |
modelModel | Yes | For example Corolla or Ranger. |
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 GX or XLT. |
odometer_kmOdometer (km) | No | Whole kilometres. Needed for a demo, used or damaged car; a new car may leave it out. |
fuelFuel | No | Petrol, Diesel, Hybrid, Plug-in hybrid, Electric, LPG or Hydrogen. Needed for every car. |
drive_typeDrive | No | Front-wheel drive, Rear-wheel drive, All-wheel drive or Four-wheel drive (or FWD, RWD, AWD, 4WD). Needed for every car. |
transmissionTransmission | No | Manual, Semi-automatic or Automatic. |
gearboxGearbox | No | As you would describe it, for example 8-speed automatic, 7-speed DCT or CVT, up to 60 characters. Shown in the ad. |
body_doorsDoors | No | How many doors, 2 to 5. |
seatsSeats | No | How many seats, 1 to 15. |
engine_lEngine (litres) | No | The engine size in litres with at most one decimal place, for example 2.4 (or in cc, for example 2393 cc). Left out for an electric car. |
cylindersCylinders | No | How many cylinders, 0 to 16 (0 or blank for an electric car). |
inductionInduction | No | Naturally aspirated, Turbocharged, Supercharged, Turbocharged and supercharged or Electric motor. |
rotaryRotary engine | No | Yes or no. Left out for an electric car. |
engine_modifiedEngine performance-modified | No | Yes or no. A performance modification bans the car for P-plate drivers in NSW, VIC, QLD and SA. |
power_kwPower (kW) | No | In kW with at most one decimal place, 1 to 1,500 kW. |
torque_nmTorque (Nm) | No | Whole Nm, 1 to 3,000 Nm. |
tare_kgTare (kg) | No | In kg, from the compliance plate or the registration papers, 300 to 4,500 kg. |
gvm_kgGVM (kg) | No | Gross vehicle mass in kg, 500 to 4,500 kg, never less than the tare. |
towing_braked_kgTowing braked (kg) | No | The braked towing capacity in kg, 0 to 5,000 kg. |
towing_unbraked_kgTowing unbraked (kg) | No | The unbraked towing capacity in kg, 0 to 1,000 kg, never more than the braked. |
range_kmElectric range (km) | No | Whole km, 1 to 2,000 km. Electric and plug-in hybrid cars only. |
battery_kwhBattery (kWh) | No | In kWh with at most one decimal place, 0.1 to 999.9 kWh. Electric and plug-in hybrid cars only. |
charge_ac_kwAC charging (kW) | No | In kW with at most one decimal place, 0.1 to 99.9 kW. Electric and plug-in hybrid cars only. |
charge_dc_kwDC charging (kW) | No | In kW with at most one decimal place, 0.1 to 999.9 kW. Electric and plug-in hybrid cars only. |
charge_plugCharging plug | No | For example Type 2 and CCS2, up to 60 characters. Shown in the ad. Electric and plug-in hybrid cars only. |
ownersOwners | No | How many owners it has had, 1 to 20. |
seriesSeries | No | The series or generation as you advertise it, for example 300 Series or VE, up to 40 characters. Shown in the ad; matched to the model's series where we know it. |
service_historyService history | No | Full service history, Partial service history or No service history. |
warranty_untilWarranty until | No | The day the warranty ends, as 2028-06-30 or 30/06/2028. |
warranty_kmWarranty (km) | No | The kilometres the warranty runs to, 1 to 1,000,000 km. |
fuel_lFuel tank (litres) | No | In litres with at most one decimal place, 1 to 999.9 L. Left out for an electric car. |
fuel_use_l100Fuel use (L/100 km) | No | In litres per 100 km with at most one decimal place, 0.1 to 99.9. Left out for an electric car. |
co2_gkmCO2 (g/km) | No | Whole grams per km, 0 to 999. |
colourColour | No | |
categoryCategory | No | Sedans, hatchbacks, SUVs, utes, wagons, vans 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_drivesRuns and drives? | No | Runs and drives, runs but not driveable, does not run, 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;503Car 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-CarDomain-Event: lead.created
X-CarDomain-Delivery: 5521
X-CarDomain-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 Toyota Corolla", "year": 2021,
"make": "Toyota", "model": "Corolla", "price_cents": 2899000, "url": "https://cardomain.com.au/car/..."},
"customer": {"name": "Sam", "phone": "+61400000000"},
"message": "Hi, is this car 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-CarDomain-Signature header before you trust the body, and refuse one older than five minutes:
import { createHmac, timingSafeEqual } from 'node:crypto';
// header: the X-CarDomain-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.
