# CarrefourSA API scraper — CarrefourSA (Turkey) online grocery: search and browse products, read the full product record with the regular price and the CarrefourSA Kart member price kept apart, unit prices, multi-buy and basket campaigns, stock, barcode, label sheet and nutrition table, plus reviews and search suggestions. Prices in TRY. No account, no browser.

> Search carrefoursa.com by keyword, or browse a category, and get one row per product: the regular price and, separately, the CarrefourSA Kart member price when one runs, unit price for weight-sold and multi-pack products, stock status with unit count, multi-buy and basket campaigns with their dates, brand and category path. Filter by brand, price band and in-stock, sort the way the site does, page through the results. The response also lists the categories, brands, price bands and package sizes available for the query.
> ReefAPI engine `carrefoursa` · 4 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/carrefoursa/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, `Authorization: Bearer <key>`) and your assistant can call these actions directly.

## Endpoints

### POST /carrefoursa/v1/search — 1 credit
Search carrefoursa.com by keyword, or browse a category, and get one row per product: the regular price and, separately, the CarrefourSA Kart member price when one runs, unit price for weight-sold and multi-pack products, stock status with unit count, multi-buy and basket campaigns with their dates, brand and category path. Filter by brand, price band and in-stock, sort the way the site does, page through the results. The response also lists the categories, brands, price bands and package sizes available for the query.

