# Kieskeurig API — Dutch and Belgian price comparison: search, categories, every shop's price with shipping, specs, price history and reviews

> Keyword search on Kieskeurig (kieskeurig.nl or kieskeurig.be). Rows are catalogue products with the cheapest offer incl. shipping and the shop that has it (the two cheapest new offers), number of offers, EANs, review score and count, the site's price-drop badge and lowest-price-ever flag. Filter by category, brand, price, offer, review score and the site's own facets; sort by relevance, popularity or price.
> ReefAPI engine `kieskeurig` · 8 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/kieskeurig/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/kieskeurig/v1/search — 2 credits
Keyword search on Kieskeurig (kieskeurig.nl or kieskeurig.be). Rows are catalogue products with the cheapest offer incl. shipping and the shop that has it (the two cheapest new offers), number of offers, EANs, review score and count, the site's price-drop badge and lowest-price-ever flag. Filter by category, brand, price, offer, review score and the site's own facets; sort by relevance, popularity or price.

**Parameters:**
- `query` (string, required) — Search words, e.g. `iphone 15`, `wasmachine`, `robotstofzuiger`, or a model number.
- `category` (string, optional) — Narrow to one category slug (`categories` action, a row's `category_slug`, or a top level like `elektronica`).
- `country` (enum, optional, default "nl") — Which Kieskeurig: nl = kieskeurig.nl (Dutch shops), be = kieskeurig.be (Belgian shops). Product ids are shared; offers, prices and counts are per market. Prices in EUR. [one of: nl, be]
- `page` (integer, optional, default 1) — Result page. The source serves the first 10 000 rows of a listing (page × limit ≤ 10 000); `reachable_total` says how many that is.
- `limit` (integer, optional, default 24) — Rows per page (site default 24).
- `sort` (enum, optional, default "relevance") — Result order. [one of: relevance, popular, price_asc, price_desc]
- `brand` (string, optional) — Brand name (`Apple`, `JACK & JONES`) or several comma-separated; matched on the site's brand key (letters and digits).
- `min_price` (number, optional) — Lowest price in EUR, whole euros (the source refuses decimals and matches against the product's cheapest offer). A value below 1 is sent as 1.
- `max_price` (number, optional) — Highest price in EUR, whole euros (rounded up). The source filters on its own price index, which can lag the live cheapest offer: measured 2026-10-15, wasmachine 300-500 returned 2 of 24 rows at 529 and 259.
- `on_sale` (boolean, optional, default false) — Only products the site marks as on offer (aanbieding).
- `lowest_price_ever` (boolean, optional, default false) — Only products at their lowest price ever (laagste prijs ooit).
- `min_score` (number, optional) — Lowest user review score (1-10 scale).
- `facet` (string, optional) — Facet option id(s) from `facets[].options[].facet_id` of an earlier `facets` call (like `t23142:iOS`, `p0-100`), comma-separated for several.
- `range_filter` (string, optional) — One numeric trait range as `<trait_id>_<min>-<max>` (trait ids in `facets[].trait_id`; 23144 = storage GB on smartphones).

**Returns:** results[]{product_id, title, brand, url, slug, image, eans[], category_slug, category_path, taxonomy_slug, lowest_total_price, lowest_price, lowest_shipping_cost, lowest_effective_price, lowest_price_shop, lowest_price_shop_id, cheapest_offers[]{shop_id, shop_name, shop_type, total_price, discount_price, effective_price, price, shipping_cost, delivery_code, shop_certificates}, offer_count, currency, review_score, review_count, price_drop_pct, lowest_price_ever, spotlight_specs, promos} + count + total + reachable_total + total_capped + page + limit + has_more + applied{} + price_range_in_results + query + country

**Example request body:**
```json
{
  "query": "iphone 15",
  "country": "nl"
}
```

### POST https://api.reefapi.com/kieskeurig/v1/category — 2 credits
One Kieskeurig category listing (e.g. `smartphone`, `wasmachine`, `televisie`, or a top level such as `elektronica`): the same rows as `search`, sorted by popularity by default, with brand, price, offer, score, facet and numeric-trait filters and paging.

**Parameters:**
- `category` (string, required) — Category slug: from the `categories` action, a row's `category_slug`, the first path part of a category URL (kieskeurig.nl/<slug>), or a top level like `elektronica`. An unknown slug is refused (the source would silently list the whole catalogue).
- `country` (enum, optional, default "nl") — Which Kieskeurig: nl = kieskeurig.nl (Dutch shops), be = kieskeurig.be (Belgian shops). Product ids are shared; offers, prices and counts are per market. Prices in EUR. [one of: nl, be]
- `page` (integer, optional, default 1) — Result page. The source serves the first 10 000 rows of a listing (page × limit ≤ 10 000); `reachable_total` says how many that is.
- `limit` (integer, optional, default 24) — Rows per page (site default 24).
- `sort` (enum, optional, default "popular") — Result order. [one of: popular, relevance, price_asc, price_desc]
- `brand` (string, optional) — Brand name (`Apple`, `JACK & JONES`) or several comma-separated; matched on the site's brand key (letters and digits).
- `min_price` (number, optional) — Lowest price in EUR, whole euros (the source refuses decimals and matches against the product's cheapest offer). A value below 1 is sent as 1.
- `max_price` (number, optional) — Highest price in EUR, whole euros (rounded up). The source filters on its own price index, which can lag the live cheapest offer: measured 2026-10-15, wasmachine 300-500 returned 2 of 24 rows at 529 and 259.
- `on_sale` (boolean, optional, default false) — Only products the site marks as on offer (aanbieding).
- `lowest_price_ever` (boolean, optional, default false) — Only products at their lowest price ever (laagste prijs ooit).
- `min_score` (number, optional) — Lowest user review score (1-10 scale).
- `facet` (string, optional) — Facet option id(s) from `facets[].options[].facet_id` of an earlier `facets` call (like `t23142:iOS`, `p0-100`), comma-separated for several.
- `range_filter` (string, optional) — One numeric trait range as `<trait_id>_<min>-<max>` (trait ids in `facets[].trait_id`; 23144 = storage GB on smartphones).

**Returns:** results[]{product_id, title, brand, url, slug, image, eans[], category_slug, category_path, taxonomy_slug, lowest_total_price, lowest_price, lowest_shipping_cost, lowest_effective_price, lowest_price_shop, lowest_price_shop_id, cheapest_offers[]{shop_id, shop_name, shop_type, total_price, discount_price, effective_price, price, shipping_cost, delivery_code, shop_certificates}, offer_count, currency, review_score, review_count, price_drop_pct, lowest_price_ever, spotlight_specs, promos} + count + total + reachable_total + total_capped + page + limit + has_more + applied{} + price_range_in_results + category + country

**Example request body:**
```json
{
  "category": "wasmachine",
  "country": "nl"
}
```

### POST https://api.reefapi.com/kieskeurig/v1/facets — 1 credit
The filter lists Kieskeurig shows for a search or a category, with counts: categories, brands, on offer, lowest price ever, price bands and spec traits (string options with their `facet_id`, numeric traits with their `trait_id` and min / median / max). Takes the same filters as `search` / `category`, so counts follow the filters already applied. Give `query` or `category` (or both).

**Parameters:**
- `query` (string, optional) — Search words (give query or category).
- `category` (string, optional) — Category slug (give query or category).
- `country` (enum, optional, default "nl") — Which Kieskeurig: nl = kieskeurig.nl (Dutch shops), be = kieskeurig.be (Belgian shops). Product ids are shared; offers, prices and counts are per market. Prices in EUR. [one of: nl, be]
- `brand` (string, optional) — Brand name (`Apple`, `JACK & JONES`) or several comma-separated; matched on the site's brand key (letters and digits).
- `min_price` (number, optional) — Lowest price in EUR, whole euros (the source refuses decimals and matches against the product's cheapest offer). A value below 1 is sent as 1.
- `max_price` (number, optional) — Highest price in EUR, whole euros (rounded up). The source filters on its own price index, which can lag the live cheapest offer: measured 2026-10-15, wasmachine 300-500 returned 2 of 24 rows at 529 and 259.
- `on_sale` (boolean, optional, default false) — Only products the site marks as on offer (aanbieding).
- `lowest_price_ever` (boolean, optional, default false) — Only products at their lowest price ever (laagste prijs ooit).
- `min_score` (number, optional) — Lowest user review score (1-10 scale).
- `facet` (string, optional) — Facet option id(s) from `facets[].options[].facet_id` of an earlier `facets` call (like `t23142:iOS`, `p0-100`), comma-separated for several.
- `range_filter` (string, optional) — One numeric trait range as `<trait_id>_<min>-<max>` (trait ids in `facets[].trait_id`; 23144 = storage GB on smartphones).

**Returns:** facets[]{name, type, trait_id, unit, options[]{facet_id, name, count}, range{min, max, median}} + count + applied{} + query + category + country

**Example request body:**
```json
{
  "category": "smartphone",
  "country": "nl"
}
```

### POST https://api.reefapi.com/kieskeurig/v1/product — 3 credits
One Kieskeurig product with every shop's offer: title, brand, model type, EANs, product family, category, images, summary and description, the full spec sheet and filter traits, review score and count, the site's price-drop badge; plus the live offers (new and refurbished apart) and the lowest prices computed from them.

**Parameters:**
- `product_id` (string, required) — Kieskeurig product id: `product_id` of a search / category row, or the number at the start of the product URL slug (/<category>/product/<id>-…).
- `country` (enum, optional, default "nl") — Which Kieskeurig: nl = kieskeurig.nl (Dutch shops), be = kieskeurig.be (Belgian shops). Product ids are shared; offers, prices and counts are per market. Prices in EUR. [one of: nl, be]

**Returns:** product{product_id, title, type, brand, url, slug, eans[], state, category_slug, category_path, taxonomy_slug, taxonomy_name, family{family_id, name}, series_id, summary, description, images[], review_score, review_count, price_drop_pct, lowest_price_ever, spotlight_specs, traits[]{group, trait_id, name, value, unit}, specs[]{group, label, value}} + offers[] + refurbished_offers[] (same shape as the offers action) + summary{lowest_total_price, lowest_effective_price, lowest_price, highest_total_price, cheapest_shop, offer_count, lowest_total_price_refurbished, refurbished_offer_count, lowest_total_price_any_condition, currency} + country

**Example request body:**
```json
{
  "product_id": "50848486",
  "country": "nl"
}
```

### POST https://api.reefapi.com/kieskeurig/v1/offers — 1 credit
Every shop's offer for one product on Kieskeurig: shop (name, id, type, rating and count, official dealer and quality-mark flags), item price, shipping cost, total incl. shipping, a shop's temporary discount price where the site shows one, delivery promise, the shop's own text and the click-out link. New offers in the site's order (cheapest effective price first); refurbished offers apart.

**Parameters:**
- `product_id` (string, required) — Kieskeurig product id: `product_id` of a search / category row, or the number at the start of the product URL slug (/<category>/product/<id>-…).
- `country` (enum, optional, default "nl") — Which Kieskeurig: nl = kieskeurig.nl (Dutch shops), be = kieskeurig.be (Belgian shops). Product ids are shared; offers, prices and counts are per market. Prices in EUR. [one of: nl, be]
- `condition` (enum, optional, default "all") — Which offers. [one of: all, new, refurbished]

**Returns:** offers[]{position, offer_id, condition, total_price, price, shipping_cost, total_matches_price_plus_shipping, discount_price, effective_price, currency, ean, delivery_code, delivery_text, promotion, label, shop_text, offer_description, clickout_url, shop{shop_id, name, slug, type, rating, rating_count, review_count, official_dealer, kieskeurig_quality_mark, thuiswinkel_member, becommerce_member, logo}} + refurbished_offers[] + count + summary{…} + condition + country

**Example request body:**
```json
{
  "product_id": "50848486",
  "country": "nl"
}
```

### POST https://api.reefapi.com/kieskeurig/v1/price_history — 3 credits
Kieskeurig's own price history for one product: the lowest price on each day (about six months, one point a day), with lowest / highest / median in the range. The chart's daily lowest spans every offer and can hold single days far below the band; those are kept as published and flagged `suspect_low`. Each point carries the EAN it belongs to and is checked against the product's own EANs.

**Parameters:**
- `product_id` (string, required) — Kieskeurig product id: `product_id` of a search / category row, or the number at the start of the product URL slug (/<category>/product/<id>-…).
- `country` (enum, optional, default "nl") — Which Kieskeurig: nl = kieskeurig.nl (Dutch shops), be = kieskeurig.be (Belgian shops). Product ids are shared; offers, prices and counts are per market. Prices in EUR. [one of: nl, be]

**Returns:** product_id + title + points[]{date, lowest_price, ean, suspect_low} + count + first_date + last_date + lowest_in_range{date, lowest_price} + lowest_in_range_excluding_suspect + highest_in_range + median_in_range + suspect_point_count + chart_eans + identity{requested_product_id, page_product_id, product_eans, all_points_match} + current_lowest_total_price + lowest_price_ever + currency + country

**Example request body:**
```json
{
  "product_id": "50848486",
  "country": "nl"
}
```

### POST https://api.reefapi.com/kieskeurig/v1/reviews — 3 credits
User reviews of one product on Kieskeurig, 25 per page: score (1-10), title, text, date, whether the reviewer bought it, language, likes, criteria ratings, pros and cons, and which product variant the review was written for.

**Parameters:**
- `product_id` (string, required) — Kieskeurig product id: `product_id` of a search / category row, or the number at the start of the product URL slug (/<category>/product/<id>-…).
- `country` (enum, optional, default "nl") — Which Kieskeurig: nl = kieskeurig.nl (Dutch shops), be = kieskeurig.be (Belgian shops). Product ids are shared; offers, prices and counts are per market. Prices in EUR. [one of: nl, be]
- `page` (integer, optional, default 1) — Review page, 25 reviews each.

**Returns:** reviews[]{review_id, score, score_max, title, text, date, acquired, acquired_label, author, language, likes, recommend, official, ratings[], pros[], cons[], reaction_count, reviewed_product_id, other_variant, family_id} + count + total + page + total_pages + has_more + review_score + product_id

**Example request body:**
```json
{
  "product_id": "50848486",
  "country": "nl"
}
```

### POST https://api.reefapi.com/kieskeurig/v1/categories — 2 credits
Kieskeurig's category list (slug + name, about 1 270 entries) for the `category` parameter. Top-level groups such as `elektronica` work too but are not in this list.

**Parameters:**
- `country` (enum, optional, default "nl") — Which Kieskeurig: nl = kieskeurig.nl (Dutch shops), be = kieskeurig.be (Belgian shops). Product ids are shared; offers, prices and counts are per market. Prices in EUR. [one of: nl, be]
- `query` (string, optional) — Keep only categories whose name or slug contains this text.

**Returns:** categories[]{slug, name} + count + total + country

**Example request body:**
```json
{
  "query": "wasmachine"
}
```

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