# REWE API — German supermarket prices per market: shelf price, offers, base price (Grundpreis), Pfand, GTIN, nutrition and ingredients for REWE Lieferservice and Abholservice

> Search REWE's online shop AS ONE MARKET SELLS IT: price, regular price and discount, offer end date, base price per kg/l, Pfand, pack size, GTIN, brand, tags, category, sponsored flag. `query` is required; filters: category, attribute, brand; sort; paging.
> ReefAPI engine `rewe` · 6 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/rewe/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/rewe/v1/search — 2 credits
Search REWE's online shop AS ONE MARKET SELLS IT: price, regular price and discount, offer end date, base price per kg/l, Pfand, pack size, GTIN, brand, tags, category, sponsored flag. `query` is required; filters: category, attribute, brand; sort; paging.

**Parameters:**
- `query` (string, required) — Search words as typed in the REWE shop (German works best).
- `zip_code` (string, optional) — German post code (PLZ, 5 digits). REWE prices and assortment belong to ONE market: with `service=delivery` the delivery market of this PLZ, with `service=pickup` the nearest pickup market. Give `zip_code` OR `market_id`; with neither, Köln 50667 is used and a warning says so.
- `market_id` (string, optional) — A REWE market id (wwIdent) exactly as the `markets` action returns it (pickup[].market_id or delivery.market_id). Use with the matching `service`.
- `service` (enum, optional, default "pickup") — Which REWE service the prices are for. The same product can cost differently (measured: Alpro oat drink 1,49 € pickup vs 2,49 € delivery, same PLZ). [one of: pickup, delivery]
- `category` (string, optional) — Category slug as the `categories` action or a row's facets return it (e.g. kaese-eier-molkerei, milch, frischmilch).
- `attribute` (enum, optional) — One product attribute filter: discounted (on offer), organic (Bio), regional, vegan, new, cool (chilled), frozen, glutenfree, lactosefree, loyalty_bonus (PAYBACK bonus). [one of: discounted, organic, regional, vegan, new, cool, frozen, glutenfree, lactosefree, loyalty_bonus]
- `brand` (string, optional) — Exact brand name as REWE prints it (e.g. ja!, REWE Bio, Alpro).
- `sort` (enum, optional, default "relevance") — relevance · price_asc · price_desc · name_asc · topseller. [one of: relevance, price_asc, price_desc, name_asc, topseller]
- `page` (integer, optional, default 1) — Result page (1-based). REWE serves rows up to number 10,000: page × per_page ≤ 10000.
- `per_page` (integer, optional, default 40) — Products per page, 1-100. REWE adds its sponsored rows ON TOP of this number (10 → 16 rows measured); they come flagged `sponsored`.

**Returns:** market{market_id, service, zip_code, resolved_from}, query, filters, sort, total, total_pages, page, has_more, returned, sponsored_returned, results[]{rank, product_id (-> product.product_id), name, brand, gtin, listing_id, available_in_market, price, regular_price, on_offer, discount_percent, offer_valid_to, currency, deposit (Pfand, NOT included in price), pack_size, grammage_text, base_price, base_unit, base_price_text, base_price_text_matches, order_limit, tags[], category_path, category_id, has_variants, merchant, merchant_type, sponsored, duplicate_of_rank (rank of an earlier row of the same product on this page; REWE shows some products twice, once sponsored), image, url}

**Example request body:**
```json
{
  "query": "milch",
  "zip_code": "50667"
}
```

### POST https://api.reefapi.com/rewe/v1/category — 2 credits
List one REWE category (slug from `categories`) in one market, with the same row fields and filters as `search`.

