# billiger.de API — German price comparison: search, categories, every shop's price with shipping, product specs and grades, price history

> Keyword search on billiger.de (Germany, EUR). Rows are catalogue products (lowest price, number of prices compared, overall rating), product families (`row_type: baseproduct`, several variants) and single shop offers (`row_type: offer`, with shop, marketplace seller and shipping). Filter by brand, category, shop, price range and in-stock (ids come from `facets` of an earlier call). Some queries are turned into a category page by the site itself (`redirected_to`); a category page lists catalogue products only.
> ReefAPI engine `billiger` · 6 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/billiger/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/billiger/v1/search — 3 credits
Keyword search on billiger.de (Germany, EUR). Rows are catalogue products (lowest price, number of prices compared, overall rating), product families (`row_type: baseproduct`, several variants) and single shop offers (`row_type: offer`, with shop, marketplace seller and shipping). Filter by brand, category, shop, price range and in-stock (ids come from `facets` of an earlier call). Some queries are turned into a category page by the site itself (`redirected_to`); a category page lists catalogue products only.

**Parameters:**
- `query` (string, required) — Search words, e.g. `kaffeevollautomat delonghi`, `kopfhörer`, `lego technic`, or an EAN.
- `sort` (enum, optional, default "relevance") — Result order. [one of: relevance, popularity, price_asc, price_desc]
- `page` (integer, optional, default 1) — Result page. A page past the last returns no rows (`page_beyond_last: true`).
- `page_size` (integer, optional, default 48) — Rows per page: 48, 72 or 96 (the site's own choices).
- `brand_id` (string, optional) — Brand id from `facets.brand[].id` of an earlier call (2451932 = De'Longhi).
- `category_filter` (string, optional) — Category id from `facets.category[].id` (narrows a search to one category).
- `shop_id` (string, optional) — Shop id from `facets.shop[].id`: only items this shop sells.
- `price_min` (number, optional) — Lowest price in EUR (the source's own price index).
- `price_max` (number, optional) — Highest price in EUR.
- `in_stock_only` (boolean, optional, default false) — Only items marked immediately deliverable (sofort lieferbar).
- `row_types` (enum, optional, default "all") — Which rows: everything, only catalogue products, or only single shop offers. Each view has its own total (kopfhörer: all 61 635, products 6 767, offers 86 889). Not applied when the site turns the query into a category page (`redirected_to`), which lists products only. [one of: all, products, offers]

**Returns:** results[]{row_type (product|baseproduct|offer), product_id, baseproduct_id, offer_id (the id of its own type, others null), title, url, image, price, price_is_from, price_mismatch, currency, offer_count, overall_rating, rating_count, has_variants, energy_class, shop{id, name, marketplace} (offer rows), seller (offer rows), shipping_cost (offer rows)} + count + total (the source's own count for this view) + shop_count + page + page_size + has_more + page_beyond_last + facets{brand[], category[], shop[], availability[], paymentmethod[], price_range[]} + redirected_to + category_path[] + query + sort

**Example request body:**
```json
{
  "query": "kaffeevollautomat delonghi"
}
```

### POST https://api.reefapi.com/billiger/v1/category — 3 credits
One billiger.de category listing (e.g. 3551 = Kaffeevollautomaten): the same rows as `search`, with the same filters, sort and paging. A top-level category (e.g. 100165 Kaffeegeräte) is a landing page with no total.

**Parameters:**
- `category_id` (string, required) — Numeric billiger.de category id: from `category_path[].category_id` of `product`, from a facet, or from /show/kategorie/<id>.htm.
- `sort` (enum, optional, default "relevance") — Result order. [one of: relevance, popularity, price_asc, price_desc]
- `page` (integer, optional, default 1) — Result page. A page past the last returns no rows (`page_beyond_last: true`).
- `page_size` (integer, optional, default 48) — Rows per page: 48, 72 or 96 (the site's own choices).
- `brand_id` (string, optional) — Brand id from `facets.brand[].id` of an earlier call (2451932 = De'Longhi).
- `shop_id` (string, optional) — Shop id from `facets.shop[].id`: only items this shop sells.
- `price_min` (number, optional) — Lowest price in EUR (the source's own price index).
- `price_max` (number, optional) — Highest price in EUR.
- `in_stock_only` (boolean, optional, default false) — Only items marked immediately deliverable (sofort lieferbar).

**Returns:** results[]{same row shape as search} + count + total + page + page_size + has_more + page_beyond_last + facets + category{category_id, name, url} + category_path[] + sort

**Example request body:**
```json
{
  "category_id": "3551"
}
```

### POST https://api.reefapi.com/billiger/v1/product — 3 credits
One product (or product family) on billiger.de: title, brand, EAN, colour, category path, image, description, lowest and highest price and number of offers, the billiger.de overall grade (German school grade, 1 best) and its star equivalent, the user rating and the test-report rating with their counts, the popularity rank in its category, editorial pros and cons, the full spec sheet, every professional test report (publisher, grade, pros, cons) and, for a family, every variant with its own id, EAN and price range.

**Parameters:**
- `product_id` (string, optional) — billiger.de product id: `product_id` of a search / category row (row_type product), or the number in a product URL (/products/<id>-…). Give this OR `baseproduct_id`.
- `baseproduct_id` (string, optional) — billiger.de product-family id: `baseproduct_id` of a row with row_type baseproduct, or the number in /baseproducts/<id>-…. A family groups the variants (colour, storage); its offers and history span all of them. Give this OR `product_id`.

**Returns:** product{row_type, product_id, baseproduct_id, title, url, brand, gtin, color, variant_attributes, category, category_path[]{category_id, name}, image, description, price_min, price_max, price_now, offer_count, currency, overall_grade, overall_grade_label, overall_rating, user_rating, user_rating_count, test_report_rating, test_report_count, popularity_rank{rank, category}, pros[], cons[], key_specs[], specs[]{group, label, value}, test_reports[]{title, date, publisher, grade_display, grade_scale, grade, rating (5 stars), pros, cons}, variants[]{product_id, title, url, gtin, color, size, price_min, price_max, offer_count}, variant_count}

**Example request body:**
```json
{
  "product_id": "3443116743"
}
```

### POST https://api.reefapi.com/billiger/v1/offers — 3 credits
Every shop's offer for one product (or family) on billiger.de, one row per shop in billiger.de's order: shop (name, id, star rating and rating count, marketplace, Trusted Shops), marketplace seller, condition, price, price without voucher and the voucher code where the price needs one, crossed-out price, shipping cost, total price including shipping, delivery time, free-return days, and how many more offers the same shop has. Sort by price or by total price incl. shipping, only in-stock, new or used / refurbished.

**Parameters:**
- `product_id` (string, optional) — billiger.de product id: `product_id` of a search / category row (row_type product), or the number in a product URL (/products/<id>-…). Give this OR `baseproduct_id`.
- `baseproduct_id` (string, optional) — billiger.de product-family id: `baseproduct_id` of a row with row_type baseproduct, or the number in /baseproducts/<id>-…. A family groups the variants (colour, storage); its offers and history span all of them. Give this OR `product_id`.
- `sort` (enum, optional, default "price") — Offer order. [one of: price, total_price]
- `in_stock_only` (boolean, optional, default false) — Only offers marked immediately deliverable.
- `condition` (enum, optional, default "new") — New offers, or used / refurbished ones. [one of: new, used]
- `max_offers` (integer, optional, default 20) — How many shop rows to return; billiger.de serves 20 per request, more rows cost more requests.

**Returns:** product{product_id, baseproduct_id, title, url, price_min, price_max, offer_count} + offers[]{position, offer_id, product_id, title, condition (new|used|refurbished|b_stock), condition_text, price, price_without_voucher, voucher_code, voucher_terms, original_price, shipping_cost, total_price, total_price_source (printed|price_plus_shipping), total_mismatch, currency, delivery_time, free_return_days, badges[], info[], shop{id, name, url, rating, rating_count, marketplace, trusted_shops}, seller, more_offers_from_shop} + count + has_more + cheapest_price + cheapest_total_price + sort + condition

**Example request body:**
```json
{
  "product_id": "3443116743"
}
```

### POST https://api.reefapi.com/billiger/v1/offer — 2 credits
One single shop offer billiger.de lists without a product page (`row_type: offer` rows of search / category): title, shop, marketplace seller, price, shipping, total incl. shipping, delivery time, image, category path.

**Parameters:**
- `offer_id` (string, required) — `offer_id` of a search / category row with row_type offer, or the number in /offers/<id>.

**Returns:** offer{row_type=offer, offer_id, title, url, image, condition, price, price_without_voucher, voucher_code, original_price, shipping_cost, total_price, total_price_source, total_mismatch, currency, delivery_time, free_return_days, badges[], info[], shop{id, name, url, rating, rating_count, marketplace, trusted_shops}, seller, category_path[]}

**Example request body:**
```json
{
  "offer_id": "3046341211"
}
```

### POST https://api.reefapi.com/billiger/v1/price_history — 3 credits
billiger.de's own price history for one product: the lowest price on every day, the lowest / highest / median in the range, the site's own verdict on the current price per period (e.g. 'Aktuell hoher Preis' with its typical band), and with `time_range: all` the separate daily lines it draws for the big marketplaces (eBay, Kaufland, Otto, …). Single-day drops far below the band are kept as published and flagged `suspect_low`.

**Parameters:**
- `product_id` (string, optional) — billiger.de product id: `product_id` of a search / category row (row_type product), or the number in a product URL (/products/<id>-…). Give this OR `baseproduct_id`.
- `time_range` (enum, optional, default "6m") — How far back. 1m / 3m / 6m come with the product page; `all` is one more request and adds the per-marketplace lines. [one of: 1m, 3m, 6m, all]

**Returns:** product{product_id, baseproduct_id, title, url, price_now} + time_range + currency + points[]{date, price, suspect_low} + count + first_date + last_date + lowest_in_range{date, price} + lowest_in_range_excluding_suspect + highest_in_range + median_in_range + suspect_point_count + price_assessment[]{days, assessment, type, typical_low, typical_high, current_price} + shop_lines[]{shop, points[], count} (time_range all) + identity{page_product_id, layer_title_matches, last_point_equals_price_now}

**Example request body:**
```json
{
  "product_id": "3443116743",
  "time_range": "6m"
}
```

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