**Parameters:**
- `query` (string, optional) — What to look for on carrefoursa.com, as a shopper would type it. Turkish keywords match best ('peynir', 'zeytinyağı', 'bebek bezi'); brand names and small typos work too. Optional when `category` is given.
- `category` (string, optional) — Browse or narrow to one CarrefourSA category: its code (the number after /c/ in a category URL, e.g. https://www.carrefoursa.com/beyaz-peynir/c/1319 → 1319) or the URL itself. Codes come back in every row's `category.id`, in `keyword_redirect` and in `filters_available`.
- `page` (integer, optional, default 1) — Result page, 1-based.
- `page_size` (integer, optional, default 20) — Products per page, 1-100 (default 20).
- `sort` (enum, optional, default "relevance") — Result order — only the orderings carrefoursa.com offers. `sort_applied` in the response is CarrefourSA's own confirmation. [one of: relevance, best_selling, price_asc, price_desc]
- `brand` (string, optional) — Only these brands: CarrefourSA brand codes (BRN-1392) as returned in `filters_available.brands` and every row's `brand.id`. Several codes (comma-separated or a list) mean any of them.
- `in_stock` (boolean, optional, default false) — true = only products CarrefourSA shows as in stock.
- `price_band` (string, optional) — Only products in these CarrefourSA price bands, exactly as labelled in `filters_available.price_bands` (e.g. '50 TL - 199,99 TL'). Several bands mean any of them. Arbitrary ranges are not supported by the site.
- `max_rotations` (integer, optional, default 4) — Advanced: how many times to retry a difficult request (1-8, default 4).

**Returns:** results[]{position, product_id, title, brand{id, name, url}, category{id, name, url}, category_path[], url, image, price (number, TRY — what a shopper WITHOUT a CarrefourSA Kart pays), price_display, currency=TRY, original_price (null — no non-card discount was observed), discount_percent (null), member_price (the CarrefourSA Kart price when one runs, else null), member_price_display, member_discount_percent, member_program ('CarrefourSA Kart' | null), member_price_condition (e.g. '100 TL ve Üzeri %40' when the card price needs a minimum basket, else null), unit_price, unit_price_unit ('kg' | 'l' | 'piece'), member_unit_price, unit_price_basis ('sold_by_weight' | 'site_per_piece' | 'package_size' | null), sold_by ('piece' | 'weight'), price_per ('piece' | 'kg'), availability ('in_stock' | 'low_stock' | 'out_of_stock'), in_stock, stock_level (units at the default online store), limited_stock, min_order_quantity, max_order_quantity (an order cap, not stock), order_step, badges[]{type, text}, promotions[]{text, description, code, kind ('multi_buy' | 'basket_threshold' | 'campaign'), card_required, active_from, active_to}, multi_buy_offer, special_today, search_index_rating, search_index_review_count (category browse rows only)}, count, page, page_size, total_results, total_pages, has_more, sort_applied, keyword_redirect{type, id, url} (the category or brand page the website would send this keyword to — rows are still the keyword's own matches), applied_filters[]{filter, id, name}, filters_available{categories[], top_categories[], brands[], package_sizes[]{id, name, count}, price_bands[]{label, count}, in_stock_count, out_of_stock_count} (null if that part of the answer was unavailable), query, category

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

### POST /carrefoursa/v1/product/detail — 1 credit
The full CarrefourSA product record by product code or URL: title, brand, category path, every image, barcode, the regular price and the CarrefourSA Kart price kept apart (with the minimum basket when the card price needs one), unit price, package size, availability and order limits, multi-buy and basket campaigns with dates, the label sheet (ingredients, allergens, origin, storage, food business operator) and the nutrition table, the description and rating.

**Parameters:**
- `product_id` (string, required) — CarrefourSA product code — the number every search row returns as `product_id` (30500720) — or a carrefoursa.com product URL.
- `max_rotations` (integer, optional, default 4) — Advanced: how many times to retry a difficult request (1-8, default 4).

**Returns:** product{product_id, title, brand{id, name, url}, category{id, name, url}, category_path[], url, images[], barcode, barcode_in_store_code, price (number, TRY — what a shopper WITHOUT a CarrefourSA Kart pays), price_display, currency=TRY, original_price (null — no non-card discount was observed), discount_percent (null), member_price (the CarrefourSA Kart price when one runs, else null), member_price_display, member_discount_percent, member_program ('CarrefourSA Kart' | null), member_price_condition (e.g. '100 TL ve Üzeri %40' when the card price needs a minimum basket, else null), unit_price, unit_price_unit ('kg' | 'l' | 'piece'), member_unit_price, unit_price_basis ('sold_by_weight' | 'site_per_piece' | 'package_size' | null), sold_by ('piece' | 'weight'), price_per ('piece' | 'kg'), package_size{raw, amount, unit}, availability ('in_stock' | 'out_of_stock'), in_stock, limited_stock, limited_stock_text, min_order_quantity, max_order_quantity, order_step, free_shipping, badges[], promotions[], multi_buy_offer, special_today, sponsored, rating (1-5, null when unrated), review_count (written reviews), rating_scale, description, specs{label: value}, spec_table[], nutrition{basis, reference_intake_basis, rows[]{name, value, reference_intake_percent}, note}, ingredients, allergens, origin, storage, usage, warnings, food_business_operator, approval_number, variants[] (always empty — no variant products seen), price_scope_note}

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

### POST /carrefoursa/v1/product/reviews — 1 credit
Written customer reviews of one CarrefourSA product, newest first: star rating (1-5), headline, review text and date. Most products have none; reviewer names are never returned.

**Parameters:**
- `product_id` (string, required) — CarrefourSA product code — the number every search row returns as `product_id` (30500720) — or a carrefoursa.com product URL.
- `limit` (integer, optional, default 20) — How many reviews to return, newest first (1-100, default 20).
- `max_rotations` (integer, optional, default 4) — Advanced: how many times to retry a difficult request (1-8, default 4).

**Returns:** reviews[]{rating, headline, comment, date}, count, total_reviews, average_rating, rating_scale (5), order ('newest_first'), product_id

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

### POST /carrefoursa/v1/search/suggest — 1 credit
CarrefourSA's own search-box suggestions for what a shopper has typed so far.

**Parameters:**
- `query` (string, required) — What the shopper has typed so far (at least 2 characters).
- `max_rotations` (integer, optional, default 4) — Advanced: how many times to retry a difficult request (1-8, default 4).

**Returns:** suggestions[] (search phrases), products[]{product_id, title, url} (empty unless the site returns product suggestions), query

**Example request body:**
```json
{
  "query": "çikol"
}
```

## More
- Try it live, no code: https://reefapi.com/playground?engine=carrefoursa
- Human docs page: https://reefapi.com/docs/carrefoursa
- Overview page: https://reefapi.com/carrefoursa-api
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