**Parameters:**
- `zip_code` (string, optional) — German post code (PLZ, 5 digits). REWE prices and assortment belong to ONE market: with `service=delivery` the delivery market of this PLZ, with `service=pickup` the nearest pickup market. Give `zip_code` OR `market_id`; with neither, Köln 50667 is used and a warning says so.
- `market_id` (string, optional) — A REWE market id (wwIdent) exactly as the `markets` action returns it (pickup[].market_id or delivery.market_id). Use with the matching `service`.
- `service` (enum, optional, default "pickup") — Which REWE service the prices are for. The same product can cost differently (measured: Alpro oat drink 1,49 € pickup vs 2,49 € delivery, same PLZ). [one of: pickup, delivery]
- `category` (string, optional) — Category slug as the `categories` action or a row's facets return it (e.g. kaese-eier-molkerei, milch, frischmilch).
- `attribute` (enum, optional) — One product attribute filter: discounted (on offer), organic (Bio), regional, vegan, new, cool (chilled), frozen, glutenfree, lactosefree, loyalty_bonus (PAYBACK bonus). [one of: discounted, organic, regional, vegan, new, cool, frozen, glutenfree, lactosefree, loyalty_bonus]
- `brand` (string, optional) — Exact brand name as REWE prints it (e.g. ja!, REWE Bio, Alpro).
- `sort` (enum, optional, default "relevance") — relevance · price_asc · price_desc · name_asc · topseller. [one of: relevance, price_asc, price_desc, name_asc, topseller]
- `page` (integer, optional, default 1) — Result page (1-based). REWE serves rows up to number 10,000: page × per_page ≤ 10000.
- `per_page` (integer, optional, default 40) — Products per page, 1-100. REWE adds its sponsored rows ON TOP of this number (10 → 16 rows measured); they come flagged `sponsored`.

**Returns:** market{market_id, service, zip_code, resolved_from}, query, filters, sort, total, total_pages, page, has_more, returned, sponsored_returned, results[]{rank, product_id (-> product.product_id), name, brand, gtin, listing_id, available_in_market, price, regular_price, on_offer, discount_percent, offer_valid_to, currency, deposit (Pfand, NOT included in price), pack_size, grammage_text, base_price, base_unit, base_price_text, base_price_text_matches, order_limit, tags[], category_path, category_id, has_variants, merchant, merchant_type, sponsored, duplicate_of_rank (rank of an earlier row of the same product on this page; REWE shows some products twice, once sponsored), image, url}

**Example request body:**
```json
{
  "category": "frischmilch",
  "zip_code": "50667"
}
```

### POST https://api.reefapi.com/rewe/v1/offers — 2 credits
REWE online-shop offers (Angebote) of one market: every discounted product with offer price, regular price, discount % and offer end date. Narrow with `query`, `category` or `brand`.

**Parameters:**
- `query` (string, optional) — Optional search words inside the offers.
- `zip_code` (string, optional) — German post code (PLZ, 5 digits). REWE prices and assortment belong to ONE market: with `service=delivery` the delivery market of this PLZ, with `service=pickup` the nearest pickup market. Give `zip_code` OR `market_id`; with neither, Köln 50667 is used and a warning says so.
- `market_id` (string, optional) — A REWE market id (wwIdent) exactly as the `markets` action returns it (pickup[].market_id or delivery.market_id). Use with the matching `service`.
- `service` (enum, optional, default "pickup") — Which REWE service the prices are for. The same product can cost differently (measured: Alpro oat drink 1,49 € pickup vs 2,49 € delivery, same PLZ). [one of: pickup, delivery]
- `category` (string, optional) — Category slug as the `categories` action or a row's facets return it (e.g. kaese-eier-molkerei, milch, frischmilch).
- `brand` (string, optional) — Exact brand name as REWE prints it (e.g. ja!, REWE Bio, Alpro).
- `sort` (enum, optional, default "relevance") — relevance · price_asc · price_desc · name_asc · topseller. [one of: relevance, price_asc, price_desc, name_asc, topseller]
- `page` (integer, optional, default 1) — Result page (1-based). REWE serves rows up to number 10,000: page × per_page ≤ 10000.
- `per_page` (integer, optional, default 40) — Products per page, 1-100. REWE adds its sponsored rows ON TOP of this number (10 → 16 rows measured); they come flagged `sponsored`.

