Whoppah API & Scraper
Whoppah is a Netherlands-based marketplace for second-hand design and vintage pieces - furniture, lighting, art, decoration, tableware and designer bags - and this API reads it as JSON with no account and no key.
🤖 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.
On 2026-10-14 it held 222,006 listings: 185,846 for sale and 36,108 already sold, and the sold ones keep their final sale price, which makes Whoppah one of the few resale sources where you can read what a piece actually went for. Sellers are in 25 countries, led by the Netherlands (100,217 listings), France (34,036), Belgium (26,418), Germany (19,913) and Italy (9,169). The furniture attributes come back as filterable values with the source's own counts rather than as words in a title: 52 styles and periods (vintage 68,779, mid-century modern 26,542, Scandinavian 7,666, space age 3,682, art deco 3,617, brutalist 1,460), 51 materials, 20 colours, brands (Leolux 2,209, Vitra 1,429, Artifort 1,148, Cassina 886), designers (Paulin 175, Eames 169, Breuer 119) and artists (Andy Warhol 338). `search` combines all of that with category, the item's country, condition, the three-step wear grade, delivery method, free-shipping destination, showroom models, bidding, price, width, height and depth in centimetres, lot size, minimum discount and seller, and `status: sold` turns it into a sold-comparables search. `detail` returns one listing in full - the description in your language and in the seller's own words, every price the source keeps, weight in kilogrammes, the brand, designer, colour, material and style records, the item's city, the seller, and the courier price the listing publishes for each destination country. `shipping` returns the live delivery quote for a destination you name, `similar` the listings Whoppah itself shows as related, `seller` a seller's public profile with their listings or sold history, and `facets` every filter value with its live count for any scope.
What a Whoppah field actually contains
Fields that read differently from how they look, and the limits worth knowing before you build on them. Every row was measured against live Whoppah responses on 2026-10-14, including the ones that go against us.
| Field | What it holds |
|---|---|
| price_eur | The buy-now price today, in euros. Whoppah has one price list for all six storefront languages - 25 sofas read in all six languages in the same minute had identical ids, prices, previous prices, minimum bids and dimensions, and the same total (11,416). It is null on a sold listing, never the stale asking price: a sold dining set's record still says 800 while it sold for 700, so the 800 comes back as last_asking_price_eur in detail and the 700 as sold_price_eur. |
| previous_price_eur and discount_pct | previous_price_eur is the seller's earlier price, and it is not always higher - one set of chairs went from 600 to 750 - so it is not called a list or was price. discount_pct is Whoppah's own figure where it shows one (14 of 40 sofas, 0 of 40 vases sampled). |
| min_bid_eur | The lowest bid the seller accepts, only while the listing accepts bids. Two details measured: search rows round it UP to a whole euro (86 where the listing's record says 85.50), and a listing that has switched bidding off can still carry an old minimum in its record (180 on a 257 listing) - that one is returned as null, because it is not an offer you can make. |
| sold and sold_price_eur | 36,108 listings are sold and stay searchable with the price they sold for. status: sold in search returns only those, status: available only what can still be bought; by default you get both and every row says which. |
| dimensions_cm and weight_kg | Width, height and depth in centimetres and weight in kilogrammes - the units are Whoppah's own, confirmed by its product pages' structured data (CMT, '3 kg'). They are what the seller typed, and some sellers type a placeholder: 1,784 listings give a width of 1 cm or less (90 of them sofas) and 3,889 a height of 1 cm or less, while 142 claim a width of 10 m or more. Those rows keep the value and carry a dimension_warnings flag, so nobody sorts a sofa by a 1 cm width. |
| listed_courier_prices (detail) and the shipping action | Two different shipping figures, both from Whoppah. The listing publishes a courier price per destination country; the checkout gives a live quote for an address. For one lamp in the same minute they agreed for the Netherlands (95), Belgium (117) and Austria (255) and disagreed for Germany (grid 278, quote 182) and France (309 vs 277). detail returns the grid, shipping returns the quote with the grid price next to it and grid_matches_quote. Neither depends on where the call comes from: the same listings read from twelve different network locations, in the Netherlands, Germany, the UK, the US, France and elsewhere, were identical every time. |
| total and total_is_exact | Exact with the default match: keyword - for 'eames' the total said 1,010 and paging through returned exactly 1,010 different listings. match: hybrid is the website's own default and adds meaning-based matches, but its total is an estimate (it said 1,011 and paged out 1,181 rows, 21 of them repeats), so those responses say total_is_exact: false. match: semantic stops at 500. Browsing without a query is exact to the last row: 222,006 listings, last page partial, then empty. |
| filter_mismatch | Whoppah filters on its search index, and a listing edited minutes ago can still be matched on its old values while the row shows the new ones - one 495 listing came back under a 500 minimum because its price had been cut two hours earlier. It is rare (about 1 row in 100 on the pages where it happened) and the row is kept, with filter_mismatch naming the filter it now contradicts. |
| category, brand, designer, artist, style, material, color | Slugs, the same in every language ('mid-century-modern', 'vitra', 'eames', 'dining-chairs'). The facets action lists them with live counts. An unknown value is refused by name rather than answered with an empty result, because Whoppah itself answers a typo with zero rows. |
| seller | As Whoppah publishes it: display_name (a business's shop name, or a private seller's chosen name), kind private or business, the expert-seller badge, rating, review count, live listings and completed sales, member since and the countries they sell from. Search rows carry only seller_id; the name comes from detail or seller. No address, phone or e-mail is published. |
| location | The item's city and country, as the product page shows it. The country filter is the item's country, not a delivery destination - use free_shipping_to or the shipping action for that. |
| not returned | Search rows carry no seller name, city, category or brand name (only the ids). No bid history, no buyer identity, no review texts. Facet lists stop at the top 100 values. Nothing behind a login: favourites, messages, offers and checkout are out of scope. |
Prices are EUR throughout. Measured on 2026-10-14: two identical live runs of 41 cases each, 41 of 41 passing both times, plus the recon probes behind each row above.
Real request and response JSON
Captured from the indexed primary action, search, on .
{
"method": "POST",
"url": "https://api.reefapi.com/whoppah/v1/search",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"query": "eames",
"language": "en",
"page_size": 24
}
}{
"ok": true,
"meta": {
"api": "whoppah",
"endpoint": "search",
"mode": "live",
"latency_ms": 596.4,
"record_count": 24,
"bytes": 90636,
"cache_hit": false,
"upstream_requests": 1,
"total_is_exact": true,
"language": "en",
"charged_credits": 2,
"version": "1.0.0",
"request_id": "b61c056d4ec4431e",
"queue_ms": 1.1,
"fetched_at": "2026-10-14T18:57:32.625Z"
},
"data": {
"total": 1011,
"total_is_exact": true,
"page": 1,
"page_size": 24,
"pages": 43,
"has_more": true,
"language": "en",
"match": "keyword",
"sort": "relevance",
"status": "all",
"query": "eames",
"filters": {},
"listings": [
{
"id": "e118076f-e59b-42a3-a3de-bc6b48fe4973",
"identifier": "Q_k02nyvJ",
"slug": "vitra-eames-lounge-chair-6",
"url": "https://www.whoppah.com/products/vitra-eames-lounge-chair-6",
"title": "Vitra Eames Lounge chair",
"description": "Offered:\n\nVitra Eames lounge chair + ottoman in American Cherry in white leather. New chair.\nPeriod 1970s. Several available.\n\nProducer: Vitra\nDesigner: Charles & Ray Eames\nMaterial: leather\nColour: cherry wood - white leather",
"currency": "EUR",
"price_eur": 8500,
"previous_price_eur": 8250,
"discount_pct": null,
"min_bid_eur": null,
"sold": false,
"sold_price_eur": null,
"on_hold_until": null,
"condition": "used",
"quality": "perfect",
"quality_label": "Excellent",
"number_of_items": 2,
"dimensions_cm": {
"width": 85,
"height": 86,
"depth": 89
},
"dimension_warnings": [],
"shape": null,
"gender": null,
"is_art": null,
"is_curated": true,
"is_boosted": false,
"is_showroom_model": false,
"brand_id": "ebfe9cb6-cc85-4240-bdda-5a9618f13b75",
"seller_id": "5025e72b-9d9a-496f-99de-1052f55d549b",
"image": "https://images.whoppah.com/image/ba6b8f2c-55b1-4933-81ae-2993541cd05b/original.jpeg",
"images": [
{
"url": "[trimmed-depth]",
"width": "[trimmed-depth]",
"height": "[trimmed-depth]"
},
{
"url": "[trimmed-depth]",
"width": "[trimmed-depth]",
"height": "[trimmed-depth]"
},
{
"url": "[trimmed-depth]",
"width": "[trimmed-depth]",
"height": "[trimmed-depth]"
}
],
"created_at": "2023-05-26T13:10:28.762Z",
"updated_at": "2026-10-12T19:10:02.860Z"
},
{
"id": "14101ad7-f5bf-4fd9-9e04-05dd3f9dbe70",
"identifier": "XGT95HQ3PHY2",
"slug": "eames-dining-table-contract-table-herman-miller-vitra-765cm",
"url": "https://www.whoppah.com/products/eames-dining-table-contract-table-herman-miller-vitra-765cm",
"title": "Eames dining table contract table Herman Miller Vitra 76.5cm",
"description": "Original dining table by Charles and Ray Eames for Vitra. Design: Charles & Ray Eames Manufacturer: Vitra Herman Miller Design era: 1970 Style: Design classic Condition: Overall very good used condition. Very few signs of use present. Photos serve as additional description. For further questions, please feel free to contact or arrange a viewing appointment. Material: Metal, wood Dimensions: Diameter: 76.5cm Height: 73cm Item location: 37170 Volpriehausen Industriestraße 3.\n\nAdditional details:\n- Style: Design classic\n- Period: 1970s",
"currency": "EUR",
"price_eur": 420,
"previous_price_eur": null,
"discount_pct": null,
"min_bid_eur": 378,
"sold": false,
"sold_price_eur": null,
"on_hold_until": null,
"condition": "used",
"quality": "great",
"quality_label": "Very good",
"number_of_items": null,
"dimensions_cm": {
"width": 76,
"height": 73,
"depth": 76
},
"dimension_warnings": [],
"shape": null,
"gender": null,
"is_art": false,
"is_curated": false,
"is_boosted": false,
"is_showroom_model": false,
"brand_id": "d6e8d900-6406-4f3b-86d7-1f785dbc2199",
"seller_id": "d95bf748-c9bd-408b-82d9-b3d6f51d280c",
"image": "https://images.whoppah.com/image/ee528281-43f0-420c-b3c4-ed2b390c1512/original.jpg",
"images": [
{
"url": "[trimmed-depth]",
"width": "[trimmed-depth]",
"height": "[trimmed-depth]"
},
{
"url": "[trimmed-depth]",
"width": "[trimmed-depth]",
"height": "[trimmed-depth]"
},
{
"url": "[trimmed-depth]",
"width": "[trimmed-depth]",
"height": "[trimmed-depth]"
}
],
"created_at": "2026-10-11T21:41:24.082Z",
"updated_at": "2026-10-11T21:42:02.015Z"
},
{
"id": "3a3c2178-526d-4595-b4e1-db6818e10beb",
"identifier": "0D3OZX7MIXFR",
"slug": "herman-miller-eames-lobby-chair-es-104-leather-premium-f-chocolate",
"url": "https://www.whoppah.com/products/herman-miller-eames-lobby-chair-es-104-leather-premium-f-chocolate",
"title": "Herman Miller Eames Lobby Chair ES 104 - Leather Premium F Chocolate",
"description": "The Eames ES104 Executive Chair, better known as the Time-Life Lobby Chair, is the ultimate symbol of corporate luxury and mid-century prestige. Originally designed in 1960 by Charles and Ray Eames for the lobbies of the Time-Life Building in New York, this 1980s edition radiates authority and timeless comfort. It is defined by its three plush, hand-tufted leather cushions and its iconic polished aluminum frame.\n\nStyle: Vintage\nBrand: Herman Miller\nDesigner: Charles & Ray Eames\nPeriod: 1980s\nMaterial: Brown leather upholstery and aluminum frame\nHeight: 86 – 92 cm (adjustable)\nWidth: 73 cm\nDept",
"currency": "EUR",
"price_eur": 5850,
"previous_price_eur": 6500,
"discount_pct": 10,
"min_bid_eur": 4500,
"sold": false,
"sold_price_eur": null,
"on_hold_until": null,
"condition": "used",
"quality": "good",
"quality_label": "Good",
"number_of_items": 1,
"dimensions_cm": {
"width": 73,
"height": 92,
"depth": 71
},
"dimension_warnings": [],
"shape": null,
"gender": null,
"is_art": null,
"is_curated": true,
"is_boosted": false,
"is_showroom_model": false,
"brand_id": "9752f31c-4fa4-4f88-8c53-31777bfd9424",
"seller_id": "5025e72b-9d9a-496f-99de-1052f55d549b",
"image": "https://images.whoppah.com/image/fbc1425b-5f68-480b-bb40-0e8a2a8f6760/original.jpg",
"images": [
{
"url": "[trimmed-depth]",
"width": "[trimmed-depth]",
"height": "[trimmed-depth]"
},
{
"url": "[trimmed-depth]",
"width": "[trimmed-depth]",
"height": "[trimmed-depth]"
},
{
"url": "[trimmed-depth]",
"width": "[trimmed-depth]",
"height": "[trimmed-depth]"
}
],
"created_at": "2026-03-10T10:41:07.820Z",
"updated_at": "2026-10-10T21:15:00.786Z"
}
]
}
}What the Whoppah API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| search | Search whoppah's 222,006 second-hand design and vintage listings — furniture, lighting, art, decoration, tableware and designer bags, from sellers in 25 countries — with the source's own filters: free text, category, brand, designer, artist, style/period, material, colour, shape, the item's country, condition, wear grade, delivery method, free-shipping destination, showroom models, bidding, trade discount, price, width / height / depth in cm, lot size, minimum discount and seller. `status=sold` turns it into a sold-comparables search: 36,108 sold listings with their final sale price. Every row carries its own price in EUR, previous price, discount, minimum bid, wear grade, dimensions, photos and the seller's id. | Pricing teams call search to search whoppah's 222,006 second-hand design and vintage listings. | query, language, match, category, brand, ... |
| detail | One listing in full from whoppah's own API: title and description in the requested language AND the seller's original wording, wear notes, status (for sale / sold, with the final sale price), every price the source keeps (buy-now, previous, new retail, minimum bid, bid count), condition and wear grade, width / height / depth / seat height in cm and weight in kg, lot size, category path, brand / designer / artist / colour / material / style records, the item's city and country, delivery options with the listing's own courier price per destination country, every photo, view and favourite counts, and the seller (name, business name, private or business, rating, reviews, listings and sales counts, member since). | Marketplace operators call detail to get one listing in full from whoppah's own API. | id, language, include_pii |
| shipping | The live delivery quote whoppah's checkout gives for one listing to a destination YOU name — country, and optionally postcode, city and street for the address-priced courier — with each option's price, provider, delivery-day window and whether it is supported. The listing's own per-country courier grid is returned beside the quote with `grid_matches_quote`, because the two disagree for some destinations (measured: DE grid 278 vs quote 182, FR 309 vs 277; NL, BE, AT equal). The quote depends only on the address you pass, never on where the call comes from. | Catalog enrichment teams call shipping to get the live delivery quote whoppah's checkout gives for one listing to a destination YOU name. | id, country, postal_code, city, street, ... |
| similar | The listings whoppah itself shows as related to a given one (same maker, category or style), each with price, previous price, minimum bid, wear grade, sold flag and photo — the 'what else like this is on the market, and at what price' view. | Retail analysts call similar to get the listings whoppah itself shows as related to a given one (same maker, category or style),…. | id, limit, language, include_pii |
| seller | A seller's public profile — display name, business name, private or business, expert-seller badge, rating, review count, live listings and completed sales counts, member since, countries — plus a page of that seller's listings with the same row shape as search (`status` lets you ask for their sold history). | Pricing teams call seller to get a seller's public profile. | id, include_listings, status, sort, page, ... |
| facets | The source's own filter values with its own live counts, for any scope you can search — the whole catalogue, a free-text query, or any combination of the search filters: categories, brands, designers, artists, styles, materials, colours, seller countries, conditions, wear grades, delivery methods, free-shipping destinations, and the price / width / height / depth ranges. This is where the slugs the search filters take come from. The source lists at most the top 100 values of a facet. | Marketplace operators call facets to get the source's own filter values with its own live counts, for any scope you can search. | query, language, match, category, brand, ... |
Call search from your stack
curl -X POST https://api.reefapi.com/whoppah/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"query":"eames","language":"en","page_size":24}'import requests
r = requests.post(
"https://api.reefapi.com/whoppah/v1/search",
headers={"x-api-key": REEF_KEY},
json={
"query": "eames",
"language": "en",
"page_size": 24
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/whoppah/v1/search", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"query": "eames",
"language": "en",
"page_size": 24
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.whoppah.search with {"query":"eames","language":"en","page_size":24}.Who uses this API and why
- Price a design piece from real sales: search status: sold for the same brand or designer and category, and read the final sale prices next to the live asking prices of the pieces still for sale.
- Source stock with real constraints: a sideboard under 180 cm wide, in teak, mid-century modern, under 1,500 EUR, located in the Netherlands or Belgium, with courier delivery, newest first.
- Quote landed cost for a cross-border buyer: the shipping action for a German or French address next to the listing's own courier price, with delivery-day windows.
- Watch a dealer: a business seller's profile with rating, review count, live listings and completed sales, plus their newest listings or their sold history.
- Build a vintage catalogue with real attributes: brand, designer, style, material, colour and centimetre dimensions as separate values, in six languages, with dimension placeholders flagged instead of passed off as measurements.
Questions developers ask before integrating
Do I need a Whoppah account or key?
No. Everything this API reads is Whoppah's public marketplace: search, listings, sold listings, delivery quotes, related listings and public seller profiles. Nothing behind a login is touched.
Can I get the price a piece actually sold for?
Yes. Whoppah keeps sold listings searchable with their final sale price - 36,108 of them on 2026-10-14. Pass status: sold to search only those, with any of the usual filters, for example every sold Eames piece or every sold Thonet dining chair. On a sold row price_eur is null and sold_price_eur carries what it went for.
Are prices different on the Dutch, German or French storefront?
No. One price list in euros behind all six storefront languages: 25 sofas read in en, nl, de, fr, es and it in the same minute had identical prices, dimensions and totals. The language parameter changes titles, descriptions and category names, not prices or counts.
Does the shipping cost depend on where I call from?
No. The same listings were read from twelve different network locations - in the Netherlands, Germany, the UK, the US, France and elsewhere - and every price, every courier grid and every delivery quote was byte-identical. The destination is a parameter you pass to the shipping action - a country, and optionally a postcode, city and street for the address-priced courier.
Why does the shipping action sometimes disagree with the listing's courier price?
Because Whoppah publishes two figures and they do not always match: the per-country price on the listing and the live quote its checkout gives. For one lamp they matched for the Netherlands, Belgium and Austria and differed for Germany (278 vs 182) and France (309 vs 277). The shipping action returns both with grid_matches_quote, so you can choose.
Is the total count reliable?
With the default keyword matching, yes, to the row. The website's own hybrid matching gives an estimate and can repeat a listing on the next page; you can still ask for it with match: hybrid, and the response says total_is_exact: false when you do.
What happens if I pass a brand or category Whoppah does not have?
You get a clear INVALID_PARAM naming the value. Whoppah itself answers an unknown value with zero results, which would look like an empty market, so this API checks the value first: closed lists are checked locally, and brand, designer, artist, category, style, material and colour against Whoppah's own answer.
Which countries do the items come from?
25. The Netherlands 100,217 listings, France 34,036, Belgium 26,418, Germany 19,913, Italy 9,169, Czechia 7,441, Spain 6,717, Poland 6,291, the UK 3,138, Hungary 2,350, Denmark 1,700 and 14 smaller ones. The country parameter filters on where the item is.
What is the Whoppah API?
Whoppah API is a ReefAPI endpoint group for the dutch-born design and vintage resale market: 222,006 listings of furniture, lighting, art and designer bags from sellers in 25 countries, including 36,108 sold pieces with their final sale price. It returns live JSON through POST requests under /whoppah/v1.
Is the Whoppah API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. Whoppah calls use the same shared credit balance as every other ReefAPI engine.
Do I need a Whoppah login or account?
No login to Whoppah is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the Whoppah data?
The page example is captured from a live search call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the Whoppah API use?
Whoppah actions currently cost 1-3 credits per successful call. Failed or blocked calls are free. All APIs draw from one credit pool.
Can I call Whoppah from an AI assistant or MCP client?
Yes. Connect ReefAPI once through MCP and your assistant can call whoppah actions with the same key, credit pool and JSON envelope used by normal REST requests.