ŞOK Market API & Scraper
The ŞOK Market API turns sokmarket.com.tr, the online shop of Turkey's ŞOK discount grocery chain, into clean JSON in seven actions.
🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.
search runs ŞOK's own product search in either of its two shops: market for groceries, household and personal care, or ekstra for electronics, home and fashion, with ŞOK's four sort orders and optional category, brand and price filters. Each row carries the product id, title, brand, URL, images, the store's price, ŞOK's struck price and the discount where one exists, stock, the full category path and any campaign badge the product carries. category/products browses one category and categories returns ŞOK's whole tree, 250 categories for the grocery shop and 123 for Ekstra, so you never have to guess an id. product/detail returns one product with its description, country of origin, net quantity, ingredients, allergen warning, storage condition, nutrition table and package dimensions. campaigns returns the products of Haftanın Fırsatları, ŞOK's weekly deal page, as well as its badge campaigns, any single named campaign with its conditions, and ŞOK's promotion and product groups; campaigns/list is the campaign catalogue itself, and suggest returns ŞOK's own search autocomplete. ŞOK prices are scoped to a store, so every row and every response says which store it came from. In a live check on 2026-09-24, 102 of 102 calls across all seven actions succeeded. Prices are Turkish lira. No ŞOK account, no browser, one ReefAPI key and the standard { ok, data, meta, error } envelope.
What ŞOK publishes, and what it does not
ŞOK prints one shelf price and, on about one product in twelve, a struck-through was-price. It prints no unit price at all and no campaign dates. The API returns what ŞOK publishes and leaves the rest null rather than calculating it. Census taken on 2026-09-24 over the whole default store, 2,722 offers.
| Field | Coverage on 2,722 offers | What comes back |
|---|---|---|
| price | 2,722 of 2,722 | The price at the store named in store_id, in TRY. |
| price_before_discount | 228 of 2,722 | ŞOK's own struck price. Null on the rest, because ŞOK repeats the shelf price there and a repeated price is not a discount. |
| discount_percent | 228 of 2,722 | Computed only from two prices ŞOK published. Never estimated, never zero. |
| campaigns / badges | 167 and 158 of 2,722 | ŞOK's campaign badges, such as buy-one-get-one and basket thresholds. Most carry no struck price because the benefit lands at the basket. |
| unit_price | 0 of 2,722 | Always null. ŞOK shows no price per litre or kilo anywhere, and no figure is derived from the pack size in the title. |
| campaign starts_on / ends_on | 0 campaigns | Always null. ŞOK's only dates are sentences inside the campaign conditions, which come back as terms. |
| store_sku_code | 2,722 of 2,722 | ŞOK's internal article number. It is not a barcode and is not returned as one. |
Prices are per store. Compared against five other real ŞOK stores on 489 shared products, the price differed on two of them, but only 70 to 141 of every 500 products were stocked by both. Which products a store carries varies far more than what they cost, so the store is never averaged away and never hidden.
Real request and response JSON
Captured from the indexed primary action, search, on .
{
"method": "POST",
"url": "https://api.reefapi.com/sok/v1/search",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"query": "süt",
"channel": "market"
}
}{
"ok": true,
"meta": {
"api": "sok",
"endpoint": "search",
"mode": "live",
"latency_ms": 3196.5,
"record_count": 100,
"bytes": 164079,
"cache_hit": false,
"pagination": {
"page": 0,
"page_size": 100,
"total": 194,
"has_more": true
},
"charged_credits": 1,
"version": "0.1.0"
},
"data": {
"results": [
{
"product_id": "5834",
"sku_id": "5834.1",
"offer_id": "5834.1.1.13412",
"channel": "market",
"store_id": "13412",
"title": "Mis Uht Süt Yarım Yağlı 1 L",
"brand": "MİS",
"brand_id": 6,
"url": "https://www.sokmarket.com.tr/mis-uht-sut-yarim-yagli-1-l-p-5834",
"image": "https://images.ceptesok.com/product-assets/sub-folder/d61f2833-887e-414b-9512-af75ad163ae6.png",
"images": [
"https://images.ceptesok.com/product-assets/sub-folder/d61f2833-887e-414b-9512-af75ad163ae6.png"
],
"price": 43.5,
"price_before_discount": null,
"discount_percent": null,
"currency": "TRY",
"unit_price": null,
"in_stock": true,
"private_label": true,
"sales_unit": "EACH",
"min_order_quantity": 1,
"max_order_quantity": 99,
"quantity_increment": 1,
"category": "Süt",
"category_id": 470,
"category_path": [
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]",
"url": "[trimmed-depth]"
},
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]",
"url": "[trimmed-depth]"
},
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]",
"url": "[trimmed-depth]"
}
],
"campaigns": [],
"badges": [],
"store_sku_code": "11011001",
"position": 1
},
{
"product_id": "7796",
"sku_id": "7796.1",
"offer_id": "7796.1.1.13412",
"channel": "market",
"store_id": "13412",
"title": "İçim Organik Süt 1 L",
"brand": "İÇİM",
"brand_id": 301,
"url": "https://www.sokmarket.com.tr/icim-organik-sut-1-l-p-7796",
"image": "https://images.ceptesok.com/product-assets/sub-folder/642caf4f-b52d-493f-9813-f5d533f778e5.png",
"images": [
"https://images.ceptesok.com/product-assets/sub-folder/642caf4f-b52d-493f-9813-f5d533f778e5.png"
],
"price": 88.5,
"price_before_discount": null,
"discount_percent": null,
"currency": "TRY",
"unit_price": null,
"in_stock": true,
"private_label": false,
"sales_unit": "EACH",
"min_order_quantity": 1,
"max_order_quantity": 12,
"quantity_increment": 1,
"category": "Süt",
"category_id": 470,
"category_path": [
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]",
"url": "[trimmed-depth]"
},
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]",
"url": "[trimmed-depth]"
},
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]",
"url": "[trimmed-depth]"
}
],
"campaigns": [],
"badges": [],
"store_sku_code": "00083212",
"position": 2
},
{
"product_id": "5179",
"sku_id": "5179.1",
"offer_id": "5179.1.1.13412",
"channel": "market",
"store_id": "13412",
"title": "Mis Uht Süt Yağsız 1 L",
"brand": "MİS",
"brand_id": 6,
"url": "https://www.sokmarket.com.tr/mis-uht-sut-yagsiz-1-l-p-5179",
"image": "https://images.ceptesok.com/product-assets/sub-folder/c87d0ff9-d53f-4956-8def-4099f523abea.jpg",
"images": [
"https://images.ceptesok.com/product-assets/sub-folder/c87d0ff9-d53f-4956-8def-4099f523abea.jpg",
"https://images.ceptesok.com/product-assets/sub-folder/347cd982-4938-4ada-b3cc-4d2f669736dc.jpg",
"https://images.ceptesok.com/product-assets/sub-folder/12d4b983-b149-4393-b07b-362300ee0b7b.jpg"
],
"price": 36,
"price_before_discount": null,
"discount_percent": null,
"currency": "TRY",
"unit_price": null,
"in_stock": true,
"private_label": true,
"sales_unit": "EACH",
"min_order_quantity": 1,
"max_order_quantity": 12,
"quantity_increment": 1,
"category": "Süt",
"category_id": 470,
"category_path": [
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]",
"url": "[trimmed-depth]"
},
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]",
"url": "[trimmed-depth]"
},
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]",
"url": "[trimmed-depth]"
}
],
"campaigns": [],
"badges": [],
"store_sku_code": "00080691",
"position": 3
}
],
"count": 100,
"total_results": 194,
"total_pages": 2,
"page": 0,
"page_size": 100,
"has_more": true,
"channel": "market",
"store_id": "13412",
"sort": "relevance",
"filters_applied": {
"sort": "relevance"
},
"query": "süt"
}
}What the ŞOK Market API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| search | Search ŞOK by keyword in either shop — `market` (the online grocery shelf) or `ekstra` (electronics, home, fashion) — with ŞOK's own sort orders and optional category, brand and price filters. Each row carries the product id, title, brand, URL, images, the store's price, ŞOK's struck price and discount where one exists, stock, the full category path and any campaign badge the product carries. | Pricing teams call search to search ŞOK by keyword in either shop. | query, channel, page, page_size, sort, ... |
| category/products | Browse one ŞOK category — every product ŞOK lists in it, paged, with the same fields as search and the same optional brand, price and campaign filters. Category ids come from the `categories` action or from the number at the end of a ŞOK category URL. | Marketplace operators call category/products to get browse one ŞOK category. | category_id, channel, page, page_size, sort, ... |
| categories | ŞOK's whole category tree for a shop — every category with its id, name, level, parent and URL, nested — plus the shortcuts ŞOK links from its own front page (its weekly deal page, new products, gluten-free and so on). Use the ids with `category/products`. | Catalog enrichment teams call categories to get şOK's whole category tree for a shop. | channel, max_depth, store_id, max_rotations |
| product/detail | One ŞOK product by id or URL: the store's price, ŞOK's struck price and discount where one exists, stock, brand, own-brand flag, images, the full category path, campaign badges, the product description, country of origin, net quantity, ingredients, allergen warning, storage condition, usage instructions, the nutrition table and the package dimensions ŞOK publishes. | Retail analysts call product/detail to get one ŞOK product by id or URL. | product_id, url, channel, store_id, max_rotations |
| campaigns | The products of a ŞOK campaign listing. `weekly_deals` (the default) is ŞOK's own deal page — every product it currently sells below its struck price, with both prices and the discount. `badge_campaigns` is ŞOK's "Kampanyalı Ürünler" filter (1 Alana 1 Bedava, 50 TL ve üzeri…). `campaign` returns one named campaign's products together with its terms; `promotion_group` and `product_group` return ŞOK's own grouped listings. | Pricing teams call campaigns to get the products of a ŞOK campaign listing. | campaign, campaign_id, group_id, channel, page, ... |
| campaigns/list | ŞOK's campaign catalogue: every campaign currently running with its id, title, conditions, page URL and artwork, plus the campaign groups ŞOK sorts them into. Feed a campaign_id back into the `campaigns` action to get that campaign's products. | Marketplace operators call campaigns/list to get şOK's campaign catalogue. | channel, group_id, page, store_id, max_rotations |
| suggest | ŞOK's own search autocomplete for a partial keyword: the search terms and category suggestions the site offers while the shopper types. | Catalog enrichment teams call suggest to get şOK's own search autocomplete for a partial keyword. | query, channel, store_id, max_rotations |
Call search from your stack
curl -X POST https://api.reefapi.com/sok/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"query":"süt","channel":"market"}'import requests
r = requests.post(
"https://api.reefapi.com/sok/v1/search",
headers={"x-api-key": REEF_KEY},
json={
"query": "süt",
"channel": "market"
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/sok/v1/search", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"query": "süt",
"channel": "market"
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.sok.search with {"query":"süt","channel":"market"}.Who uses this API and why
- Grocery price trackers store a daily row per product per store and follow ŞOK's marked-down set, which is its own struck price rather than an estimate.
- Deal and discount sites publish Haftanın Fırsatları the morning it changes, with both prices and the discount ŞOK itself printed.
- Turkish retail analysts compare ŞOK against A101, BİM and Migros on the same keyword and category, week over week.
- Product-data teams enrich a catalogue with country of origin, net quantity, ingredients, allergens, storage conditions and the nutrition table.
- Assortment analysis reads the same category at several store ids to see which products a store actually carries, which varies far more than the price does.
Questions developers ask before integrating
Where is Aldın Aldın?
That is A101's weekly campaign, not ŞOK's. ŞOK's weekly deal page is Haftanın Fırsatları, and you get it from campaigns with campaign set to weekly_deals: every product ŞOK is currently selling below its own struck price, with both prices and the discount. Use the a101 API if you want Aldın Aldın.
What is the difference between market and ekstra?
They are ŞOK's two online shops. market is the grocery shelf: food, drinks, cleaning and personal care, delivered from a store and priced at that store. ekstra is ŞOK Ekstra: electronics, white goods, furniture, fashion and pet supplies, shipped. They have separate catalogues, separate category trees and separate stores, so a washing-machine search in market finds nothing. The channel parameter is on every action.
Which store do the prices belong to?
ŞOK's default online store, the one a logged-out shopper sees. Its number is on every row as store_id and in meta. Pass store_id if you know another ŞOK store number and you read that store instead. An unknown store id returns zero rows, so a wrong number cannot silently hand you another store's prices.
Why is in_stock true on everything?
Because ŞOK's listing only publishes offers it has. It was true on 2,722 of 2,722 offers. Out-of-stock products are absent from the listing rather than flagged, so the real availability signal is whether a product appears for a given store at all, not the flag.
Does ŞOK search tolerate typos?
No. ŞOK matches words literally: sutt, cikolatta and samsng all return nothing, and ŞOK never pads an unmatched query with unrelated products the way some retailers do. So an empty result is a real statement about ŞOK's shelf, and the response says so in page_notice rather than leaving you to guess.
How do the pages work?
Page numbering is ŞOK's own and starts at zero. page_size defaults to 100 and goes up to 500. Past the last page ŞOK reports a total of zero, which looks exactly like no such product, so the response distinguishes the two in page_notice and tells you to read page 0 for the real count.
What is the ŞOK Market API?
ŞOK Market API is a ReefAPI endpoint group for turkish discount grocery online: şok market and şok ekstra, this week's haftanın fırsatları deals, prices in lira per store. It returns live JSON through POST requests under /sok/v1.
Is the ŞOK Market API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. ŞOK Market calls use the same shared credit balance as every other ReefAPI engine.
Do I need a ŞOK Market login or account?
No login to ŞOK Market is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the ŞOK Market data?
The page example is captured from a live search call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the ŞOK Market API use?
ŞOK Market actions currently cost 1-2 credits per successful call. Failed or blocked calls are free. All APIs draw from one credit pool.
Can I call ŞOK Market from an AI assistant or MCP client?
Yes. Connect ReefAPI once through MCP and your assistant can call sok actions with the same key, credit pool and JSON envelope used by normal REST requests.
Is the ŞOK Market API a ŞOK Market scraper?
It is the managed alternative to a DIY ŞOK Market scraper. Instead of building and maintaining your own scraper — proxies, headless browsers, captcha and constant breakage — you call one ReefAPI endpoint and get the same turkish discount grocery online: şok market and şok ekstra, this week's haftanın fırsatları deals, prices in lira per store back as clean JSON.
Why does my ŞOK Market scraper keep getting blocked?
Most ŞOK Market scrapers break on anti-bot defenses, rate limits and IP bans that need rotating residential proxies and browser fingerprinting to clear. ReefAPI handles all of that for you — no proxies, no captchas, no maintenance — and returns live JSON. Blocked calls are free.