---
title: "Suggest similar products a shopper might have meant"
method: GET
path: "/v1/products/similar"
---

# Suggest similar products a shopper might have meant

`GET /v1/products/similar`

## Request

- Base URL: `https://supermcp.co.il`
- URL: `https://supermcp.co.il/v1/products/similar`
- Auth: none required

After a delivery basket priced the wrong SKU, search catalogue neighbours. Not cheaper nearby shelf substitutes — those are GET /v1/products/{id}/substitutes.

## Query parameters

- `q` string
- `product_id` string, uuid
- `limit` integer
- `city` string
- `near` string
- `location` string
- `radius_km` number

## Response `200`

OK

- object
  - `data` object
    - `query` string
    - `rejected` object, nullable
      - `id` string, uuid
      - `gtin` string, nullable
      - `name` string
      - `brand` string, nullable
      - `categoryL1` string, nullable
      - `categoryL2` string, nullable
      - `sizeQty` number, nullable
      - `sizeUnit` string, nullable
      - `pieceCount` number, nullable
      - `fromPrice` number, nullable: Lowest price at any storefront delivering to the requested location — a floor across shops, not a national price, so quote it as 'from ₪X'. The ordinary price, never a club or coupon rate. Null when no delivering storefront prices this product.
      - `pricedAtStorefronts` integer: How many delivering storefronts price it at all. 1 means fromPrice is a single shop's price rather than a market rate.
      - `pricedAtChains` integer: How many distinct chains, the better guide to how easy the product is to buy.
      - `normalizedUnitPrice` number, nullable: fromPrice per 100g / 100ml / piece, and THE field to compare on: a 100g pack can undercut a 125g one on pack price while costing more per gram. Results are sorted by it. Null when the package size could not be parsed.
      - `normalizedUnitBasis` 'per_100g' | 'per_100ml' | 'per_piece', nullable
    - `products` object[]
      - `id` string, uuid
      - `gtin` string, nullable
      - `name` string
      - `brand` string, nullable
      - `categoryL1` string, nullable
      - `categoryL2` string, nullable
      - `sizeQty` number, nullable
      - `sizeUnit` string, nullable
      - `pieceCount` number, nullable
      - `fromPrice` number, nullable: Lowest price at any storefront delivering to the requested location — a floor across shops, not a national price, so quote it as 'from ₪X'. The ordinary price, never a club or coupon rate. Null when no delivering storefront prices this product.
      - `pricedAtStorefronts` integer: How many delivering storefronts price it at all. 1 means fromPrice is a single shop's price rather than a market rate.
      - `pricedAtChains` integer: How many distinct chains, the better guide to how easy the product is to buy.
      - `normalizedUnitPrice` number, nullable: fromPrice per 100g / 100ml / piece, and THE field to compare on: a 100g pack can undercut a 125g one on pack price while costing more per gram. Results are sorted by it. Null when the package size could not be parsed.
      - `normalizedUnitBasis` 'per_100g' | 'per_100ml' | 'per_piece', nullable

## Other responses

- `400`: Bad request. Query parameters are validated strictly: a parameter this document does not list is rejected, and `details[].keys` names it. A misspelled filter used to be dropped silently, which answered a question nobody asked with a plausible list of products.
- `401`: Unauthorized
- `404`: Not found
- `429`: Rate limited

---

[API](https://skmtc.dev/supermcp/apis/super-mcp-api.md) · [All operations](https://skmtc.dev/supermcp/apis/super-mcp-api/llms.txt) · [OpenAPI document](https://skmtc.dev/supermcp/apis/super-mcp-api/revisions/f0dea9415b1c?raw)
