# Checkers API — South African grocery prices from checkers.co.za (Sixty60) and shoprite.co.za: price in rand, Xtra Savings card price, multi-buys, price per kg, stock on hand, barcode, categories and stores

> Search the Checkers Sixty60 (or Shoprite) shop for one delivery address: shelf price, was-price, Xtra Savings card price (kept apart from the price), Xtra Savings multi-buy, price per kg for goods sold by weight, stock on hand, brand and barcode per product. `query` or `category_id` is required (either one); `barcode` finds one product by its EAN.
> ReefAPI engine `checkers` · 5 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/checkers/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/checkers/v1/search — 3 credits
Search the Checkers Sixty60 (or Shoprite) shop for one delivery address: shelf price, was-price, Xtra Savings card price (kept apart from the price), Xtra Savings multi-buy, price per kg for goods sold by weight, stock on hand, brand and barcode per product. `query` or `category_id` is required (either one); `barcode` finds one product by its EAN.

**Parameters:**
- `query` (string, optional) — What to search for, as typed in the site's search box. Search is fuzzy: a nonsense word still returns loose matches. Required unless category_id or barcode is given.
- `category_id` (string, optional) — Category id from the `categories` action. Without a query any level works; together with a query only a top-level department narrows the search.
- `barcode` (string, optional) — Find the product with this barcode (EAN, 8-14 digits).
- `latitude` (number, optional) — Delivery address latitude (with longitude). Prices, stock and the assortment are those of the store that delivers there. Without an address the site's own default store is used and the answer says so (store_defaulted: true).
- `longitude` (number, optional) — Delivery address longitude (with latitude).
- `site` (enum, optional, default "checkers") — Which shop of the group: checkers (default) or shoprite. Same catalogue platform, own stores, prices and promotions. [one of: checkers, shoprite]
- `page` (integer, optional, default 1) — Page number, from 1. Past the last page the answer is an empty page.
- `page_size` (integer, optional, default 24) — Products per page, 1-48 (default 24, the site's own page).
- `sort` (enum, optional, default "relevance") — Order of the results. [one of: relevance, price_asc, price_desc, name_asc, name_desc]
- `brand` (string, optional) — Only this brand, written exactly as the `brand` field of a row (case-sensitive: Clover, not clover).
- `on_promotion` (boolean, optional, default false) — Only products on a deal (sale price or Xtra Savings offer).

**Returns:** query, category_id, category_path[], barcode, site, store_id, store_defaulted, location{latitude, longitude}, delivery_stores[]{store_id, service_options, distance_km}, total, page, page_size, returned, products[]{rank, product_id, article_number, unit_of_measure, title, brand, price, price_unit ('each' | 'kg'), currency, original_price, savings, on_promotion, member_price (Xtra Savings card price), member_price_program, member_price_basis ('stated' | 'computed_from_amount_off' | 'computed_from_percent_off'), member_price_text, member_price_ends, multi_buy{quantity, price, text, card_required, promotion_id}, promotions[]{promotion_id, promotion_code, text, discount_type, discount_value, member_type, card_required, kind, quantity, deal_price, starts, ends}, sold_by ('unit' | 'weight'), weight_range_g{min, max}, in_stock, stock_on_hand, max_per_order, barcodes[], categories[], rating, review_count, sponsored, requires_over_18, store_id, service_option, image, url}

**Example request body:**
```json
{
  "query": "milk",
  "latitude": -33.9249,
  "longitude": 18.4241
}
```

### POST https://api.reefapi.com/checkers/v1/promotions — 3 credits
Only the products on a deal for one delivery address — sale prices and Xtra Savings offers (card price, multi-buys) — inside a search term or a category (one of the two is required).

**Parameters:**
- `query` (string, optional) — Deals whose product matches this search (or give category_id).
- `category_id` (string, optional) — Category id from the `categories` action. Without a query any level works; together with a query only a top-level department narrows the search.
- `latitude` (number, optional) — Delivery address latitude (with longitude). Prices, stock and the assortment are those of the store that delivers there. Without an address the site's own default store is used and the answer says so (store_defaulted: true).
- `longitude` (number, optional) — Delivery address longitude (with latitude).
- `site` (enum, optional, default "checkers") — Which shop of the group: checkers (default) or shoprite. Same catalogue platform, own stores, prices and promotions. [one of: checkers, shoprite]
- `page` (integer, optional, default 1) — Page number, from 1. Past the last page the answer is an empty page.
- `page_size` (integer, optional, default 24) — Products per page, 1-48 (default 24, the site's own page).
- `sort` (enum, optional, default "relevance") — Order of the results. [one of: relevance, price_asc, price_desc, name_asc, name_desc]
- `brand` (string, optional) — Only this brand, written exactly as the `brand` field of a row (case-sensitive: Clover, not clover).

**Returns:** query, category_id, category_path[], site, store_id, store_defaulted, location{latitude, longitude}, delivery_stores[]{store_id, service_options, distance_km}, total, page, page_size, returned, products[]{rank, product_id, article_number, unit_of_measure, title, brand, price, price_unit ('each' | 'kg'), currency, original_price, savings, on_promotion, member_price (Xtra Savings card price), member_price_program, member_price_basis ('stated' | 'computed_from_amount_off' | 'computed_from_percent_off'), member_price_text, member_price_ends, multi_buy{quantity, price, text, card_required, promotion_id}, promotions[]{promotion_id, promotion_code, text, discount_type, discount_value, member_type, card_required, kind, quantity, deal_price, starts, ends}, sold_by ('unit' | 'weight'), weight_range_g{min, max}, in_stock, stock_on_hand, max_per_order, barcodes[], categories[], rating, review_count, sponsored, requires_over_18, store_id, service_option, image, url}

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

### POST https://api.reefapi.com/checkers/v1/product — 2 credits
One product for one delivery address by the `product_id` a search row returns (article number + unit, e.g. 10387741EA) or a product URL: price, was-price, Xtra Savings price and every offer with dates, price per kg and weight range, stock on hand, barcodes, brand, manufacturer, description, attributes (ingredients, nutrition, usage as the site prints them), categories, images.

**Parameters:**
- `product_id` (string, required) — The `product_id` exactly as a search row returns it (article number + unit: 10387741EA, 10156094PK1, 10796287KG) or a product URL ending in it.
- `latitude` (number, optional) — Delivery address latitude (with longitude). Prices, stock and the assortment are those of the store that delivers there. Without an address the site's own default store is used and the answer says so (store_defaulted: true).
- `longitude` (number, optional) — Delivery address longitude (with latitude).
- `site` (enum, optional, default "checkers") — Which shop of the group: checkers (default) or shoprite. Same catalogue platform, own stores, prices and promotions. [one of: checkers, shoprite]

**Returns:** site, store_id, store_defaulted, location, product{product_id, article_number, unit_of_measure, internal_id, title, brand, manufacturer, price, price_unit, currency, original_price, savings, on_promotion, member_price, member_price_program, member_price_basis, member_price_text, member_price_ends, multi_buy{…}, promotions[]{…}, sold_by, weight_range_g, in_stock, stock_on_hand, max_per_order, barcodes[], categories[], category_ids[], description, short_description, attributes[]{name, value}, pack_size, pack_quantity, dimensions, has_alcohol, has_tobacco, requires_over_18, rating, review_count, images[], image, url}

**Example request body:**
```json
{
  "product_id": "10413121EA"
}
```

### POST https://api.reefapi.com/checkers/v1/categories — 2 credits
The shop's category tree (33 departments, 3 levels) with the ids `search` takes as category_id; or one department's subtree.

**Parameters:**
- `category_id` (string, optional) — A top-level department id: only its subtree.
- `site` (enum, optional, default "checkers") — Which shop of the group: checkers (default) or shoprite. Same catalogue platform, own stores, prices and promotions. [one of: checkers, shoprite]

**Returns:** site, departments, total_categories, categories[]{category_id, name, level, parent_id, children[]{…}}

**Example request body:**
```json
{
  "category_id": "67075e27ff987811364007a9"
}
```

### POST https://api.reefapi.com/checkers/v1/stores — 2 credits
Physical stores of the Shoprite group near a point (Checkers, Checkers Hyper, Checkers FX, Shoprite, LiquorShop, MediRite, Petshop Science …): name, brand, address, coordinates, distance, opening hours per day.

**Parameters:**
- `latitude` (number, required) — Latitude of the point to search around.
- `longitude` (number, required) — Longitude of the point.
- `radius_km` (integer, optional, default 20) — Search radius in km (1-300, default 20).
- `limit` (integer, optional, default 12) — At most this many stores, nearest first (1-200, default 12).
- `brand` (string, optional) — Keep only stores whose brand starts with this text (case-insensitive), applied to the nearest `limit` stores.
- `site` (enum, optional, default "checkers") — Which shop of the group: checkers (default) or shoprite. Same catalogue platform, own stores, prices and promotions. [one of: checkers, shoprite]

**Returns:** site, location{latitude, longitude}, radius_km, returned, brands{brand: count}, stores[]{store_id, name, brand, pos_site_code, address, latitude, longitude, distance_km, hours{monday … sunday: 'HH:MM-HH:MM' | null}}

**Example request body:**
```json
{
  "latitude": -33.9249,
  "longitude": 18.4241
}
```

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