# Maschinensucher / Machineseeker API — live used-industrial-machinery marketplace data from Europe's largest second-hand machine marketplace (maschinensucher.de, machineseeker.com): 200,000 listings from 8,100+ dealers across metalworking and machine tools, construction plant, forklifts, woodworking, agricultural, food-processing, packaging, printing, plastics and recycling machinery. Search and filter on the fields a pricing or sourcing desk actually needs — machine type, manufacturer, model, year of construction, operating hours, price band, seller country and region — then pull one listing in full: price with its VAT treatment and incoterm, condition, every technical property the seller typed, delivery and payment terms, auction buyer's premium, the seller's town, country and trust seal, and the full description. Plus the category tree, live facet counts, autocomplete and the dealer directory. No login, no API key.

> Search or browse the marketplace. Combine a keyword with any of the typed filters the source supports natively — category, manufacturer, machine type, condition, price band, year of construction, operating hours, seller country and region, rental-only, price-published-only — and sort by price, year, listing date or update. Returns up to 25 rows a page with the price (and its VAT and incoterm wording), year, operating hours, condition, seller country and every property the result card prints. 🔴 Depth is capped by the source at 8 pages = 200 rows per query, so narrow rather than page; the filters are measured to bite hard (1,157 rows → 123 by manufacturer, → 269 by a 6-year window, → 178 by an operating-hour band).
> ReefAPI engine `maschinensucher` · 7 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/maschinensucher/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/maschinensucher/v1/search — 3 credits
Search or browse the marketplace. Combine a keyword with any of the typed filters the source supports natively — category, manufacturer, machine type, condition, price band, year of construction, operating hours, seller country and region, rental-only, price-published-only — and sort by price, year, listing date or update. Returns up to 25 rows a page with the price (and its VAT and incoterm wording), year, operating hours, condition, seller country and every property the result card prints. 🔴 Depth is capped by the source at 8 pages = 200 rows per query, so narrow rather than page; the filters are measured to bite hard (1,157 rows → 123 by manufacturer, → 269 by a 6-year window, → 178 by an operating-hour band).

