Pricing analystsRevenue growth managersCategory teams

Walk into Monday's price meeting with this morning's shelf prices.

Shelffeed reads competitor shelf prices, promo mechanics and weekly flyers from 23 grocery banners and returns them as JSON. No six-week panel lag, no aisle walks, no flyer screenshots pasted into a spreadsheet.

A request API: each call opens the retailer's site in a real browser and reads the shelf at that moment. You decide when and how often to ask.

PRICE GAP MATRIXBelgium / 4 banners / incl. promo
BannerShelfPromoNet unitGap vs you

Simulated prices and promotions for illustration. Not live retailer data.

79endpoints you can call today
23retail banners and flyer sources
13countries, strongest in Belgium, Iberia, Italy and Israel
26endpoints across 5 Belgian banners alone
Three moments you know

The data you price on is older than the promo you are reacting to.

MON 08:40

The price meeting runs on a spreadsheet somebody walked for.

A colleague photographed competitor aisles on Friday, or screenshotted three flyers on Sunday night. Half the cells are from last week. Nobody is sure which half.

SKUComp. AChecked Milk 1 L1.09Fri Coffee 500 g5.4912 days Pasta 500 g?no photo Olive oil 1 L8.9919 days
WEEK 3 OF THE PERIOD

Volume on a top-50 SKU drops. You find the promo afterwards.

A competitor ran 2+1 on your hero line for two weeks. The panel report that would have told you arrives next month, priced like a company car.

wk 1competitor 2+1: wk 4 to 5wk 6
RE: COVERAGE REQUEST

The big data vendor does not track the banner that actually hurts you.

Your real competitor is a mid-size regional chain with 120 stores. It is too small for the syndicated feed, and exactly big enough to take your shoppers.

From: account team
"That banner is outside our current
panel scope. We can scope a custom
study for next fiscal year."

Illustrative scenarios with made-up figures.

Coverage

79 endpoints. Including the regional banners the panels skip.

Each endpoint is one job against one retailer: search products, read a product page, list a category, pull this week's promotions, fetch the flyer.

This is the full list, not a sample. Depth varies by banner: Carrefour Belgium has 11 endpoints, Hoogvliet has one. If the banner you compete with is missing, tell us which one and what you need read from it.

How it works

One POST per question. JSON back.

1

Pick an endpoint. Each one has a function ID and a short list of variables, such as a search term, a category or a postal code.

2

Start a run. We open the retailer's site in a real browser on our side, read what a shopper would see, and structure it.

3

Store the answer. The data is read at call time. Schedule the calls you need, daily or before each price meeting, and keep the history in your own warehouse.

Works from Python, R, Power Query, Airflow or anything that can send an HTTPS request.

illustrative shape
# Delhaize Belgium - product search
curl -L -X POST \
  "https://api.notte.cc/functions/$FUNCTION_ID/runs/start" \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "function_id": "'"$FUNCTION_ID"'",
    "variables": {
      "query": "halfvolle melk 1L"
    }
  }'
// Illustrative response shape. Field names vary by endpoint.
// Values below are made up.
{
  "status": "closed",
  "result": {
    "banner": "delhaize-be",
    "query": "halfvolle melk 1L",
    "read_at": "2026-11-09T06:02:11Z",
    "products": [
      {
        "name": "Halfvolle melk 1 L",
        "brand": "Own label",
        "price": 1.15,
        "currency": "EUR",
        "unit_price": "1.15 EUR/L",
        "promotion": {
          "mechanic": "2+1",
          "valid_until": "2026-11-15"
        },
        "url": "https://..."
      }
    ]
  }
}
import os, requests

FUNCTION_ID = os.environ["SHELFFEED_FUNCTION_ID"]
KEY = os.environ["SHELFFEED_KEY"]

def shelf(query):
    r = requests.post(
        f"https://api.notte.cc/functions/{FUNCTION_ID}/runs/start",
        headers={"Authorization": f"Bearer {KEY}"},
        json={
            "function_id": FUNCTION_ID,
            "variables": {"query": query},
        },
        timeout=180,
    )
    r.raise_for_status()
    return r.json()

# Your top SKUs, before the Monday meeting
for sku in ["halfvolle melk 1L", "koffie gemalen 500g"]:
    print(shelf(sku))
Working tool

Basket index: which banner is cheapest, and by how much?

Pick a market and a basket. Untick lines you do not range. Switch promotions off to see the regular-price position underneath.

Cheapest banner
line on promotion cheapest for that line Index: cheapest banner = 100. All prices in this tool are simulated in your browser, not read from retailers.
From the pricing desk

Less walking the aisles. More arguing about the right number.

"Our Monday file used to be whatever someone managed to photograph on Friday. Now a script fills it before I have coffee, and the meeting starts from the gaps instead of from doubts about the data."

Ines V.Pricing analyst, regional grocery chain, Portugal

"I do not need the whole market. I need my top 50 SKUs at four banners, with the promo mechanic, every morning. That was a custom study from our panel vendor. Here it is a loop."

Joris D.Revenue growth manager, food CPG, Belgium

"The honest part sold me: it is a request API and they say so. We call it on our schedule, store the results ourselves, and we know exactly when each price was read."

Pricing

Priced per call, not per fiscal year.

You pay for the reads you run. No seat licences, no minimum term.

Pilot
€0

Prove it on your own SKUs before you ask for budget.

  • 250 calls, one time
  • All 79 endpoints
  • One API key
  • Email support
Start a pilot
Analyst
€290 / month

A top-50 SKU watch across a handful of banners, read daily.

  • 10,000 calls per month
  • All 79 endpoints
  • Three API keys
  • Extra calls at €0.03 each
Get an API key
Category team
€990 / month

Full-category reads, several markets, several analysts.

  • 50,000 calls per month
  • Unlimited API keys
  • New banner requests reviewed first
  • Invoice billing and a named contact
Talk to us

Indicative prototype pricing, excluding VAT.

FAQ

What a careful analyst asks first.

Is this a live feed?

No. It is a request API. Each call opens the retailer's site and reads it at that moment, then returns JSON. Nothing is pushed to you and nothing changes between calls. If you want a daily series, schedule a daily call.

Do you keep price history?

Not for you. A call returns what is on the shelf page now. Write each response to your own warehouse with its read time and you build the history you need, in your own schema.

Are these store prices or online prices?

They are the prices the retailer publishes on its website or app. Some endpoints are store-aware: Pricez returns per-store prices, Carrefour Spain resolves a store from a postal code, and Pingo Doce lists nearby stores. Where a retailer prices differently in store and online, you get the online view.

How do I match a competitor's product to my SKU?

Matching stays with you. Endpoints return what the product page shows, typically name, brand, pack size and price. Carrefour UAE supports search by EAN. For other banners most teams keep a mapping table per SKU and search by name and pack size.

What happens when a retailer redesigns its site?

An endpoint can break until it is repaired. That is the nature of reading websites, and we would rather say it than promise otherwise. A failed run returns an error instead of stale or guessed data.

My main competitor is not on the list.

The list on this page is complete: 23 banners. Tell us the banner and what you need from it, such as search, product details or promotions, and we will tell you whether we can add it.

Does this replace our syndicated panel?

No. Panels measure sales and share. Shelffeed reads published shelf prices and promotions. It covers the weeks between panel deliveries and the banners your panel leaves out.

Next Monday, bring prices that were read that morning.

Start with your top 50 SKUs at the banners you already worry about. Keep the spreadsheet. Let a script fill it.