Turners API & Scraper
The Turners API turns turners.co.nz, New Zealand's largest used-vehicle network, into clean JSON in four actions.
🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.
search covers six divisions in one call shape: cars (2,719 live listings on 2026-10-01), trucks and machinery (374), damaged and end-of-life vehicles (554), general goods (1,521), boats and marine (14) and buses, caravans and motorhomes (34) — 5,216 listings in total. Seventeen filters were each measured against the unfiltered total in the same run and every one of them narrows it: query, make, model, year band, price band, odometer band, fuel, body type, transmission, drive type, seats, branch, sale method, discounted-only, ex-lease-only and CGA-only. Every row carries the Turners good number, the canonical listing URL, the title, make, model and year, the odometer, the holding branch, the spec, and the money kept apart: price_nzd is what the vehicle sells for today and was_price_nzd is the pre-discount figure Turners struck out, never merged (958 of 2,720 cars were discounted). sale_method tells you which of Turners' four channels the listing is in: a fixed buy-now price (2,202 cars), an in-room auction lot (544 cars, carrying the sale's venue and date), an online auction lot (carrying whichever of current_bid_nzd or starting_bid_nzd Turners is printing, plus when it closes) or a tender lot (carrying its lot number and the tender window). detail returns one car or one truck in full: VIN, the complete odometer history Turners holds for the vehicle, WOF, COF and registration expiry, origin, colour, factory features, the CO2, fuel-economy and safety star ratings, every photo, the branch with its street address and coordinates, the named sales consultant with their work email and mobile, and for a machinery lot about thirty extra fields such as gross vehicle mass, wheel configuration, axle ratings and condition grades. auctions returns Turners' auction diary — 99 scheduled car sales on 2026-10-01, each with its date, start time, name, branch, lot count and catalogue id — and auction_lots returns every lot in one of those catalogues. In two consecutive live runs on 2026-10-01 all 52 cases passed in both, 52 of 52 and 52 of 52, with a median of 1.8 seconds and a worst case of 3.6. Prices are NZD. No Turners account, one ReefAPI key, and the standard { ok, data, meta, error } envelope.
Turners prints more than one number per listing, and the API keeps them apart
A Turners listing can show a selling price, a struck-out was-price, a running online bid, a starting bid nobody has matched yet, and a reserve range. They mean different things, so each has its own field and none is ever written into another.
| What Turners shows (2026-10-01) | Field | What it means |
|---|---|---|
| BUY NOW $10,490, "Was $10,990", "You Save $500" | price_nzd 10490 · was_price_nzd 10990 · savings_nzd 500 | price_nzd is what you pay for the car today; was_price_nzd is the pre-campaign figure and is the larger, louder number on the page. |
| A car in a Live Auction that also prints BUY NOW $19,440 | price_nzd 19440 · sale_method "auction" · auction_date · auction_location | 544 of 2,720 cars are auction lots and nearly all also carry a buy-now offer. The price is an offer to buy it now, not a bid. |
| An Online Auction lot printing "Starting Bid $900" | starting_bid_nzd 900 · current_bid_nzd null | Nobody has bid. 14 of 20 general-goods lots sampled were in this state; publishing 900 as a current bid would be a bid that does not exist. |
| An Online Auction lot printing "Current Bid $2,550 Reserve Met" | current_bid_nzd 2550 · bid_status "Reserve Met" | A real running bid, with Turners' own words about the reserve alongside it. |
| A damaged vehicle printing "Reserve Price Range $500 - $1,500" | reserve_low_nzd 500 · reserve_high_nzd 1500 | Read from the page's own low/high values, not from the dash-separated text. |
| A tender truck printing "Lot No 006", a start and an end date | sale_method "tender" · lot_number "006" · tender_start_date · tender_end_date | Trucks and machinery mostly sell by tender, which has a closing time rather than a live sale. |
Every card also carries a second price in the page's own analytics attribute. The API compares the two on every row, publishes price_conflict when they disagree, and counts the disagreements in meta. Across both live runs, about two thousand rows, there were zero. On detail the state figure and the page's own structured-data figure agreed on 7 of 7 priced listings, and search price matched detail price on 8 of 8 ids.
Real request and response JSON
Captured from the indexed primary action, search, on .
{
"method": "POST",
"url": "https://api.reefapi.com/turners/v1/search",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"division": "cars",
"max_results": 20
}
}{
"ok": true,
"meta": {
"api": "turners",
"endpoint": "search",
"mode": "live",
"latency_ms": 1596.8,
"record_count": 20,
"bytes": 424276,
"cache_hit": false,
"stop_reason": "limit_reached",
"total_available": 2734,
"page_ceiling": 110,
"price_witness_mismatch": 0,
"dropped_ad_tiles": 4,
"charged_credits": 1,
"version": "1.0.0",
"request_id": "c471ad0b508c41bd",
"queue_ms": 1.1
},
"data": {
"division": "cars",
"results": [
{
"listing_id": "28450344",
"stock_id": "54c9fea7-6ba9-f111-b3f2-005056a80e31",
"url": "https://www.turners.co.nz/Cars/Used-Cars-for-Sale/volkswagen/touareg/28450344",
"title": "2015 Volkswagen Touareg TDI 180KW BMT 4WD",
"division": "cars",
"sale_method": "buy-now",
"year": 2015,
"make": "Volkswagen",
"model": "Touareg",
"price_nzd": 10490,
"currency": "NZD",
"was_price_nzd": 10990,
"savings_nzd": 500,
"is_discounted": true,
"price_note": "*All ORC included",
"price_conflict": false,
"odometer_km": 244545,
"branch": "Avalon Drive",
"responsible_branch": "Hamilton Avalon Cars",
"category": "Cars",
"body_type": "SUV",
"transmission": "Automatic",
"drive_type": "4 Wheel Drive",
"fuel_type": "Diesel",
"engine": "2967 cc",
"registration_status": null,
"seats": 5,
"variant": "Volkswagen Touareg TDI 180KW BMT 4WD SUV Diesel 4 Wheel Drive",
"image": "https://tips-cloud.tgstatic.co.nz/photos/good/2015-volkswagen-touareg-28450344_24565386_gallery.jpg",
"image_count": 24,
"sale_channel": null,
"auction_location": null,
"auction_date": null,
"auction_closes_text": null,
"auction_starts_text": null,
"tender_start_date": null,
"tender_end_date": null,
"lot_number": null,
"lane": null,
"lot_lane_text": null,
"current_bid_nzd": null,
"starting_bid_nzd": null,
"bid_status": null,
"reserve_low_nzd": null,
"reserve_high_nzd": null,
"reserve_range_text": null
},
{
"listing_id": "28054725",
"stock_id": "8e1199ca-bf20-f111-b3e2-005056a80e31",
"url": "https://www.turners.co.nz/Cars/Used-Cars-for-Sale/mitsubishi/outlander/28054725",
"title": "2015 Mitsubishi Outlander 2WD",
"division": "cars",
"sale_method": "buy-now",
"year": 2015,
"make": "Mitsubishi",
"model": "Outlander",
"price_nzd": 15400,
"currency": "NZD",
"was_price_nzd": 18900,
"savings_nzd": 3500,
"is_discounted": true,
"price_note": "*All ORC included",
"price_conflict": false,
"odometer_km": 89519,
"branch": "Hornby",
"responsible_branch": "Hornby Cars",
"category": "Cars",
"body_type": "SUV",
"transmission": "Automatic",
"drive_type": "2 Wheel Drive",
"fuel_type": "Petrol",
"engine": "2000 cc",
"registration_status": null,
"seats": null,
"variant": "Mitsubishi Outlander 2WD SUV Petrol 2 Wheel Drive",
"image": "https://tips-cloud.tgstatic.co.nz/photos/good/2015-mitsubishi-outlander-28054725_24016661_gallery.jpg",
"image_count": 28,
"sale_channel": null,
"auction_location": null,
"auction_date": null,
"auction_closes_text": null,
"auction_starts_text": null,
"tender_start_date": null,
"tender_end_date": null,
"lot_number": null,
"lane": null,
"lot_lane_text": null,
"current_bid_nzd": null,
"starting_bid_nzd": null,
"bid_status": null,
"reserve_low_nzd": null,
"reserve_high_nzd": null,
"reserve_range_text": null
},
{
"listing_id": "28410497",
"stock_id": "1dfba9d5-609b-f111-b3f0-005056a80e31",
"url": "https://www.turners.co.nz/Cars/Used-Cars-for-Sale/toyota/alphard/28410497",
"title": "2012 Toyota Alphard Vellfire 2WD",
"division": "cars",
"sale_method": "buy-now",
"year": 2012,
"make": "Toyota",
"model": "Alphard",
"price_nzd": 10915,
"currency": "NZD",
"was_price_nzd": 11380,
"savings_nzd": 465,
"is_discounted": true,
"price_note": "*All ORC included",
"price_conflict": false,
"odometer_km": 164975,
"branch": "Westgate",
"responsible_branch": "Westgate Cars",
"category": "Cars",
"body_type": "SUV",
"transmission": "Automatic",
"drive_type": "2 Wheel Drive",
"fuel_type": "Petrol",
"engine": "2360 cc",
"registration_status": null,
"seats": 7,
"variant": "Toyota Alphard Vellfire 2WD SUV Petrol 2 Wheel Drive",
"image": "https://tips-cloud.tgstatic.co.nz/photos/good/2012-toyota-alphard-28410497_24395785_gallery.jpg",
"image_count": 23,
"sale_channel": null,
"auction_location": null,
"auction_date": null,
"auction_closes_text": null,
"auction_starts_text": null,
"tender_start_date": null,
"tender_end_date": null,
"lot_number": null,
"lane": null,
"lot_lane_text": null,
"current_bid_nzd": null,
"starting_bid_nzd": null,
"bid_status": null,
"reserve_low_nzd": null,
"reserve_high_nzd": null,
"reserve_range_text": null
}
],
"returned": 20,
"total_available": 2734,
"page_ceiling": 110
}
}What the Turners API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| search | Search Turners' live New Zealand stock across six divisions — cars, trucks & machinery, damaged/end-of-life vehicles, general goods, boats and motorhomes. Every row carries the id, the canonical listing URL, the asking price and the pre-discount price separately, the odometer, the holding branch and the spec. `sale_method` tells you whether the row is a fixed-price car or an auction lot, and auction rows carry the sale's date and venue. All filters are optional; `total_available` is the site's own count for your query, so you can see how much a filter actually narrowed it. 🔴 One query returns at most 110 rows — Turners publishes no paging on its URLs — so use `sort` and tighter filters to reach the rest. | Price-intelligence teams call search to search Turners' live New Zealand stock across six divisions. | division, query, make, model, year_from, ... |
| detail | One Turners listing in full, from the listing page's own data: VIN, the complete odometer HISTORY series Turners holds for the vehicle, WOF / COF / registration expiry dates, origin, factory features, the vehicle's CO2 / fuel-economy / safety star ratings, every photo, the branch with its street address and coordinates, the named consultant with their work email and mobile, and — when the vehicle is an auction lot — the catalogue, lot and lane number, sale date, estimate range and no-reserve flag. Pass `url` from a search row for a single request, or `listing_id` to have Turners resolve it first. One of the two is required: with neither you get MISSING_PARAM. 🔴 COVERAGE: cars and trucks & machinery. Turners still serves damaged vehicles, general goods, boats and motorhomes from an older listing page that publishes no detail payload, so `detail` answers MARKET_UNAVAILABLE for those four and says why; their `search` rows already carry the price or current bid, odometer, spec, branch and sale channel. | Classifieds aggregators call detail to get one Turners listing in full, from the listing page's own data. | listing_id, url, division |
| auctions | Turners' auction diary for one division: every scheduled sale with its date, start time, name, branch, lot count, live state and the catalogue id you pass to `auction_lots`. The cars diary held 99 scheduled sales on 2026-10-01. Dates and times are returned exactly as Turners prints them (`05 Oct`, `12:00pm`, NZ local time) — nothing here converts a timezone or guesses a year. | Resale and arbitrage tools call auctions to get turners' auction diary for one division. | division, max_results |
| auction_lots | The catalogue of one scheduled Turners auction: every lot in it, in the same shape `search` returns, including each lot's buy-now price where Turners also offers one. Take `auction_id` from `auctions`. On an in-room auction the lots carry the sale's venue and date rather than a running bid; on an online auction they carry whichever of `current_bid_nzd` or `starting_bid_nzd` Turners is printing, plus `auction_closes_text`. | Lead-generation teams call auction_lots to get the catalogue of one scheduled Turners auction. | auction_id, max_results |
Call search from your stack
curl -X POST https://api.reefapi.com/turners/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"division":"cars","max_results":20}'import requests
r = requests.post(
"https://api.reefapi.com/turners/v1/search",
headers={"x-api-key": REEF_KEY},
json={
"division": "cars",
"max_results": 20
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/turners/v1/search", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"division": "cars",
"max_results": 20
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.turners.search with {"division":"cars","max_results":20}.Who uses this API and why
- Price a trade-in or a retail car against New Zealand's largest single inventory: filter to the same make, model, year band and odometer band, read total_available for how thin or deep that segment is, then pull the cheapest and dearest 110 with sort price_asc and price_desc.
- Watch the auction diary: list the 99 scheduled car sales, open the catalogues that matter and track each lot's venue, date and — on online auctions — its running bid and closing time.
- Monitor discounting: discounted_only returned 958 of 2,720 cars, each with the struck-out price and Turners' own savings figure, so you can see what is being cut, by how much and at which branch.
- Source machinery and commercial vehicles: the trucks division returns gross vehicle mass, wheel configuration, axle ratings, body dimensions, engine and transmission makes, tyre sizes and condition grades, with the tender's lot number and closing time.
- Build a vehicle-history check: detail returns the VIN plus the full odometer history Turners holds, so a rollback or an implausible jump is visible without a paid report.
Questions developers ask before integrating
Which divisions does search cover, and how many listings are in each?
Six, all in one call shape via the division parameter. Measured 2026-10-01: cars 2,719 · trucks (trucks and machinery) 374 · damaged (damaged and end-of-life vehicles) 554 · general-goods 1,521 · boats 14 · motorhomes (buses, caravans and motorhomes) 34. That is 5,216 live listings. Turners' site menu also lists motorcycles, but it does not publish a search page for them, so there is no motorcycle division here rather than one that returns nothing.
How deep can one search go?
110 rows, and that is a hard ceiling we did not choose. Turners does not page over its URLs: we tried nine parameter spellings and two path forms and every one returned page one. So total_available always tells you the real size of your result set, and you reach the rest by narrowing (make, model, year band, price band) or by flipping sort — price_asc and price_desc on the same query give you both ends of it. page_ceiling is in every response so this is never a surprise.
Which price do I store?
price_nzd. It is what the vehicle sells for today. was_price_nzd is the struck-out pre-discount figure and savings_nzd is Turners' own "You Save" number; 958 of 2,720 cars were discounted on 2026-10-01, so a quarter of the catalogue has both. On auction-only divisions there is no fixed price at all and price_nzd is null (0 of 20 general goods, 0 of 14 boats and 0 of 20 damaged vehicles carried one).
Is there a current bid?
On online-auction lots, yes: current_bid_nzd when Turners is printing one, with bid_status carrying its own words such as "Reserve Met". When nobody has bid, Turners prints a starting bid instead, and that goes in starting_bid_nzd and never in current_bid_nzd. In-room auction lots do not show a running figure at all: they carry the sale's venue and date, and on damaged vehicles a reserve price range. Nowhere does Turners publish a bid count or a bid history, so neither is offered.
What does detail add over a search row?
On the cars and trucks divisions: the VIN, the complete odometer history Turners holds for the vehicle (13 readings over 11 years on the car we audited), WOF, COF and registration expiry dates, origin, colour, the factory feature list, the CO2 and fuel-economy and safety star ratings with Turners' own figures, every photo, the branch with its street address, postcode and coordinates, the named sales consultant with their work email and mobile, the page view and watchlist counts, and the condition-guide and MotorWeb report links. A machinery lot adds about thirty more fields under extra_specs — gross vehicle mass, wheel configuration, axle ratings, body dimensions, engine and transmission makes, tyre sizes and condition grades.
Does detail work for every division?
No, and it says so instead of returning half a page. Cars and trucks and machinery are covered. Turners still serves damaged vehicles, general goods, boats and motorhomes from an older listing page that publishes no record at all, so detail answers MARKET_UNAVAILABLE for those four and names them. Their search rows already carry the price or current bid, the odometer, the spec, the branch and the sale channel, which is most of what the detail page would add.
How do I get from a search row to a listing?
Pass the row's url to detail and it is one request. Pass listing_id (the eight-digit Turners good number) and Turners resolves it first, which costs one extra request. Both were checked on the same ids: 8 of 8 round-tripped to the same record. A good number that is sold or withdrawn returns NOT_FOUND rather than an empty success — Turners answers a dead listing with a 200 and a "Page Not Found" body, and that is translated.
Can I follow the auction calendar?
Yes. auctions returns Turners' diary for a division — 99 scheduled car sales and 10 truck sales on 2026-10-01 — each with its date, start time, name, branch, lot count, live state ("Not Yet Started") and the catalogue id. Feed that id to auction_lots and you get every lot in the sale in the same shape search returns, each with its lot number and the lane it runs in; when a catalogue has not been numbered yet Turners prints "To be confirmed" and that is what you get, rather than a silent blank. Dates and times come back exactly as Turners prints them in New Zealand local time; nothing here converts a timezone or guesses a year that is not on the page.
Which filter values does Turners accept?
division, sale_method, sort and max_results are closed lists and a wrong value is rejected with the allowed values. fuel, body_type, transmission, drive_type and branch take Turners' own display strings and are not frozen, because the measured vocabulary came from three divisions and Turners has more. The ones we measured are in each parameter's description. If Turners does not recognise a value it answers with an empty page rather than an error, so a zero-row result from one of those filters comes back as a successful empty answer with a note in meta.warnings telling you to check the spelling.
branch does not accept Auckland. Why?
Because Turners filters by branch, not by city or region. Auckland returned nothing; Hornby returned 180. The 21 branch names we measured are listed in the parameter description, among them Avalon Drive, Botany, Manukau, North Shore, Penrose - Great South Road, Moorhouse Ave, Te Rapa Road and Wellington - Porirua. Every row also carries its own branch, so you can group by it after the fact.
Who is the seller?
Always Turners. There are no private sellers on this source: every listing belongs to a Turners branch, and detail returns that branch in full — name, street address, locality, postcode, coordinates — plus the named sales consultant for the vehicle with the work email and mobile Turners prints on the page.
What does Turners not publish?
A bid count or bid history anywhere. A reserve amount on an in-room auction lot (only a range, and only on damaged vehicles). A plate or registration number — the registration expiry date is published, the plate is not. A fixed price on the auction-only divisions. And registration_expiry is genuinely missing on some vehicles: 4 of the 8 detail records we audited had it. Those fields come back null rather than filled with a guess.
What is the Turners API?
Turners API is a ReefAPI endpoint group for new zealand's largest used-vehicle network: cars, trucks and machinery, damaged vehicles, general goods, boats and motorhomes, plus the auction diary. It returns live JSON through POST requests under /turners/v1.
Is the Turners API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. Turners calls use the same shared credit balance as every other ReefAPI engine.