**Parameters:**
- `market` (enum, optional, default "de") — Which Machineseeker host to read. 🔴 This picks the LANGUAGE of the labels, not a different catalogue: the listings are one shared pool and the price is the same number in the same currency on every host (measured: listing 22811490 is EUR 49,900 on all six, machineseeker.co.uk included — the site does not convert currency). Use 'de' for German wording and 'com' for English wording. The wider Machineseeker network has 50+ further hosts; only these six have their label vocabulary measured and mapped here, so the others answer MARKET_UNAVAILABLE rather than returning fields this engine cannot name. [one of: de, at, ch, com, gb, ie]
- `query` (string, optional) — Free-text keyword, exactly as typed into the site's own search box: a machine type ('bagger', 'drehmaschine', 'excavator'), a manufacturer, a model, or several words. Either `query` or `category_id` is the normal starting point; calling with neither walks the whole catalogue, and `meta.total` will say so. 🔴 A MULTI-WORD QUERY WIDENS, IT DOES NOT NARROW: the source splits on spaces and hyphens and matches any token, so adding words adds results. Measured on one run: 'machine' 64,678 · 'anywhere' 142 · 'zzz' 4 · and 'zzz-no-such-machine-anywhere-xyz' 67,890, roughly their union. A single unmatched word is an honest empty answer ('xyzzyplughfoo' → total 0, zero rows). To narrow, use `category_id`, `machine_type`, `manufacturer` or `description_contains` rather than a longer phrase.
- `category_id` (integer, optional) — Browse one category instead of searching, using the site's own numeric category id (105 = excavators, 43 = lathes, 42 = forklifts, 13 = packaging machines, 2 = metalworking & machine tools). Works for leaf categories too, not only the 40-odd top ones. Get the ids from the `categories` action or from any `ci-<id>` URL. Can be combined with `query` and every filter.
- `manufacturer` (string, optional) — Manufacturer, spelled exactly as the source's own facet spells it ('Caterpillar', 'Liebherr', 'Komatsu', 'Wacker Neuson', 'DOOSAN' — the case is the source's). Pass a comma-separated list or a JSON array for several. Read the available spellings out of `facets.manufacturers` on an unfiltered call. Measured to bite: query=bagger 1,157 rows → 123 for Caterpillar.
- `machine_type` (string, optional) — The machine-type name in that market's language, as printed on the first line of every result ('Kettenbagger', 'Abbruchbagger', 'CNC-Drehmaschine'). This is a narrower filter than `query` because it matches the typed field rather than the whole listing. Measured to bite: 1,157 → 158 for 'Kettenbagger'. The `suggest` action returns valid values for a prefix.
- `condition` (enum, optional) — Condition class. Pass a comma-separated list for several. 🔴 An unknown value is NOT an error on this source — it is silently dropped and you get the unfiltered catalogue with a '0 matches' headline, so this engine validates the value instead of forwarding it. Measured to bite: 1,157 → 895 used, 256 new. [one of: used, new, ex-display machine, defective]
- `year_min` (integer, optional) — Earliest year of construction, inclusive. Plain year — this engine converts it to the unix timestamp the site's own select carries, which is why the filter actually bites here: sending the bare year to the site answers HTTP 200 with a '0 matches' headline and 25 rows that have no year at all. Measured: year_min=2024 → 219 of 1,157 and every row on page 1 is 2024-2026.
- `year_max` (integer, optional) — Latest year of construction, inclusive (measured: year_max=2000 returns rows up to and including 2000). Same timestamp conversion as `year_min`.
- `operating_hours_min` (integer, optional) — Lowest operating-hour reading to include, in hours. This is the field a used-plant buyer prices on, and the source filters on it natively. Measured to bite: query=bagger 1,157 → 178 for 0-2,000 h and every returned reading was under 2,000 h.
- `operating_hours_max` (integer, optional) — Highest operating-hour reading to include, in hours. Measured to bite: 1,157 → 119 for 10,000-99,999 h. Listings that publish no reading are excluded by the source when either bound is set.
- `price_min` (number, optional) — Lowest price to include, in EUR (every price on this marketplace is EUR, on every host). Measured to bite: 1,157 → 430 for 10,000-50,000.
- `price_max` (number, optional) — Highest price to include, in EUR. Combine with `price_min` for a band; the source excludes the price-on-request listings from a price-filtered result, so pair this with `with_price_only=false` only when you want them back in an unfiltered call.
- `with_price_only` (boolean, optional, default false) — Only listings that publish a price. Worth knowing why it exists: 122 of 313 cards in a 12-category sweep carry no price at all but a 'price on request' button, and those come back with price=null and price_on_request=true. Measured to bite: 1,157 → 855.
- `country` (string, optional) — Seller country as an ISO-3166 alpha-2 code, UPPER CASE ('DE', 'NL', 'ES', 'TR', 'AT', 'PL', 'BE', 'FR', 'IT', 'CH', 'GB'). Comma-separated for several. 🔴 The source is case-sensitive and silently drops 'de' — this engine upper-cases it for you and rejects anything that is not two letters. Measured to bite: 1,157 → 646 for DE, 117 for NL. `facets.countries` lists the codes that actually have stock for your query.
- `region` (string, optional) — Sub-national region, spelled with the source's own NAME, not a code: 'Bayern', 'Nordrhein-Westfalen', 'Baden-Württemberg'. 🔴 Sending 'BY' is silently dropped by the source. Requires `country` (the source nests regions under a country), and `facets.regions` lists the valid names with counts for your query.
- `rental_only` (boolean, optional, default false) — Only machines offered for rent rather than for sale. Measured to bite: query=bagger 1,157 → 38.
- `description_contains` (string, optional) — Extra keyword matched against the listing's free-text description only, on top of `query`. This is how you find equipment detail the typed fields do not carry ('hydraulik', 'klimaanlage', 'CE'). Measured to bite: 1,157 → 64.
- `listing_id` (string, optional) — Look one listing up by its id through the search surface (the `detail` action is the fuller answer). 🔴 The result page then reports '(1)' and still renders 25 cards — 24 of them unrelated filler under a 'further results' heading. This engine cuts them, so you get exactly the one row.
- `reference_number` (string, optional) — The seller's or auction's own reference number, as printed in a listing's offer details. Measured: 'AUC-2609172' returns exactly its one listing.
- `sort` (enum, optional, default "relevance") — Result order; each value maps to the source's own sort field, so the order is the site's and is not re-sorted here. 🔴 The site also offers a distance sort; it is deliberately NOT exposed, because it sorts by distance from the exit IP the request happened to leave through, which would make two identical calls return different orders. [one of: relevance, price_asc, price_desc, newest, oldest, year_desc, year_asc, updated_desc, updated_asc, manufacturer_asc, manufacturer_desc]
- `page` (integer, optional, default 1) — 1-based page number, 25 rows a page. 🔴 Only 8 pages = 200 rows are retrievable per query however large `total` is: page 9 answers HTTP 404 for a 1,157-row query and for a 31,884-row one alike (it does not silently repeat the last page). To go deeper, narrow — category, manufacturer, year, country, price and operating hours all bite. `meta.pagination` publishes last_page, retrievable_max and has_more.
- `include_facets` (boolean, optional, default false) — Also return the source's own live facet counts for this query (categories, manufacturers, countries, regions, conditions, radius bands), which is how you find the exact spelling a filter wants and how much stock each value has. The source publishes its top 15 per group.
- `include_description` (boolean, optional, default true) — Include each row's description preview. It is the seller's own prose and often carries equipment detail the typed fields do not. One machine-generated decoy line is injected by the source on every render and is removed here; the count removed is reported per row as description_decoy_lines_removed.

