# Turners NZ — used vehicles, machinery and auction catalogues

> 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.
> ReefAPI engine `turners` · 4 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/turners/v1/<action>` with a JSON body.
- **Auth:** header `x-api-key: <YOUR_REEFAPI_KEY>` — create one free (1,000 credits, no card): https://reefapi.com/signup
- **Response (every call):** `{ ok: boolean, data: ..., meta: { record_count, credits, ... }, error: { code, message } }` — branch on `ok`. Failed calls are free except verified SHEIN NOT_FOUND on product/detail and price (4 credits).
- **One key + one shared credit pool** across every ReefAPI API. Per-call credits are listed on each endpoint below.
- **Use it from an AI agent (MCP):** connect `https://api.reefapi.com/mcp` (remote streamable-http). Send the key as `Authorization: Bearer <key>`, or put it in the URL (`?key=<key>`) when the client has no header field, as ChatGPT does.

## Endpoints

### POST https://api.reefapi.com/turners/v1/search — 3 credits
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.

**Parameters:**
- `division` (enum, optional, default "cars") — Which Turners marketplace to search. Live totals measured 2026-10-01: cars 2,719 · trucks 374 · damaged 554 · general-goods 1,521 · boats 14 · motorhomes 34. [one of: cars, trucks, damaged, general-goods, boats, motorhomes]
- `query` (string, optional) — Free-text search over the listing, exactly as the site's own search box takes it (`hilux` returned 45 cars). A Turners good number also resolves here, which is how `detail` turns an id into a listing.
- `make` (string, optional) — Manufacturer, as Turners spells it in its own URLs — lower-case, hyphenated: `toyota`, `holden`, `alfa-romeo`, `mercedes-benz`. Measured: `toyota` -> 495 of 2,719 cars.
- `model` (string, optional) — Model name, case-insensitive (`corolla` and `Corolla` both -> 46 cars with make=toyota). Use together with `make`: a model on its own is not how Turners indexes its stock.
- `year_from` (integer, optional) — Earliest model year, inclusive.
- `year_to` (integer, optional) — Latest model year, inclusive. Measured: 2020-2022 -> 819 of 2,715 cars.
- `price_from` (integer, optional) — Lowest asking price in NZD, inclusive.
- `price_to` (integer, optional) — Highest asking price in NZD, inclusive. Measured: 5,000-10,000 -> 422 of 2,715 cars.
- `odometer_from` (integer, optional) — Lowest odometer reading in kilometres.
- `odometer_to` (integer, optional) — Highest odometer reading in kilometres. Measured: 0-50,000 -> 282 of 2,715 cars.
- `fuel` (string, optional) — Fuel type, as the site prints it. Measured on the cars division: Petrol 1,495 · Diesel 540 · Hybrid 504 · Electric 89 (of 2,715). `Plugin Hybrid` also appears on listing cards. Not a closed list — other divisions may publish values we have not sampled, so anything you pass reaches the site; a value Turners does not know comes back as 0 rows with a note in `meta.warnings`.
- `body_type` (string, optional) — Body style, as the site prints it on the card. Measured: SUV 1,119 and Hatchback 754 of 2,715 cars. Sampled values across divisions include SUV, Hatchback, Sedan, Wagon, Van, Utility, Cab Chassis, Flat Deck, Tipper, Curtainsider, Tractor Unit, Excavator, Forklift and 34 more truck/machinery styles. Not a closed list; an unknown value returns 0 rows with a note in `meta.warnings`. (Turners' own `bodystyles` parameter is ignored upstream and is deliberately NOT offered here.)
- `transmission` (string, optional) — Measured on the cars division: Automatic 2,596 · Manual 119 (of 2,715 — the two add up to the whole catalogue).
- `drive_type` (string, optional) — Drive configuration as the site prints it: `2 Wheel Drive` or `4 Wheel Drive`. Measured: 4 Wheel Drive -> 900 of 2,715 cars.
- `seats` (integer, optional) — Seat count. Measured: 5 -> 2,205 of 2,715 cars.
- `branch` (string, optional) — Turners branch holding the vehicle, as the site prints it on the card — a BRANCH name, not a city or region (`locations=Auckland` returns nothing; `Hornby` returned 180). Sampled branches: Avalon Drive, Botany, Christchurch, Dunedin, Hornby, Manukau, Moorhouse Ave, Mount Maunganui, Napier, Nelson, New Plymouth, North Shore, Palmerston North, Penrose - Great South Road, Rotorua, Te Rapa Road, Timaru, Wairakei Rd, Wellington - Porirua, Westgate, Whangarei. Not a closed list; an unknown value returns 0 rows with a note in `meta.warnings`.
- `sale_method` (enum, optional) — How the vehicle is being sold. Measured on cars, 2026-10-01: auction 521, buy-now 2,201, which together are the whole catalogue of 2,719. [one of: auction, buy-now, tender, online-auction]
- `discounted_only` (boolean, optional, default false) — Only vehicles whose price Turners has cut (the card then prints its own `Was $...` figure). Measured: 956 of 2,715 cars.
- `ex_lease_only` (boolean, optional, default false) — Only ex-lease stock. Measured: 727 of 2,715 cars.
- `cga_only` (boolean, optional, default false) — Only vehicles sold with NZ Consumer Guarantees Act cover. Measured: 2,636 of 2,715 cars, i.e. it does bite but only excludes 79.
- `sort` (enum, optional, default "featured") — Result order. Because Turners publishes no paging on its URLs (see `max_results`), sorting is how you reach the other end of a big result set: `price_asc` and `price_desc` on the same query give you both ends. [one of: featured, auction_date, odometer_asc, odometer_desc, price_asc, price_desc, discount_desc, year_asc, year_desc, location, make_model, newest_listing]
- `max_results` (integer, optional, default 20) — Rows to return, 1-110. Turners' own page-size dropdown offers 20 and 110 and nothing else, so a value of 20 or below fetches the 20-row page and anything above fetches the 110-row page and trims. 🔴 110 IS A HARD CEILING PER QUERY: Turners does not page over its URLs (measured on nine parameter spellings and two path forms, all returning page one). `total_available` always reports the real size of the result set, so narrow by make, model, year or price band to go deeper.

**Returns:** {results[], total_available, returned, division, page_ceiling} — each result: listing_id, stock_id, url, title, make, model, year, variant, sale_method, price_nzd, was_price_nzd, savings_nzd, is_discounted, price_note, price_conflict, currency, odometer_km, branch, responsible_branch, body_type, transmission, drive_type, fuel_type, engine, seats, registration_status, category, image, image_count, and the sale-channel block: sale_channel, auction_date, auction_location, auction_closes_text, auction_starts_text, tender_start_date, tender_end_date, lot_number, current_bid_nzd, starting_bid_nzd, bid_status, reserve_low_nzd, reserve_high_nzd, reserve_range_text.

**Example request body:**
```json
{
  "division": "cars",
  "max_results": 20
}
```

### POST https://api.reefapi.com/turners/v1/detail — 3 credits
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.

**Parameters:**
- `listing_id` (string, optional) — Turners good number, the 8-digit id on every search row and at the end of every listing URL (e.g. 28450344). Resolved to its listing through Turners' own search, so it costs one extra upstream request; pass `url` instead when you already have it from a search row and want a single request.
- `url` (string, optional) — A full turners.co.nz listing URL, exactly as `search` returns it in `url`. Cheapest way to fetch a detail: one request, no id resolution.
- `division` (enum, optional, default "cars") — Which Turners marketplace to search. Live totals measured 2026-10-01: cars 2,719 · trucks 374 · damaged 554 · general-goods 1,521 · boats 14 · motorhomes 34. [one of: cars, trucks, damaged, general-goods, boats, motorhomes]

**Returns:** One listing object: identity, spec, odometer_history[], expiry dates, price_nzd + was_price_nzd + ld_json_price_nzd + price_conflict, auction{}, seller{} with branch address/geo/consultant, features[], description_lines[], images[], ratings{}.

**Example request body:**
```json
{
  "url": "https://www.turners.co.nz/Cars/Used-Cars-for-Sale/volkswagen/touareg/28450344"
}
```

### POST https://api.reefapi.com/turners/v1/auctions — 1 credit
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.

**Parameters:**
- `division` (enum, optional, default "cars") — Which auction diary to read. Turners publishes a separate schedule per division; the cars diary held 99 scheduled sales on 2026-10-01. [one of: cars, trucks, damaged, general-goods]
- `max_results` (integer, optional, default 20) — Rows to return, 1-110. Turners' own page-size dropdown offers 20 and 110 and nothing else, so a value of 20 or below fetches the 20-row page and anything above fetches the 110-row page and trims. 🔴 110 IS A HARD CEILING PER QUERY: Turners does not page over its URLs (measured on nine parameter spellings and two path forms, all returning page one). `total_available` always reports the real size of the result set, so narrow by make, model, year or price band to go deeper.

**Returns:** {results[], returned, total_available} — each result: auction_id, name, date_text, start_time_text, branch, lot_count, live_state, division, catalogue_url.

**Example request body:**
```json
{
  "division": "cars",
  "max_results": 20
}
```

### POST https://api.reefapi.com/turners/v1/auction_lots — 3 credits
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`.

**Parameters:**
- `auction_id` (string, required) — Auction identifier as `auctions` returns it: `<divisionIndex>-<auctionId>`, e.g. `1000-80076`. It is the last path segment of the catalogue URL.
- `max_results` (integer, optional, default 20) — Rows to return, 1-110. Turners' own page-size dropdown offers 20 and 110 and nothing else, so a value of 20 or below fetches the 20-row page and anything above fetches the 110-row page and trims. 🔴 110 IS A HARD CEILING PER QUERY: Turners does not page over its URLs (measured on nine parameter spellings and two path forms, all returning page one). `total_available` always reports the real size of the result set, so narrow by make, model, year or price band to go deeper.

**Returns:** {results[], total_available, returned, auction_id, auction_name} — rows as in `search`.

**Example request body:**
```json
{
  "auction_id": "1000-80076"
}
```

## At scale
- **Volume:** 5M+ requests a day, measured at 60 requests a second across the fleet with no
  central bottleneck. Per-key limits are raised for high-volume accounts; volume pricing on request.
- **Missing a source:** tell us a site we do not cover and it becomes an engine. A customer asked
  for bestprice.gr on 21 Sep 2026 and it was in the catalog on 22 Sep.
- **Support:** 2 minute median time from a question in the live chat to the first answer. Setup
  help included, no support tier to buy.
- **One key, one credit pool** across every API. No per-site plans, no separate subscriptions.

## More
- Try it live, no code: https://reefapi.com/playground?engine=turners
- Human docs page: https://reefapi.com/docs/turners
- Overview page: https://reefapi.com/turners-api
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
