Put your stock on MotorLoop from your own system
A documented REST API for creating, updating and reading vehicle listings — plus an MCP server if you would rather let an AI assistant do the work. Both are free to use, and a private seller with one car gets the same endpoints as a dealer with two hundred.
API tokens do not reach the REST API on MotorLoop yet.
A token still works with an AI assistant straight away — that is the MCP server, and it needs no setting changed. For the REST endpoints below, a storefront administrator switches this on in Store settings. Talk to us and we will help you get it turned on.
Type it once, not twice
If your stock already lives somewhere — a dealer management system, a spreadsheet, your own website — that system is the source of truth. Re-typing each car into a second web form is where the errors come from: the price that was updated in one place and not the other, the car that sold on Tuesday and was still advertised on Friday.
One source of truth
Push from the system you already keep up to date. Change a price there and send one small request here.
Nothing goes live by accident
Everything you create starts as a draft. You choose when a listing is published, and you can unpublish it the same way.
Your own field set
The vehicle fields are configurable per storefront, so the API tells you what this one accepts rather than making you guess.
New here? MotorLoop is a place to buy, sell & show cars, and listing is free. Create an account to get started, or read how we compare to other sites.
Your first call, in about five minutes
01
Create an account
Free, and the same account you would use to list a car by hand.
02
Mint a token
Profile → API tokens → Create token. Tick “Create and update your listings” if you intend to write. The secret is shown once.
03
Check it is accepted here
See the banner at the top of this page. If REST is off for this storefront, an administrator turns it on first.
04
Read the field schema
Call /api/vehicles/attributes before you write anything. It tells you the field names, types and allowed values for this storefront.
Then read five listings — no token needed
Searching is open to anyone, so this runs before you have signed up for anything.
Your endpoint base is
https://api.motorloop.com.au/motorloopEvery route below hangs off it. The storefront name is part of the address — a token is scoped to the storefront it was created on.
Five things that will bite you
Each of these returns a success code while doing something other than what you meant. They are worth two minutes now.
01There is no “year” field, and no “state” field
Model year and location are ordinary schema fields, so they belong inside `extras` — on the shipped catalogue they are ModelYearMY and State. A top-level "year" in the body is ignored without complaint: you get 201 Created and a listing with no year on it. Call GET /api/vehicles/attributes and use the names it gives you.
02PUT replaces the whole listing
The attributes you send become the complete set, and anything you leave out is cleared. Updating a price with a two-field PUT will strip the spec sheet off the car. For routine changes use POST /{id}/price, POST /{id}/status or POST /{id}/flags, which only touch what they name.
03API tokens are switched off on the REST API by default
A token works with an AI assistant straight away, but reaching these endpoints is a separate per-storefront setting. Until it is on, a perfectly valid token gets a 401 that looks exactly like a bad one. Check the banner at the top of this page for this storefront’s answer.
04Field values are matched exactly, capitals and all
"VIC" is accepted and "vic" is not; "SUV" works and "suv" does not. Take the option strings verbatim from GET /api/vehicles/attributes rather than normalising them yourself.
05New listings are Drafts
Nothing you create through the API is visible to a buyer until you call POST /{id}/status with Active. That is deliberate — it gives you a chance to check an import before it reaches the public site.
Try it without writing any code
The API publishes an interactive console and a machine-readable OpenAPI document. The console sends real requests, so you can paste a token in and watch a call succeed before you build anything. The document imports straight into Postman, Insomnia or a client generator.
The document describes the member surface only — the endpoints on this page, and none of the administrative ones. Because you fetch it under a storefront, it comes back already pointed at https://api.motorloop.com.au/motorloop: paths resolve as-is, with nothing to configure.
Endpoint reference
Everything a member account can reach. Anything marked NO TOKEN works signed out.
Reading listingsTOKEN+–
Open to anyone — no token needed. Use these to pull your own stock back, or to read the storefront’s field schema before you write anything.
GET/api/vehiclesno token
Search public listings.
| Parameter | In | What it does |
|---|---|---|
q | query · string | Free text over make, model, description and the ML plate. |
make | query · string | Comma-separated. Punctuation-insensitive, so “Mercedes Benz” matches “Mercedes-Benz”. |
model | query · string | Single value, exact match. |
listingType | query · string | Comma-separated names: Sale, Swap, SaleOrSwap, Wanted, Showcase, Rental. A bare number is refused. |
status | query · string | Narrows within the public set only: sold, active or under-offer. It cannot reach Draft or Archived. |
minPrice / maxPrice | query · number | Price bounds. |
minOdo / maxOdo | query · number | Odometer bounds, km. |
location | query · string | Comma-separated clauses OR together; parts joined with “/” must all match one stored value, e.g. Richmond/Victoria. |
nearLat, nearLng, withinKm | query · number | All three or none — a partial set is a 400. Radius up to 1000 km. |
seller | query · string | A seller @handle. Unknown handles return an empty list rather than an error. |
{FieldName} | query · string | One parameter per enum field in the storefront schema, comma-separated OR — e.g. ?BodyType=SUV,Ute&Transmission=Automatic. Call /api/vehicles/attributes for the live list. |
min{FieldName} / max{FieldName} | query · number | Bounds for any number, date or month-year field — e.g. ?minModelYearMY=2015&maxSeats=5. |
sort | query · string | price_asc, price_desc, oldest, newest (default), or {Field}_asc / {Field}_desc for a sortable field. An unknown value silently falls back to newest. |
page | query · integer | Defaults to 1. |
pageSize | query · integer | Defaults to 20, clamped to 1–100. |
Returns Active, Sold and UnderOffer listings. A signed-in caller also sees their own Unlisted ones.
The per-field filters above are read straight off the query string, so they will not appear in the OpenAPI document — the field list is whatever GET /api/vehicles/attributes returns for your storefront.
curl -X GET 'https://api.motorloop.com.au/motorloop/api/vehicles'GET/api/vehicles/{id}no token
One listing by id, including its attributes and photos.
| Parameter | In | What it does |
|---|---|---|
id* | path · uuid | The listing id. |
Visible statuses are Active, Sold, Unlisted and UnderOffer. Anything else is a 404 unless you own it.
Reading through the API never counts as a listing view — the view counter only increments for a request carrying the X-ML-View header, so a sync job cannot inflate your own numbers.
curl -X GET 'https://api.motorloop.com.au/motorloop/api/vehicles/00000000-0000-0000-0000-000000000000'GET/api/vehicles/by-slug/{slug}no token
One listing by its public URL slug.
| Parameter | In | What it does |
|---|---|---|
slug* | path · string | e.g. 2019-toyota-corolla-ml-abc-123. Resolved by the ML-plate tail. |
curl -X GET 'https://api.motorloop.com.au/motorloop/api/vehicles/by-slug/2019-toyota-corolla-ml-abc-123'GET/api/vehicles/mineread scope
Your own listings, in every status.
No paging and no filters — it returns everything you own, newest first.
⚠ The attributes bag comes back empty here. If your sync needs field values back, follow up with GET /api/vehicles/{id} per listing, or use the MCP my_vehicles tool, which does return them.
curl -X GET 'https://api.motorloop.com.au/motorloop/api/vehicles/mine' \
-H 'Authorization: Bearer mlp_YOUR_TOKEN'GET/api/vehicles/attributesno token
The storefront’s vehicle field schema — the contract your import must satisfy.
| Parameter | In | What it does |
|---|---|---|
includeCore | query · boolean | Adds Make, Model and Odometer, which are top-level fields rather than attributes. Send true when you are building an importer. |
Start here. Field names, data types, enum options, min/max bounds and which fields are required are all per storefront and operator-configurable — there is no fixed list to hard-code.
curl -X GET 'https://api.motorloop.com.au/motorloop/api/vehicles/attributes'GET/api/vehicles/facetsno token
Filter metadata with live counts — makes, body types, price and odometer ranges, locations.
| Parameter | In | What it does |
|---|---|---|
listingType | query · string | Narrow the counts to these listing types. |
status | query · string | Narrow the counts to sold / active / under-offer. |
curl -X GET 'https://api.motorloop.com.au/motorloop/api/vehicles/facets'GET/api/vehicles/makesno token
Make options with live listing counts.
curl -X GET 'https://api.motorloop.com.au/motorloop/api/vehicles/makes'Creating and updatingTOKEN+–
Needs a token with the write scope. A new listing is always created as a Draft; publishing is a separate call.
POST/api/vehicleswrite scope
Create a listing. It is always created as a Draft.
| Parameter | In | What it does |
|---|---|---|
make* | body · string | Up to 100 characters. |
model* | body · string | Up to 100 characters. |
odometerKm* | body · integer | 0–2,000,000. |
price* | body · number | 0–100,000,000. |
termsVersion* | body · string | Required on create. Omit it and the call is refused before any other check runs. |
currency | body · string | Three letters. Blank defaults to AUD. |
description | body · string | Up to 4000 characters. |
extras | body · object | Field name → array of strings, for every field from /api/vehicles/attributes. Single-value fields still take a one-element array. |
inventoryNo | body · string | The public ML plate. Leave it blank and one is assigned. It is globally unique — this is not your stock number. |
listingType | body · string | Sale (default), Swap, SaleOrSwap, Wanted, Showcase or Rental. |
template | body · string | Detail-page layout: standard, car-cinematic, cinematic-clean or car-editorial. |
socialSharing | body · boolean | Opt the listing into share cards. New listings start off. |
commentsDisabled | body · boolean | Turn off comments for this listing. |
There is no `year` field and no `state` field. Both are ordinary schema fields and belong in `extras` — on the shipped catalogue they are ModelYearMY and State.
Photos are not part of this call. Upload them afterwards, or use the MCP bulk tool, which can fetch them from URLs.
curl -X POST 'https://api.motorloop.com.au/motorloop/api/vehicles' \
-H 'Authorization: Bearer mlp_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"make": "Toyota",
"model": "Corolla",
"odometerKm": 84200,
"price": 21990,
"currency": "AUD",
"description": "One owner, full service history, new tyres.",
"extras": {
"ModelYearMY": [
"2019"
],
"State": [
"VIC"
],
"BodyType": [
"Hatch"
],
"Transmission": [
"Automatic"
],
"FuelType": [
"Petrol"
],
"Colour": [
"White"
],
"StockNumber": [
"DLR-1042"
],
"Features": [
"Bluetooth",
"Reversing Camera",
"Apple CarPlay"
]
},
"termsVersion": "2026-08-03"
}'PUT/api/vehicles/{id}write scope
Replace a listing’s details.
| Parameter | In | What it does |
|---|---|---|
id* | path · uuid | The listing id. |
⚠ This is a full replace, not a patch. Whatever you send in `extras` becomes the complete set of attributes — every field you leave out is cleared from the listing.
To change one thing on a live listing, prefer POST /{id}/price, POST /{id}/status or POST /{id}/flags. They touch only what they name.
If you must use PUT, read the listing first with GET /api/vehicles/{id}, change what you need in the returned attributes, and send the whole bag back.
curl -X PUT 'https://api.motorloop.com.au/motorloop/api/vehicles/00000000-0000-0000-0000-000000000000' \
-H 'Authorization: Bearer mlp_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"make": "Toyota",
"model": "Corolla",
"odometerKm": 84200,
"price": 20990,
"currency": "AUD",
"description": "One owner, full service history, new tyres.",
"extras": {
"ModelYearMY": [
"2019"
],
"State": [
"VIC"
],
"BodyType": [
"Hatch"
],
"Transmission": [
"Automatic"
],
"FuelType": [
"Petrol"
],
"Colour": [
"White"
],
"StockNumber": [
"DLR-1042"
],
"Features": [
"Bluetooth",
"Reversing Camera",
"Apple CarPlay"
]
}
}'POST/api/vehicles/{id}/statuswrite scope
Publish, unpublish, or mark sold.
| Parameter | In | What it does |
|---|---|---|
id* | path · uuid | The listing id. |
This is how a Draft goes live. Nothing you create through the API is public until you call it.
Moving a listing into or out of Pending is administrator-only; every other transition is yours to make.
curl -X POST 'https://api.motorloop.com.au/motorloop/api/vehicles/00000000-0000-0000-0000-000000000000/status' \
-H 'Authorization: Bearer mlp_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"status": "Active"
}'POST/api/vehicles/{id}/pricewrite scope
Change the price without touching anything else.
| Parameter | In | What it does |
|---|---|---|
id* | path · uuid | The listing id. |
The right call for a nightly price sync — it carries none of the full-replace risk that PUT does.
curl -X POST 'https://api.motorloop.com.au/motorloop/api/vehicles/00000000-0000-0000-0000-000000000000/price' \
-H 'Authorization: Bearer mlp_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"price": 20990,
"currency": "AUD"
}'POST/api/vehicles/{id}/flagswrite scope
Toggle sharing, comments or listing type in place.
| Parameter | In | What it does |
|---|---|---|
id* | path · uuid | The listing id. |
Any field you omit is left as it was.
curl -X POST 'https://api.motorloop.com.au/motorloop/api/vehicles/00000000-0000-0000-0000-000000000000/flags' \
-H 'Authorization: Bearer mlp_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"socialSharing": true,
"listingType": "SaleOrSwap"
}'DELETE/api/vehicles/{id}write scope
Delete a listing.
| Parameter | In | What it does |
|---|---|---|
id* | path · uuid | The listing id. |
A soft delete — the listing disappears from every surface, and an administrator can restore it.
Consider POST /{id}/status with Archived instead: it keeps the listing in your own list where you can see it.
curl -X DELETE 'https://api.motorloop.com.au/motorloop/api/vehicles/00000000-0000-0000-0000-000000000000' \
-H 'Authorization: Bearer mlp_YOUR_TOKEN'PhotosTOKEN+–
Photos are uploaded as multipart form data. Ordering matters — index 0 is the cover image.
POST/api/vehicles/{id}/imageswrite scope
Upload one or more photos.
| Parameter | In | What it does |
|---|---|---|
id* | path · uuid | The listing id. |
files* | form · file[] | jpg, jpeg, png or webp; up to 10 MB each. |
labels | form · string[] | Optional, one entry per file in the same order — an image-label tag id, or empty for none. |
multipart/form-data. The first photo by sort order is the cover image.
Listings have a per-storefront photo cap, and photos below the storefront’s minimum resolution are refused.
There is no photo-by-URL option on this endpoint. If your images live on a web server, the MCP bulk import can fetch them for you.
curl -X POST 'https://api.motorloop.com.au/motorloop/api/vehicles/00000000-0000-0000-0000-000000000000/images' \
-H 'Authorization: Bearer mlp_YOUR_TOKEN'PUT/api/vehicles/{id}/images/orderwrite scope
Reorder photos, or choose a new cover image.
| Parameter | In | What it does |
|---|---|---|
id* | path · uuid | The listing id. |
The list must contain every current photo exactly once. Index 0 becomes the cover.
curl -X PUT 'https://api.motorloop.com.au/motorloop/api/vehicles/00000000-0000-0000-0000-000000000000/images/order' \
-H 'Authorization: Bearer mlp_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"imageIds": [
"00000000-0000-0000-0000-000000000001",
"00000000-0000-0000-0000-000000000002"
]
}'PUT/api/vehicles/{id}/images/{imageId}/labelwrite scope
Label a photo (“Front”, “Interior”, …), or clear its label.
| Parameter | In | What it does |
|---|---|---|
id* | path · uuid | The listing id. |
imageId* | path · uuid | The photo id. |
Send null to clear. Label ids come from GET /api/tags — they are the tags of type ImageLabel.
curl -X PUT 'https://api.motorloop.com.au/motorloop/api/vehicles/00000000-0000-0000-0000-000000000000/images/00000000-0000-0000-0000-000000000000/label' \
-H 'Authorization: Bearer mlp_YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"tagId": null
}'PUT/api/vehicles/{id}/images/{imageId}write scope
Swap the file behind an existing photo, keeping its position and label.
| Parameter | In | What it does |
|---|---|---|
id* | path · uuid | The listing id. |
imageId* | path · uuid | The photo id. |
file* | form · file | The replacement image. |
curl -X PUT 'https://api.motorloop.com.au/motorloop/api/vehicles/00000000-0000-0000-0000-000000000000/images/00000000-0000-0000-0000-000000000000' \
-H 'Authorization: Bearer mlp_YOUR_TOKEN'DELETE/api/vehicles/{id}/images/{imageId}write scope
Delete a photo.
| Parameter | In | What it does |
|---|---|---|
id* | path · uuid | The listing id. |
imageId* | path · uuid | The photo id. |
curl -X DELETE 'https://api.motorloop.com.au/motorloop/api/vehicles/00000000-0000-0000-0000-000000000000/images/00000000-0000-0000-0000-000000000000' \
-H 'Authorization: Bearer mlp_YOUR_TOKEN'Account and reference dataTOKEN+–
Who am I, and the lookups the vehicle fields depend on. Creating and revoking tokens is deliberately not here — that is a browser task, and a token is refused if it tries to mint another one.
GET/api/auth/meread scope
The account behind the token, with its roles and permissions.
The quickest way to confirm a token works and to see what it is allowed to do.
curl -X GET 'https://api.motorloop.com.au/motorloop/api/auth/me' \
-H 'Authorization: Bearer mlp_YOUR_TOKEN'GET/api/tenant-infono token
The storefront’s public settings, including whether API tokens are accepted here.
curl -X GET 'https://api.motorloop.com.au/motorloop/api/tenant-info'GET/api/tagsno token
Photo label options, so you can set one by id.
Listed here for one reason: labelling a photo takes a tag id, and this is where the ids come from. Look for the tags whose type is ImageLabel.
curl -X GET 'https://api.motorloop.com.au/motorloop/api/tags'GET/api/placesno token
Suburb and town lookup, for fields whose type is `suburb`.
| Parameter | In | What it does |
|---|---|---|
q* | query · string | What to search for. |
country | query · string | ISO2 code or country name. Omit to search worldwide. |
limit | query · integer | Up to 25. |
A suburb field stores the composed value this returns, coordinates and all — do not hand-assemble it.
curl -X GET 'https://api.motorloop.com.au/motorloop/api/places'Statuses you can set
| Value | Shown as | What it means |
|---|---|---|
Draft | Draft | Yours only. Where every new listing starts. |
Active | Listed | Public and browsable. |
Unlisted | Unlisted | Published but hidden from search — reachable by its direct link. |
UnderOffer | Under Offer | Still public and still contactable, marked as spoken for. |
Sold | Sold | Stays visible, marked sold. |
Archived | Archived | Retired from every public surface, kept in your own list. |
Moving a listing into or out of the moderation queue is an administrator action, so those states are not settable through the API.
This storefront’s vehicle fields
MotorLoop accepts 79 vehicle fields beyond make, model and odometer. They are configurable, so treat this list as a snapshot and read /api/vehicles/attributes at run time rather than hard-coding it.
Columns your file needs
| Column | Notes |
|---|---|
stockNumber | Your own reference. The bulk import matches on it, so re-running a file updates nothing twice. Stored as the StockNumber attribute — it is NOT the public ML plate. |
make* | Required. |
model* | Required. |
odometerKm* | Required. Whole kilometres. |
price* | Required. Numbers only — no currency symbol, no thousands separator. |
currency | Three letters. Blank means AUD. |
description | Free text, up to 4000 characters. |
listingType | Sale, Swap, SaleOrSwap, Wanted, Showcase or Rental. Blank means Sale. |
status | What to set after creating. Blank leaves the listing as a Draft. |
imageUrls | Pipe-separated public https URLs. Used by the MCP bulk import, which downloads them; the REST API uploads files instead. |
All 79 schema fields on this storefront+–
Send these inside extras, each as an array of strings. Values are matched exactly, capitals included. In a CSV, separate multiple values with |.
| Field | Type | Section | Accepted values |
|---|---|---|---|
SeriesSeries | text | Main | Free text |
BadgeBadge | text | Main | Free text |
ModelYearMYModel Year (MY) | monthyear | Main | Free text |
Suburb*Vehicle Location | suburb | Main | Free text |
PriceTypePrice Type | enum | Main | Negotiable, Fixed Price, Drive Away, Excl. Gov. Charges |
dealer-nameName | text | Dealer Details | Free text |
dealer-addressLocation | address | Dealer Details | Free text |
car-delaer-lmctLMCT | number | Dealer Details | Free text |
dealer-phonePhone | text | Dealer Details | Free text |
EngineDescriptionEngine Description | text | Engine & Drivetrain | Free text |
EngineSizeEngine Size | number | Engine & Drivetrain | Free text |
CylindersCylinders | enum | Engine & Drivetrain | 2, 3, 4, 5, 6, 8, 10, 12 |
InductionInduction | enum | Engine & Drivetrain | Aspirated, Turbo, Twin Turbo, Supercharged, Turbo Supercharged, Not Applicable |
FuelType*Fuel Type | enum | Engine & Drivetrain | Petrol, Diesel, Hybrid, Plug-in Hybrid, Electric, Dual Fuel, Gas Only, LPG |
Transmission*Transmission | enum | Engine & Drivetrain | Automatic, Manual, Sports Automatic, AMT, Dual Clutch |
GearsGears | number | Engine & Drivetrain | Free text |
DriveTypeDrive Type | enum | Engine & Drivetrain | Front Wheel Drive, Rear Wheel Drive, All Wheel Drive, 4x4, 4x2, 6x2, 6x6 |
PowerPower | number | Engine & Drivetrain | Free text |
TopSpeedTop Speed | number | Engine & Drivetrain | Free text |
PowerRpmPower RPM | number | Engine & Drivetrain | Free text |
TorqueTorque | number | Engine & Drivetrain | Free text |
Acceleration0-100 km/h | number | Engine & Drivetrain | Free text |
BodyTypeBody Type | enum | Body & Style | Bus, Cab Chassis, Convertible, Coupe, Hatch, People Mover, Sedan, SUV, Ute, Van, Wagon |
ColourColour | enum | Body & Style | Beige, Black, Blue, Bronze, Brown, Burgundy, Gold, Green, Grey, Maroon, Orange, Pink, Purple, Red, Silver, White, Yellow, Other |
PaintNamePaint / Colour Name | text | Body & Style | Free text |
InteriorColourInterior Colour | enum | Body & Style | Beige, Black, Blue, Bronze, Brown, Burgundy, Gold, Green, Grey, Maroon, Orange, Pink, Purple, Red, Silver, White, Yellow, Other |
SeatsSeats | number | Body & Style | Free text |
DoorsDoors | number | Body & Style | Free text |
LifestyleLifestyle | enum (multi) | Body & Style | Family, First Car, Green, Off-road 4x4, Performance, Prestige, Tradie, Unique |
FuelEconomyFuel Economy | number | Fuel & Economy | Free text |
ConsumptionCityConsumption (City) | number | Fuel & Economy | Free text |
ConsumptionHighwayConsumption (Highway) | number | Fuel & Economy | Free text |
FuelCapacityFuel Capacity | number | Fuel & Economy | Free text |
FuelGradeFuel Grade | enum | Fuel & Economy | Standard ULP, Premium ULP 95, Premium ULP 98, Diesel, E10, E85, LPG |
Co2CombinedCO2 (Combined) | number | Fuel & Economy | Free text |
EmissionStandardEmission Standard | enum | Fuel & Economy | Euro 4, Euro 5, Euro 6, Euro 6d |
RangeDriving Range | number | Electric & Hybrid | Free text |
BatteryCapacityBattery Capacity | number | Electric & Hybrid | Free text |
PlugTypePlug Type | enum (multi) | Electric & Hybrid | CCS2, CHAdeMO, Type 1, Type 2 |
AncapRatingANCAP Safety Rating | number | Safety | Free text |
AirbagsAirbags | number | Safety | Free text |
FeaturesSafetySafety & Driver-assist | enum (multi) | Safety | Driver Airbag, Passenger Airbag, Head Airbags (1st Row), Head Airbags (2nd Row), Side Airbags (1st Row), Seatbelt Reminder, Crash Avoidance Braking (Low Speed), Pedestrian AEB, Brake Assist, Emergency Brake Signal, First Aid Kit, Vulnerable Road User Detection, ABS, Traction Control, Electronic Stability Control, Hill Holder, Active Lane Keeping, Forward Collision Warning, Blind Spot Monitoring, Front Parking Sensors, Rear Parking Sensors, Automated Parking Assist, Reversing Camera, Proximity Central Locking, Remote Central Locking |
FeaturesFeatures | enum (multi) | Features | ABS, AEB, Air Conditioning, Alarm, Alloy Wheels, Android Auto, Apple CarPlay, Automatic Headlights, Automatic Wipers, Blind Spot Monitoring, Bluetooth, Bull Bar, Climate Control, Cruise Control, Daytime Running Lights, Diff Lock, ESC, Fog Lights, Forward Collision Warning, Heated Seats, Lane Departure Warning, Leather Seats, Parking Assistance, Parking Sensors, Power Mirrors, Power Windows, Proximity Keyless Entry, Rear Cross Traffic Warning, Remote Central Locking, Reversing Camera, Rollover Stability Control, Satellite Navigation, Steering Wheel Controls, Sunroof, Tow Bar, Traction Control, Trailer Sway Control, Tyre Pressure Sensors, Wheelchair Accessible |
FeaturesAudioAudio & Communication | enum (multi) | Features | Bluetooth, USB Input, Aux Input, Memory Card Reader, Inbuilt Flash Drive, Wireless Charging, Android Auto, Apple CarPlay, Smart Device Integration, Colour Display Screen (Front), 14-Speaker Stereo, Subwoofer, Digital Radio (DAB+), Voice Recognition, Multi-function Control Screen |
FeaturesComfortComfort & Convenience | enum (multi) | Features | Climate Control (2-zone), Adaptive Cruise / Distance Control, Ambient Lighting, Footwell Lamps (Front), Proximity Start Button, Front Centre Armrest, Floor Mats, Illuminated Vanity Mirror, 12V Auxiliary Socket |
FeaturesInstrumentsInstruments | enum (multi) | Features | Full Digital Instrument Display, Trip Computer, Tyre Pressure Monitoring, Satellite Navigation, Speed Limiter |
FeaturesLightsLights & Windows | enum (multi) | Features | Auto High Beam, Adaptive High Beam, Automatic Headlights, LED Headlights, Headlight Washers, LED Tail Lights, LED Daytime Running Lamps, Electric Anti-glare Rear Mirror, Rain-sensing Wipers |
FeaturesExteriorExterior | enum (multi) | Features | Body-coloured Bumpers, Body-coloured Exterior Mirrors, Power Tailgate, Electric Mirrors, Electric Anti-glare Mirrors, Electric Auto-dipping Mirrors, Electric Folding Mirrors, Electric Heated Mirrors, Scuff Plates, Lower Body Kit, Rear Diffuser, Rear Roof Spoiler |
FeaturesDrivetrainDrivetrain & Modes | enum (multi) | Features | Gear Shift Paddles, Selectable Driving Mode, Electronic Differential Lock, Engine Stop-start |
FeaturesSteeringBrakesSteering & Brakes | enum (multi) | Features | Multi-function Steering Wheel, Sports Steering Wheel, Electric Power Steering, Speed-sensitive Steering, Painted Front Calipers, Painted Rear Calipers, Ventilated Front Brakes, Solid Rear Brakes, Electric Park Brake |
FeaturesInteriorInterior | enum (multi) | Features | Leather-look Inserts, Leather-look Door Inserts, Embossed Leather Seats, Nappa Leather Seats, Partial Leather Seats, Leather Steering Wheel, Metallic Air Vents, Metallic Door Mirrors, Metallic Inserts, Metallic Speaker Trims, Sports Pedals |
FeaturesSuspensionWheelsSuspension & Wheels | enum (multi) | Features | Sports Suspension, Lowered Suspension, Tyre Repair Kit |
FeaturesSeatingSeating | enum (multi) | Features | Sports Front Seats, Electric Driver Seat (Lumbar), Electric Passenger Seat (Lumbar), Heated Front Seats, 2nd Row Split-fold |
ConditionCondition | enum | Condition & History | New, Demo, Near New, Used |
BuildDateBuild Date | monthyear | Condition & History | Free text |
ComplianceDateCompliance Date | monthyear | Condition & History | Free text |
RegoExpiryRegistration Expiry | monthyear | Condition & History | Free text |
CountryOfOriginCountry of Origin | country | Condition & History | Free text |
LengthLength | number | Dimensions & Weights | Free text |
WidthWidth | number | Dimensions & Weights | Free text |
HeightHeight | number | Dimensions & Weights | Free text |
WheelbaseWheelbase | number | Dimensions & Weights | Free text |
GroundClearanceGround Clearance | number | Dimensions & Weights | Free text |
TareMassTare Mass | number | Dimensions & Weights | Free text |
GrossVehicleMassGross Vehicle Mass | number | Dimensions & Weights | Free text |
BootSpaceMinBoot Space (Min) | number | Dimensions & Weights | Free text |
BootSpaceMaxBoot Space (Max) | number | Dimensions & Weights | Free text |
TowBrakedTow Braked Capacity | number | Dimensions & Weights | Free text |
TowUnbrakedTow Unbraked Capacity | number | Dimensions & Weights | Free text |
RimMaterialRim Material | enum | Wheels & Tyres | Alloy, Steel, Forged Alloy, Carbon Fibre |
FrontTyreFront Tyre | text | Wheels & Tyres | Free text |
RearTyreRear Tyre | text | Wheels & Tyres | Free text |
FrontRimFront Rim | text | Wheels & Tyres | Free text |
RearRimRear Rim | text | Wheels & Tyres | Free text |
WarrantyWarranty | text | Warranty & Service | Free text |
RoadsideAssistanceRoadside Assistance | text | Warranty & Service | Free text |
AntiCorrosionWarrantyAnti-corrosion Warranty | text | Warranty & Service | Free text |
FirstServiceFirst Service | text | Warranty & Service | Free text |
ServiceIntervalService Interval | text | Warranty & Service | Free text |
Templates for this storefront
Generated from the schema above, not a generic sample — the columns are the ones this storefront actually accepts.
Doing it in bulk
Being straight with you about where this stands: there is no REST endpoint that takes a whole file today. What exists is one request per vehicle, and a batch tool on the MCP side. The CSV template above is a format for your own importer to read — there is nowhere to upload it.
Loading stock for the first time
The MCP bulk tool takes up to 25 vehicles per call, checks every row before it writes any of them, and can rehearse the whole thing without creating anything. Rows carrying a stock number you have used before are skipped rather than duplicated, so re-running a file is safe. It can also fetch photos from URLs you host.
Keeping it up to date
For a nightly sync, loop your changed vehicles and send one small request each: /price for a repricing, /status when something sells. Reach for PUT only when the details themselves changed, and send the whole attribute bag when you do.
REST or MCP?
Two ways into the same marketplace, and the same token works with both. Broadly: write code against REST, point an assistant at MCP.
| What you want to do | Use | Why |
|---|---|---|
| Scripted, repeatable sync from a DMS or spreadsheet | REST | Deterministic requests you can log, retry and diff. |
| Upload photo files you hold on disk | REST | Multipart upload. The MCP tools cannot send file bytes. |
| Add photos from URLs you already host | MCP | The bulk tool fetches them in the background. The REST body has no field for image URLs. |
| Create many listings in one call | MCP | Up to 25 per call, validated as a batch before anything is written. REST is one request per vehicle. |
| Rehearse an import before it writes anything | MCP | A dry run reports what each row would do and creates nothing. |
| Skip rows you have already imported | MCP | Rows are matched on your own stock number, so re-running an import is safe. |
| Let a person manage stock by asking in plain English | MCP | Claude, ChatGPT, Cursor and friends connect directly. |
| Work with no extra storefront settings | MCP | A token reaches MCP straight away; REST needs the storefront to switch it on first. |
| Read listings with no account at all | Either | Searching and reading are open on both channels. |
| Publish, unpublish or mark a car sold | Either | Same underlying operation either way. |
Integrating your own system?
If you run a dealer management system, a website for dealers, or you are a dealer whose stock lives somewhere awkward, tell us what you have and we will work out the mapping with you. Register your interest and we will call — no obligation, and it costs nothing.
Common questions
- Do I need to be a dealer to use the API?
- No. Any account can create a token. The API gives a private seller with one car exactly the same endpoints a dealer with two hundred gets — there is no separate tier and nothing to apply for.
- What does it cost?
- Listing on MotorLoop is free, and using the API to do it is free too. There is no per-call charge and no separate developer plan.
- My token works with an AI assistant but the API returns 401.
- Reaching the REST endpoints is a separate per-storefront setting, and it is off until a storefront administrator turns it on. The refusal deliberately looks the same as an invalid token, so check the banner at the top of this page for this storefront’s answer before you go looking for a bug in your code.
- Why did my listing lose its details after an update?
- PUT replaces the whole listing: the attributes you send become the complete set, and anything you leave out is cleared. For a routine change use the price, status or flags endpoints, which touch only what they name.
- Where do I put the year?
- In the attributes bag, under whatever the storefront calls its model-year field — ModelYearMY on the standard catalogue. There is no top-level year field, and one sent at the top level is ignored rather than rejected, so the listing saves without it.
- Can I upload photos from URLs?
- Not through REST, which takes uploaded files. The MCP bulk import does fetch photos from URLs you host, which is usually the easier route when your images are already on a web server.
- Will my listings be published automatically?
- No. Everything created through the API starts as a draft and stays private until you call the status endpoint. That is deliberate: it gives you a chance to check an import before buyers see it.
- What happens if I run the same import twice?
- Through the MCP bulk import, rows carrying a stock number you have already used are reported as skipped rather than duplicated. Through REST, each request creates a listing, so your own script needs to track what it has already sent.