**Returns:** listings[]: listing_id, url, listing_type (classified | auction | auction_external), machine_type, manufacturer, model, year, condition, functionality, operating_hours, operating_hours_unit, price, currency, price_display, price_on_request, price_previous, discount_pct, price_terms, price_type (fixed | negotiable), vat (excluded | included | not_applicable), incoterm, location_city, location_country, location_country_code, image, image_count, seller_has_trust_seal, specs[] (every property the card prints, with the source's own label plus a parsed number and unit) and description_preview. Note on country: `location_country_code` is always present (it comes from the flag the card always renders), while `location_country` is the source's own localized country NAME and is empty on the rows where the source leaves its own title attribute blank — measured 29 of 150 rows. Filter and group on the code. meta carries total, total_is_rounded, pagination (page, page_size, last_page, retrievable_max, has_more), filters_applied, facets and any warnings.

**Example request body:**
```json
{
  "query": "bagger",
  "market": "de",
  "page": 1
}
```

### POST https://api.reefapi.com/maschinensucher/v1/detail — 3 credits
One listing in full, by id. Returns the machine (type, manufacturer, model, year, condition, functionality, operating hours), the price with its previous price, VAT treatment and incoterm, every technical property the seller typed — grouped the way the source groups them, each with a parsed number and unit — the boolean equipment badges, the delivery block (availability, delivery terms, dismantling, pickup and shipping costs), the payment block (an auction's buyer's premium, payment terms and methods), the offer block (listing code, reference number, last update), the seller's town, country, member-since year, listings online and trust seal, the geo coordinates the page's own map uses, the category breadcrumb and every gallery image. The price is cross-checked against the page's own schema.org product data and any disagreement is reported, not hidden.

**Parameters:**
- `listing_id` (string, required) — The listing id, as returned in `listing_id` on every search row, as the last path segment of a listing URL (…/sany-sy265c/i-22811490) or as the 'Inserat-ID / Listing ID' the page prints with an A in front (A22811490). All three forms and a full URL are accepted. A dead id answers NOT_FOUND, never an empty success.
- `market` (enum, optional, default "de") — Which Machineseeker host to read. 🔴 This picks the LANGUAGE of the labels, not a different catalogue: the listings are one shared pool and the price is the same number in the same currency on every host (measured: listing 22811490 is EUR 49,900 on all six, machineseeker.co.uk included — the site does not convert currency). Use 'de' for German wording and 'com' for English wording. The wider Machineseeker network has 50+ further hosts; only these six have their label vocabulary measured and mapped here, so the others answer MARKET_UNAVAILABLE rather than returning fields this engine cannot name. [one of: de, at, ch, com, gb, ie]

**Returns:** listing{} with machine, price, specs[], spec_groups{}, features[], delivery{}, payment{}, offer{}, seller{}, location{}, category{}, images[], description and price_witness{} (the schema.org price beside the printed one, with agreed=true/false).

**Example request body:**
```json
{
  "listing_id": "22811490",
  "market": "de"
}
```

### POST https://api.reefapi.com/maschinensucher/v1/categories — 1 credit
The marketplace's own category tree with live per-category listing counts: the 45 top-level sectors (metalworking & machine tools, woodworking, construction plant, forklifts, food technology, packaging, agricultural…) with the numeric ids every other action's `category_id` takes. Pass a `category_id` to drill into that sector's sub-categories, which is how you get from 7,593 construction machines to the 803 excavators or the 2,049 access platforms. Every count is the source's own live figure, not an estimate.

**Parameters:**
- `market` (enum, optional, default "de") — Which Machineseeker host to read. 🔴 This picks the LANGUAGE of the labels, not a different catalogue: the listings are one shared pool and the price is the same number in the same currency on every host (measured: listing 22811490 is EUR 49,900 on all six, machineseeker.co.uk included — the site does not convert currency). Use 'de' for German wording and 'com' for English wording. The wider Machineseeker network has 50+ further hosts; only these six have their label vocabulary measured and mapped here, so the others answer MARKET_UNAVAILABLE rather than returning fields this engine cannot name. [one of: de, at, ch, com, gb, ie]
- `category_id` (integer, optional) — Browse one category instead of searching, using the site's own numeric category id (105 = excavators, 43 = lathes, 42 = forklifts, 13 = packaging machines, 2 = metalworking & machine tools). Works for leaf categories too, not only the 40-odd top ones. Get the ids from the `categories` action or from any `ci-<id>` URL. Can be combined with `query` and every filter.

**Returns:** categories[]: category_id, name, url, count, parent_id. meta.level says whether these are the top sectors or one sector's children, and meta.listings_total is their counts added up.

**Example request body:**
```json
{
  "market": "de"
}
```

### POST https://api.reefapi.com/maschinensucher/v1/facets — 2 credits
The source's own live filter counts for a query: which categories, manufacturers, countries, regions and conditions have stock and how much, plus the distance bands. This is how you learn the exact spelling a filter wants (the source is case-sensitive and wants region NAMES, not codes) and how to narrow a query that is deeper than the 200-row retrievable ceiling. The source publishes its top 15 per group.

**Parameters:**
- `market` (enum, optional, default "de") — Which Machineseeker host to read. 🔴 This picks the LANGUAGE of the labels, not a different catalogue: the listings are one shared pool and the price is the same number in the same currency on every host (measured: listing 22811490 is EUR 49,900 on all six, machineseeker.co.uk included — the site does not convert currency). Use 'de' for German wording and 'com' for English wording. The wider Machineseeker network has 50+ further hosts; only these six have their label vocabulary measured and mapped here, so the others answer MARKET_UNAVAILABLE rather than returning fields this engine cannot name. [one of: de, at, ch, com, gb, ie]
- `query` (string, optional) — Free-text keyword, exactly as typed into the site's own search box: a machine type ('bagger', 'drehmaschine', 'excavator'), a manufacturer, a model, or several words. Either `query` or `category_id` is the normal starting point; calling with neither walks the whole catalogue, and `meta.total` will say so. 🔴 A MULTI-WORD QUERY WIDENS, IT DOES NOT NARROW: the source splits on spaces and hyphens and matches any token, so adding words adds results. Measured on one run: 'machine' 64,678 · 'anywhere' 142 · 'zzz' 4 · and 'zzz-no-such-machine-anywhere-xyz' 67,890, roughly their union. A single unmatched word is an honest empty answer ('xyzzyplughfoo' → total 0, zero rows). To narrow, use `category_id`, `machine_type`, `manufacturer` or `description_contains` rather than a longer phrase.
- `category_id` (integer, optional) — Browse one category instead of searching, using the site's own numeric category id (105 = excavators, 43 = lathes, 42 = forklifts, 13 = packaging machines, 2 = metalworking & machine tools). Works for leaf categories too, not only the 40-odd top ones. Get the ids from the `categories` action or from any `ci-<id>` URL. Can be combined with `query` and every filter.
- `manufacturer` (string, optional) — Manufacturer, spelled exactly as the source's own facet spells it ('Caterpillar', 'Liebherr', 'Komatsu', 'Wacker Neuson', 'DOOSAN' — the case is the source's). Pass a comma-separated list or a JSON array for several. Read the available spellings out of `facets.manufacturers` on an unfiltered call. Measured to bite: query=bagger 1,157 rows → 123 for Caterpillar.
- `machine_type` (string, optional) — The machine-type name in that market's language, as printed on the first line of every result ('Kettenbagger', 'Abbruchbagger', 'CNC-Drehmaschine'). This is a narrower filter than `query` because it matches the typed field rather than the whole listing. Measured to bite: 1,157 → 158 for 'Kettenbagger'. The `suggest` action returns valid values for a prefix.
- `condition` (enum, optional) — Condition class. Pass a comma-separated list for several. 🔴 An unknown value is NOT an error on this source — it is silently dropped and you get the unfiltered catalogue with a '0 matches' headline, so this engine validates the value instead of forwarding it. Measured to bite: 1,157 → 895 used, 256 new. [one of: used, new, ex-display machine, defective]
- `year_min` (integer, optional) — Earliest year of construction, inclusive. Plain year — this engine converts it to the unix timestamp the site's own select carries, which is why the filter actually bites here: sending the bare year to the site answers HTTP 200 with a '0 matches' headline and 25 rows that have no year at all. Measured: year_min=2024 → 219 of 1,157 and every row on page 1 is 2024-2026.
- `year_max` (integer, optional) — Latest year of construction, inclusive (measured: year_max=2000 returns rows up to and including 2000). Same timestamp conversion as `year_min`.
- `operating_hours_min` (integer, optional) — Lowest operating-hour reading to include, in hours. This is the field a used-plant buyer prices on, and the source filters on it natively. Measured to bite: query=bagger 1,157 → 178 for 0-2,000 h and every returned reading was under 2,000 h.
- `operating_hours_max` (integer, optional) — Highest operating-hour reading to include, in hours. Measured to bite: 1,157 → 119 for 10,000-99,999 h. Listings that publish no reading are excluded by the source when either bound is set.
- `price_min` (number, optional) — Lowest price to include, in EUR (every price on this marketplace is EUR, on every host). Measured to bite: 1,157 → 430 for 10,000-50,000.
- `price_max` (number, optional) — Highest price to include, in EUR. Combine with `price_min` for a band; the source excludes the price-on-request listings from a price-filtered result, so pair this with `with_price_only=false` only when you want them back in an unfiltered call.
- `with_price_only` (boolean, optional, default false) — Only listings that publish a price. Worth knowing why it exists: 122 of 313 cards in a 12-category sweep carry no price at all but a 'price on request' button, and those come back with price=null and price_on_request=true. Measured to bite: 1,157 → 855.
- `country` (string, optional) — Seller country as an ISO-3166 alpha-2 code, UPPER CASE ('DE', 'NL', 'ES', 'TR', 'AT', 'PL', 'BE', 'FR', 'IT', 'CH', 'GB'). Comma-separated for several. 🔴 The source is case-sensitive and silently drops 'de' — this engine upper-cases it for you and rejects anything that is not two letters. Measured to bite: 1,157 → 646 for DE, 117 for NL. `facets.countries` lists the codes that actually have stock for your query.
- `region` (string, optional) — Sub-national region, spelled with the source's own NAME, not a code: 'Bayern', 'Nordrhein-Westfalen', 'Baden-Württemberg'. 🔴 Sending 'BY' is silently dropped by the source. Requires `country` (the source nests regions under a country), and `facets.regions` lists the valid names with counts for your query.
- `rental_only` (boolean, optional, default false) — Only machines offered for rent rather than for sale. Measured to bite: query=bagger 1,157 → 38.
- `description_contains` (string, optional) — Extra keyword matched against the listing's free-text description only, on top of `query`. This is how you find equipment detail the typed fields do not carry ('hydraulik', 'klimaanlage', 'CE'). Measured to bite: 1,157 → 64.
- `sort` (enum, optional, default "relevance") — Result order; each value maps to the source's own sort field, so the order is the site's and is not re-sorted here. 🔴 The site also offers a distance sort; it is deliberately NOT exposed, because it sorts by distance from the exit IP the request happened to leave through, which would make two identical calls return different orders. [one of: relevance, price_asc, price_desc, newest, oldest, year_desc, year_asc, updated_desc, updated_asc, manufacturer_asc, manufacturer_desc]

