Looking for the overview — what this API returns, what it costs, and a call you can run without a key? See the ŞOK Market API page →
E-commerce & Marketplaces

Ş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.

7 actionsLive JSON1,000 free credits$0.67–$1.50 / 1,000 creditsMCP-ready
Get a free keyOpen in playground

🤖 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.

Reference

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.

FieldCoverage on 2,722 offersWhat comes back
price2,722 of 2,722The price at the store named in store_id, in TRY.
price_before_discount228 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_percent228 of 2,722Computed only from two prices ŞOK published. Never estimated, never zero.
campaigns / badges167 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_price0 of 2,722Always 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_on0 campaignsAlways null. ŞOK's only dates are sentences inside the campaign conditions, which come back as terms.
store_sku_code2,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.

Live example

Real request and response JSON

Captured from the indexed primary action, search, on .

Captured request
{
  "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"
  }
}
Captured response
{
  "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"
  }
}
Actions

What the ŞOK Market API does

ActionDescriptionConcrete use caseKey params
searchSearch Ş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/productsBrowse 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/detailOne Ş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
campaignsThe 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
Code samples

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"}'
MCP one-liner
Ask your MCP-connected assistant: call reefapi.sok.search with {"query":"süt","channel":"market"}.
Use cases

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.
FAQ

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.

docs / sok

ŞOK Market

Turkish discount grocery online: ŞOK Market and ŞOK Ekstra, this week's Haftanın Fırsatları deals, prices in lira per store.

base /sok/v17 endpoints
post/sok/v1/category/products1 credit

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.

ParameterAllowed / rangeDescription
category_idrequired—The ŞOK category to browse — an id from the `categories` action or the number at the end of a category URL (…-c-460 → 460).
channel = marketoptionalmarket · ekstraWhich ŞOK shop to read. The two shops have separate catalogues, separate stores and separate prices.
page = 0optional0–500Zero-based page number (ŞOK's own numbering).
page_size = 100optional1–500Products per page, 1-500 (default 100).
sort = relevanceoptionalrelevance · relevance_asc · price_asc · price_descThe four sort orders ŞOK's own search supports.
brand_idoptional—Restrict to one ŞOK brand id (the `brand_id` on any row).
min_priceoptional0–Only products priced at or above this, in TRY.
max_priceoptional0–Only products priced at or below this, in TRY.
only_campaign_products = falseoptional—Only products carrying a ŞOK campaign badge (ŞOK's own "Kampanyalı Ürünler" filter).
store_idoptional—Advanced: read a named ŞOK store instead of the default online store. Prices are almost always the same across stores but the assortment is not; every answer says which store it came from.
max_rotations = 5optional1–10Advanced: how many times to retry a difficult request (1-10, default 5).
Try in playground →
post/sok/v1/categoriesfree

Ş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`.

ParameterAllowed / rangeDescription
channel = marketoptionalmarket · ekstraWhich ŞOK shop to read. The two shops have separate catalogues, separate stores and separate prices.
max_depth = 3optional1–6How many levels of the category tree to return (1-6).
store_idoptional—Advanced: read a named ŞOK store instead of the default online store. Prices are almost always the same across stores but the assortment is not; every answer says which store it came from.
max_rotations = 5optional1–10Advanced: how many times to retry a difficult request (1-10, default 5).
Try in playground →
post/sok/v1/product/detail1 credit

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.

ParameterAllowed / rangeDescription
product_idoptional—The ŞOK product id — the number at the end of a product URL (…-p-5834 → 5834). Give this or `url`.
urloptional—A ŞOK product page URL, instead of `product_id`.
channel = marketoptionalmarket · ekstraWhich ŞOK shop to read. The two shops have separate catalogues, separate stores and separate prices.
store_idoptional—Advanced: read a named ŞOK store instead of the default online store. Prices are almost always the same across stores but the assortment is not; every answer says which store it came from.
max_rotations = 5optional1–10Advanced: how many times to retry a difficult request (1-10, default 5).
Try in playground →
post/sok/v1/campaigns2 credits

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.

ParameterAllowed / rangeDescription
campaign = weekly_dealsoptionalweekly_deals · badge_campaigns · campaign · promotion_group · product_groupWhich ŞOK campaign listing to return. `weekly_deals` is the deal page ŞOK links from its own front page.
campaign_idoptional—Required with campaign=campaign: a campaign id from the `campaigns/list` action.
group_idoptional—Required with campaign=promotion_group or campaign=product_group: the id at the end of the group's URL (…-pgrp-<id> / …-sgrp-<id>).
channel = marketoptionalmarket · ekstraWhich ŞOK shop to read. The two shops have separate catalogues, separate stores and separate prices.
page = 0optional0–500Zero-based page number (ŞOK's own numbering).
page_size = 100optional1–500Products per page, 1-500 (default 100).
store_idoptional—Advanced: read a named ŞOK store instead of the default online store. Prices are almost always the same across stores but the assortment is not; every answer says which store it came from.
max_rotations = 5optional1–10Advanced: how many times to retry a difficult request (1-10, default 5).
Try in playground →
post/sok/v1/campaigns/listfree

Ş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.

ParameterAllowed / rangeDescription
channel = marketoptionalmarket · ekstraWhich ŞOK shop to read. The two shops have separate catalogues, separate stores and separate prices.
group_idoptional—Only list campaigns in one ŞOK campaign group (an id from this action's own `groups` list).
page = 0optional0–500Zero-based page number (ŞOK's own numbering).
store_idoptional—Advanced: read a named ŞOK store instead of the default online store. Prices are almost always the same across stores but the assortment is not; every answer says which store it came from.
max_rotations = 5optional1–10Advanced: how many times to retry a difficult request (1-10, default 5).
Try in playground →
post/sok/v1/suggest1 credit

ŞOK's own search autocomplete for a partial keyword: the search terms and category suggestions the site offers while the shopper types.

ParameterAllowed / rangeDescription
queryrequired—What the shopper has typed so far (2+ characters).
channel = marketoptionalmarket · ekstraWhich ŞOK shop to read. The two shops have separate catalogues, separate stores and separate prices.
store_idoptional—Advanced: read a named ŞOK store instead of the default online store. Prices are almost always the same across stores but the assortment is not; every answer says which store it came from.
max_rotations = 5optional1–10Advanced: how many times to retry a difficult request (1-10, default 5).
Try in playground →
Built for volume
5M+ requests a day

Measured at 60 requests a second across the fleet, with no central bottleneck. Volume pricing is on request, and per-key limits are raised for high-volume accounts.

Missing a source?
We build it

Tell us a site we do not cover yet and it becomes an engine. A customer asked for bestprice.gr on a Sunday and it was in the catalog the next day.

Support
2 minute median reply

Median time from a question in the live chat to the first answer, measured across every answered conversation. Setup help included, no support tier to buy.

One key, one balance
Every API included

No per-site plans and no separate subscriptions. One key and one credit pool across the whole catalog, so adding a source costs nothing up front.

Planning something large? Tell us the volume and the sources and we will come back with what it costs and what we would have to build.