**Returns:** market{market_id, service, zip_code, resolved_from}, query, filters, sort, total, total_pages, page, has_more, returned, sponsored_returned, results[]{rank, product_id (-> product.product_id), name, brand, gtin, listing_id, available_in_market, price, regular_price, on_offer, discount_percent, offer_valid_to, currency, deposit (Pfand, NOT included in price), pack_size, grammage_text, base_price, base_unit, base_price_text, base_price_text_matches, order_limit, tags[], category_path, category_id, has_variants, merchant, merchant_type, sponsored, duplicate_of_rank (rank of an earlier row of the same product on this page; REWE shows some products twice, once sponsored), image, url}

**Example request body:**
```json
{
  "zip_code": "10115"
}
```

### POST https://api.reefapi.com/rewe/v1/categories — 2 credits
The category tree of one market with product counts: top level, or the children of `category`. Slugs feed `category` / `search`.

**Parameters:**
- `zip_code` (string, optional) — German post code (PLZ, 5 digits). REWE prices and assortment belong to ONE market: with `service=delivery` the delivery market of this PLZ, with `service=pickup` the nearest pickup market. Give `zip_code` OR `market_id`; with neither, Köln 50667 is used and a warning says so.
- `market_id` (string, optional) — A REWE market id (wwIdent) exactly as the `markets` action returns it (pickup[].market_id or delivery.market_id). Use with the matching `service`.
- `service` (enum, optional, default "pickup") — Which REWE service the prices are for. The same product can cost differently (measured: Alpro oat drink 1,49 € pickup vs 2,49 € delivery, same PLZ). [one of: pickup, delivery]
- `category` (string, optional) — Parent category slug; omit for the top level.

**Returns:** market{...}, parent, total_products, categories[]{slug, name, count, children[]{slug, name, count, children[]}}

**Example request body:**
```json
{
  "zip_code": "50667"
}
```

### POST https://api.reefapi.com/rewe/v1/product — 3 credits
One REWE product in one market by the `product_id` a search row returns: price, regular price, discount, Pfand, base price, buyable flag and order limit, GTIN, brand, legal product name, description, ingredients, allergens and every label attribute, nutrition table, manufacturer, breadcrumb, images — and which market the page actually priced it for.

**Parameters:**
- `product_id` (string, required) — The numeric product id a search row returns, or its https://www.rewe.de/shop/p/<slug>/<id> URL.
- `zip_code` (string, optional) — German post code (PLZ, 5 digits). REWE prices and assortment belong to ONE market: with `service=delivery` the delivery market of this PLZ, with `service=pickup` the nearest pickup market. Give `zip_code` OR `market_id`; with neither, Köln 50667 is used and a warning says so.
- `market_id` (string, optional) — A REWE market id (wwIdent) exactly as the `markets` action returns it (pickup[].market_id or delivery.market_id). Use with the matching `service`.
- `service` (enum, optional, default "pickup") — Which REWE service the prices are for. The same product can cost differently (measured: Alpro oat drink 1,49 € pickup vs 2,49 € delivery, same PLZ). [one of: pickup, delivery]

**Returns:** requested_market{market_id, service, zip_code, resolved_from}, served_market_matches_request, product{product_id, article_id, gtin, listing_id, name, regulated_name, brand, description, price, regular_price, on_offer, discount_percent, offer_valid_to, currency, deposit, deposit_type, pack_size, grammage_text, base_price, base_unit, base_price_text, is_buyable, order_limit, tags[], organic, new, category_ids[], category_slug, breadcrumb[], images[], nutrition[]{state, per, nutrients[]{code, name, value, unit, precision}}, attributes[]{group, name, label, value}, ingredients, manufacturer{name, address}, merchant, packaging, served_market{market_id, service}, url}

**Example request body:**
```json
{
  "product_id": "2235048",
  "zip_code": "50667"
}
```

### POST https://api.reefapi.com/rewe/v1/markets — 1 credit
REWE markets for a German post code: whether home delivery is offered and by which market, and the pickup markets nearest first with address, distance and coordinates. The market ids feed every other action.

**Parameters:**
- `zip_code` (string, required) — German post code (PLZ, 5 digits).

**Returns:** zip_code, delivery{available, market_id}, pickup_available, pickup[]{market_id, name, company_name, street, house_number, zip_code, city, distance_m, lat, lon, pickup_variant, is_pickup_station}

**Example request body:**
```json
{
  "zip_code": "50667"
}
```

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