**Returns:** facets{categories[], manufacturers[], countries[], regions[], conditions[]} each value with its label and count, plus radius_bands[] and meta.total.

**Example request body:**
```json
{
  "query": "bagger",
  "market": "de"
}
```

### POST https://api.reefapi.com/maschinensucher/v1/suggest — 1 credit
The site's own autocomplete for a typed prefix, in four buckets: machine types, manufacturers, categories (with their numeric ids) and products. Use it to turn whatever a user typed into values the `machine_type`, `manufacturer` and `category_id` filters accept, instead of guessing a spelling the source would silently drop.

**Parameters:**
- `query` (string, required) — At least two characters of what a user is typing. The source answers with its own vocabulary in four buckets, which is exactly what the other actions' filters want: machine types (feed to `machine_type`), manufacturers (feed to `manufacturer`), categories (feed the id to `category_id`) and products.
- `market` (enum, optional, default "de") — Which Machineseeker host to read. 🔴 This picks the LANGUAGE of the labels, not a different catalogue: the listings are one shared pool and the price is the same number in the same currency on every host (measured: listing 22811490 is EUR 49,900 on all six, machineseeker.co.uk included — the site does not convert currency). Use 'de' for German wording and 'com' for English wording. The wider Machineseeker network has 50+ further hosts; only these six have their label vocabulary measured and mapped here, so the others answer MARKET_UNAVAILABLE rather than returning fields this engine cannot name. [one of: de, at, ch, com, gb, ie]
- `category_id` (integer, optional) — Browse one category instead of searching, using the site's own numeric category id (105 = excavators, 43 = lathes, 42 = forklifts, 13 = packaging machines, 2 = metalworking & machine tools). Works for leaf categories too, not only the 40-odd top ones. Get the ids from the `categories` action or from any `ci-<id>` URL. Can be combined with `query` and every filter.

