# BestPrice.gr API — Greek price-comparison data scraper: product search, category browsing, and every Greek shop's price for one product (lowest and highest price, shop name, availability) from bestprice.gr — no API key, no login

> Search BestPrice by keyword. Returns the product grid: title, the price BestPrice shows (the lowest across shops), how many shops carry it, and the product id you feed to `product`. A row is either a compared product (`listing_type: product`) or a single shop's listing with no product page (`shop_offer`: `offer_id` and `merchant_id`, `product_id` null). BestPrice answers many queries by redirecting to a category or brand page ("Oxford" goes to children's oxford shoes, "samsung" to the Samsung brand page); when it does, `redirected_to` names that page, because the rows are its grid and may not be what the query meant. Only the FIRST page of a grid is served to us: BestPrice redirects deeper pages back to page 1, so `page` above 1 returns no rows and `page_available: false` rather than the same rows again.
> ReefAPI engine `bestprice` · 4 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/bestprice/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/bestprice/v1/search — 2 credits
Search BestPrice by keyword. Returns the product grid: title, the price BestPrice shows (the lowest across shops), how many shops carry it, and the product id you feed to `product`. A row is either a compared product (`listing_type: product`) or a single shop's listing with no product page (`shop_offer`: `offer_id` and `merchant_id`, `product_id` null). BestPrice answers many queries by redirecting to a category or brand page ("Oxford" goes to children's oxford shoes, "samsung" to the Samsung brand page); when it does, `redirected_to` names that page, because the rows are its grid and may not be what the query meant. Only the FIRST page of a grid is served to us: BestPrice redirects deeper pages back to page 1, so `page` above 1 returns no rows and `page_available: false` rather than the same rows again.

**Parameters:**
- `query` (string, required) — What to search for, in Greek or English. A BARCODE does NOT work here — BestPrice's text index does not carry barcodes (measured: 0 rows for 12 of 12 EANs that BestPrice publishes on its own pages). Use the `barcode` action for an EAN/GTIN/UPC.
- `page` (integer, optional, default 1) — 1-based page of the grid (16 products a page, measured 2026-10-13). BestPrice currently serves only page 1 to us; a deeper page answers with no rows and page_available=false.
- `limit` (integer, optional, default 24) — Rows to return from the page (1-24). The source serves 24 a page; use `page` for more.

**Returns:** products[]{listing_type (product|shop_offer), product_id, offer_id, merchant_id, url, title, price_eur, currency, category_id, shop_count, image}, page, limit, query, redirected_to{type (category|brand), id, title, url} (only when BestPrice redirected), page_available (false when a deeper page was not served)

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

### POST https://api.reefapi.com/bestprice/v1/barcode — 1 credit
Find a product by its BARCODE (EAN-13, EAN-8, UPC-12 or GTIN-14) and get the BestPrice product id, so a catalogue can be matched on barcodes instead of names. Keyword `search` cannot do this: BestPrice's text index has no barcodes in it. Each row carries `match_type`: `barcode_exact` means BestPrice itself declared an exact barcode match (measured 25 of 25 correct, no false positive), `text_match` means it fell back to a fuzzy name match and MAY be a different product. By default only exact matches are returned. Coverage is partial and honest: 25 of 36 barcodes taken off BestPrice's own product pages resolved (3/3 in electronics, appliances, laptops, toys and tools; 1/3 in supermarket and beauty), so an empty answer means BestPrice's barcode index does not carry that code — not an error. Feed the returned `product_id` to `product` for every Greek shop's price.

**Parameters:**
- `barcode` (string, required) — The barcode: EAN-13 (8806091024749), EAN-8, UPC-12 or GTIN-14. Spaces and hyphens are ignored. A 13-digit code that misses is retried zero-padded to 14 automatically.
- `strict` (boolean, optional, default true) — true (default): return ONLY rows BestPrice declared an exact barcode match for. false: also return its fuzzy name matches, marked `match_type: text_match` — useful for review, but 2 of 6 measured fuzzy rows were a DIFFERENT product, so do not treat one as a barcode match.
- `limit` (integer, optional, default 8) — Rows to return (1-8). The source's own ceiling is 8; a barcode normally resolves to exactly one.

**Returns:** products[]{product_id, url, title, brand, model, variant, category_id, category_title, price_from_eur, currency, offer_count, availability, rating, rating_count, image, match_type (barcode_exact|text_match), match_confidence}, barcode, barcode_queried, strict, exact_match

**Example request body:**
```json
{
  "barcode": "8806091024749"
}
```

### POST https://api.reefapi.com/bestprice/v1/product — 3 credits
One product with EVERY shop offer: the shop name, its price, availability and the price band across the market (lowest, highest, how many shops). This is the whole point of a price-comparison source. It also returns the product's BARCODE (`gtin`, with `gtin_type` naming the key it came from) — published on 36 of 36 pages measured across 12 categories — so a catalogue can be matched on barcodes even for the codes BestPrice's `barcode` lookup does not carry.

**Parameters:**
- `product_id` (string, required) — The numeric product id, or a bestprice.gr product URL.

**Returns:** product{product_id, url, title, brand, gtin, gtin_type, mpn, sku, category_path, price_low_eur, price_high_eur, offer_count (what the market has), offers_listed (how many this response carries), rating, rating_count, offers[]{shop, price_eur, currency, url, availability, condition}}

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

### POST https://api.reefapi.com/bestprice/v1/category — 2 credits
Browse one category's grid without a keyword. Same rows as `search`. Take the category id from a search row's `category_id` or from a category URL.

**Parameters:**
- `category_id` (string, required) — Numeric category id (806), or a bestprice.gr category URL.
- `query` (string, optional) — Optional keyword to narrow the category.
- `page` (integer, optional, default 1) — 1-based page of the grid (16 products a page, measured 2026-10-13). BestPrice currently serves only page 1 to us; a deeper page answers with no rows and page_available=false.
- `limit` (integer, optional, default 24) — Rows to return from the page (1-24). The source serves 24 a page; use `page` for more.

**Returns:** products[] (same shape as search), page, limit, category_id

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

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