**Returns:** suggestions{machine_types[], manufacturers[], categories[] (with category_id), products[]} each with name and url.

**Example request body:**
```json
{
  "query": "kettenbag",
  "market": "de"
}
```

### POST https://api.reefapi.com/maschinensucher/v1/dealers — 2 credits
The dealer directory for one category: the machinery dealers themselves, 100 a page, each with company name, street, postcode, town, country and region, plus the dealer id the `seller` action takes. This is the supplier-side view of the marketplace — the site's own figure is over 8,100 dealers.

**Parameters:**
- `category_id` (integer, required) — The category whose dealers to list, using the site's own numeric category id (105 = excavators, 43 = lathes, 2 = metalworking & machine tools). The site's dealer directory is organised per category and has no 'all dealers' page, so this is required.
- `market` (enum, optional, default "de") — Which Machineseeker host to read. 🔴 This picks the LANGUAGE of the labels, not a different catalogue: the listings are one shared pool and the price is the same number in the same currency on every host (measured: listing 22811490 is EUR 49,900 on all six, machineseeker.co.uk included — the site does not convert currency). Use 'de' for German wording and 'com' for English wording. The wider Machineseeker network has 50+ further hosts; only these six have their label vocabulary measured and mapped here, so the others answer MARKET_UNAVAILABLE rather than returning fields this engine cannot name. [one of: de, at, ch, com, gb, ie]
- `page` (integer, optional, default 1) — 1-based page number, 100 dealers a page. Past the last page the source answers HTTP 404 and this engine reports NOT_FOUND rather than an empty success.
- `sort` (enum, optional, default "name") — Order of the directory. 🔴 The site's OWN default is distance from the visitor, which for an API means distance from whichever exit the request happened to leave through — two identical calls would return different dealers on page 1 and paging would never be complete. This engine therefore defaults to the company name and does not expose the distance order at all. [one of: name, country, postcode]

**Returns:** dealers[]: dealer_id, name, url, street, postcode_city (the source's own line), postcode, city, country, region.

**Example request body:**
```json
{
  "category_id": 105,
  "market": "de",
  "page": 1
}
```

### POST https://api.reefapi.com/maschinensucher/v1/seller — 2 credits
One dealer's public profile by id: company name, contact address (street, postcode, town, region, country), their own description of the business, the machine categories and manufacturer ranges they deal in, and the site's trust seal. 🔴 The listing list on a dealer's page is login-walled placeholder markup — every card there carries the dealer's own name as its title and no price — so it is deliberately not returned; use `search` for real listings.

**Parameters:**
- `dealer_id` (string, required) — The dealer's numeric id, as returned by the `dealers` action and as the first path segment of a dealer URL (…/Haendler/10186640/schlueter-baumaschinen-gmbh-erwitte). A full dealer URL is also accepted.
- `market` (enum, optional, default "de") — Which Machineseeker host to read. 🔴 This picks the LANGUAGE of the labels, not a different catalogue: the listings are one shared pool and the price is the same number in the same currency on every host (measured: listing 22811490 is EUR 49,900 on all six, machineseeker.co.uk included — the site does not convert currency). Use 'de' for German wording and 'com' for English wording. The wider Machineseeker network has 50+ further hosts; only these six have their label vocabulary measured and mapped here, so the others answer MARKET_UNAVAILABLE rather than returning fields this engine cannot name. [one of: de, at, ch, com, gb, ie]

**Returns:** seller{dealer_id, name, url, street, postcode, city, region, country, about, categories[], related_searches[] (the manufacturer-and-model phrases the site itself cross-links from this dealer's page — the source does not claim these are brands the dealer is authorised for), trust_seal}.

**Example request body:**
```json
{
  "dealer_id": "10186640",
  "market": "de"
}
```

## 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=maschinensucher
- Human docs page: https://reefapi.com/docs/maschinensucher
- Overview page: https://reefapi.com/maschinensucher-api
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
