Skip to main content
Glama

WEM Price Compare

Server Details

Price comparison across partner retailers. Read-only, 90-day history, disclosed affiliate.

If you are the author of this connector, you can claim ownership by verifying the domain or GitHub account it belongs to. Claimed connector authors can inspect health checks, view analytics, and manage their listing.
Status
Healthy
Uptime
100.0% over 58 days
Last Tested
Transport
Streamable HTTP · MCP 2025-06-18
URL

TDQS

A4.1/5.0

Scored across 11 tools

Disambiguation3/5

Several tools return product, offer, or price information (search_products, semantic_search, lookup_products, get_product, compare_offers, find_lowest_price), so boundaries can blur despite detailed descriptions. The distinctions are usually explained, but an agent may still misselect for tasks like 'get offers for product X' or 'find a product'.

Naming Consistency4/5

Tool names use snake_case consistently and mostly follow a verb_noun pattern (compare_offers, get_product, search_products). Exceptions like semantic_search and find_lowest_price slightly break the pattern but remain readable.

Tool Count5/5

11 tools are well-scoped for a price-comparison server, covering search, lookup, comparison, verification, evidence, categories, and promotions without excessive bloat.

Completeness4/5

The surface covers the core price-comparison lifecycle: search/lookup, product details, offer comparison, lowest-price selection, price verification, and evidence receipts. Minor gaps exist, such as no full historical price series or direct category browsing beyond examples, but agents can work around them.

Available Tools

11 tools
compare_offersCompare retailer offers for one product
Read-only
Inspect

Lists the retailer offers WEM's catalogue holds for one product, current prices first and each group cheapest first, with WEM's 90-day price low (null when the product is held only in another currency). The product is found by barcode, catalogue slug or wem3.ai/pl/ URL, WEM ID, or a title (a model name, ASIN, MPN or merchant SKU) that must pass a relevance check; there is no live retailer search. A barcode, slug or WEM ID match is the product itself; a title match is inferred and marked so in identity. A marketplace offer priced far below the product's other offers is withheld and counted in filtered. When WEM does not hold the product, found is false and nextTool names search_products with a query.

ParametersJSON Schema
NameRequiredDescriptionDefault
gtinNoProduct barcode: EAN-13, UPC-A, EAN-8 or GTIN-14. The strongest identifier.
slugNoWEM catalogue slug, or a wem3.ai/pl/{slug} URL / host path. Hosts may pass either form.
titleNoProduct or model name, or an ASIN, MPN or merchant SKU (e.g. AF400UK). The weakest identifier: used only when no barcode, slug or WEM ID is given, and only if it passes a relevance check; otherwise `found` is false rather than a guess.
wem_idNoWEM ID (W + 10 Crockford characters + check). Active catalogue products only.
currencyNoISO 4217 code for the shopper's market. Default GBP. Decides which market's offers WEM returns from its catalogue, not just how the answer reads ; WEM does not infer the market from IP. When WEM holds the product only in another currency it says so rather than presenting a foreign listing as the answer.

Output Schema

ParametersJSON Schema
NameRequiredDescription
nextNoPresent when WEM's set of offers is thin. chrome_extension is a page that compares the same product on any retailer page, including shops without an affiliate programme.
foundYesFalse when the product is not in WEM’s catalogue. The rest of the fields below are then absent ; that does not mean the product is unavailable or unpriced. `unavailable` distinguishes an outage from a miss. `nextTool`, when present, names the next lookup.
linksNoThe links from `offers`, cheapest first, pre-formatted. Each opens the retailer’s page for the offer WEM priced; a retailer URL found elsewhere may be a different listing or price. The same links are in this array and, when a host renders one, in the card.
offersNoCurrent prices first (`priceStatus`), each group ascending by price; a stale or undated row is listed, never compared. Barcode, slug and WEM ID rows are the product. A title match is inferred; `identity.strength` says which.
reasonNoPresent only when `found` is false: which identifier missed, and why. When `unavailable` is true this describes the outage rather than a missing product ; it is the reason the lookup failed, not a fact about the product.
searchNoPresent when this result names no offer. `url` is WEM's results page for the query and `markdown` is the same link, pre-formatted. This tool reads the catalogue only, so an empty result here is not evidence the product is unavailable or unpriced.
sourceNo
productNo
rankingNoWhy the offers are in this order. Offers are ordered by price, lowest first; affiliate commission is not an input.
coverageNoPresent when surviving rows include a marketplace cluster at similar prices. That is not a retail floor — the cheapest marketplace listing is not the deal. The listings stay in the payload, each with its url. `next`, when present, is the Chrome extension page for shops WEM does not yet hold as partners.
currencyNo
degradedNoPresent when this call hit its time budget and skipped enrichment. The offers returned are COMPLETE — only the extras were dropped. A missing catalogue block or missing observed retailers does not mean WEM holds nothing, and no retry is needed.
filteredNoOffers of this product WEM held back, tallied by reason. "Priced far below this product’s other offers" is a marketplace listing under 40% of what the product sells for elsewhere — the shape of a counterfeit, a part or a mislisted variant. Those prices are not in `offers`, `lowPrice`, `links`, `summary` or `priceHistory.low`: none is the cheapest, a deal or the 90-day low. The tally says how many were held back.
identityNoHow the shopper’s words reached this product. On `inferred`, WEM matched it by name (not by barcode) and the identity is not confirmed, even when `identityBasis` is `barcode`; on `exact`, the barcode itself resolved it.
lowPriceNoLowest CURRENT price in `offers` (read within 14 days). Null when no price is current or WEM holds none it may quote ; it is never taken from a stale or undated row, or from `unpriced`.
nextToolNoPresent only when `found` is false. It names `search_products` and the query. A named model that misses the catalogue is the ordinary case.
unpricedNoListings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. The row carries `priceNote` (e.g. "See price at Amazon") in place of a figure. No price is stated, estimated or compared for one; it is not the cheapest and is not counted in a lowest price or a saving.
highPriceNoHighest current price in `offers`; null with lowPrice.
sameModelNoPresent only when the maker's own page says another model code is this product and a person at WEM has checked it. These are NOT offers for the product asked about: they are not part of `offers`, and none is this product's lowest price or the best deal. On verify_offer they are not part of the check: `verdict`, `cheapest`, `betterBy`, `summary` and the receipt are about the product asked about, and a cheaper sister code never makes the claimed price wrong. `summary` is written to be quoted as it is. `maker.host` is the source of the claim. `url` is WEM's comparison for that model, not a shop. When `relation` is `differs`, the `differences` are what the maker says differs, and its price is not a saving. Absent is not evidence that no equivalent exists.
disclosureNoWEM’s affiliate disclosure for this answer, written to be quoted as it is. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. A version from an earlier answer may not fit this one: a row marked `affiliate: false` earns WEM nothing.
unavailableNoPresent and true only when WEM could not reach its catalogue at all. `found` is false for the same reason it is on an ordinary miss, so the two are indistinguishable without this flag. When it is set, WEM does not know whether it holds the product. The lookup could not be completed; it does not mean WEM has no offers or no price for it. `nextTool` is still present.
priceHistoryNoThe 90-day low, for telling a real discount from a repackaged one.
identityBasisNoHow this product’s offers are grouped — NOT how the shopper’s words found the product; that is `identity`. `barcode`: the product carries a GTIN, so every offer here is that same item. `curated-grouping`: it carries none, and the grouping is an inference. This field does not make a result a barcode match: when `identity.strength` is `inferred`, WEM matched the product by name.
lastConfirmedAtNoWhen WEM last actually read any price in this answer. Null means none of them can be dated, so the answer is not current.
compare_productsCompare several products
Read-only
Inspect

Lays 2 to 5 listings from earlier search results side by side in comparison: each listing's price and currency, and its rating, shipping and features where the retailer source supplies them (many listings carry none). Each item needs the listing's provider and its id as product_id. Listings that cannot be found are left out, and fewer than two found is an error. Prices stay in each listing's own currency.

ParametersJSON Schema
NameRequiredDescriptionDefault
productsYes2 to 5 listings, each with `provider` and `product_id` as given in a search result.

Output Schema

ParametersJSON Schema
NameRequiredDescription
countYes
comparisonYes
disclosureYesWEM’s affiliate disclosure for this answer, written to be quoted as it is. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. A version from an earlier answer may not fit this one: a row marked `affiliate: false` earns WEM nothing.
find_lowest_priceFind the lowest listed price
Read-only
Inspect

Picks one listing for a kind of product within the shopper's constraints, from WEM's catalogue and a live retailer search (a current catalogue match answers without the live search). Candidates are first filtered to plausible matches, so an accessory, another size, an out-of-stock listing or one priced far below the product's other offers is not picked. With no priorities, or with cheapest first, the lowest price wins; best_rated, free_shipping and fastest (has a delivery estimate) are weighed in the order given, where listings carry ratings or delivery details, and can outrank a lower price. WEM's commission is not a factor. recommendation is null with a reason when nothing matched confidently, when the matches differ in size, or when only stale prices remain; when coverage.kind is marketplace_only it is null but alternatives still lists the listings. recommendation.verified is true when WEM has recently observed that price at the retailer.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesOne kind of product or product: a name, barcode, ASIN, WEM ID or wem3.ai/pl URL. A single query, not a list.
currencyNoISO 4217 code to quote in. Default GBP. Offers in other currencies are withheld, never converted. Pass the shopper's market explicitly — WEM does not infer currency or retailer market from IP.
conditionNoSame effect as include_used: "any", "used" or "refurbished" also includes used and refurbished listings; any other value means new only.
max_priceNoBudget cap, in `currency`.
prioritiesNoWhat matters most, in order. cheapest: lowest price. best_rated: higher rating. free_shipping: free delivery. fastest: states a delivery estimate. Weighed only where listings carry those details.
include_usedNoIf true, include used and refurbished listings. Default false — a used item is a different good, not a cheaper one.

Output Schema

ParametersJSON Schema
NameRequiredDescription
nextNoPresent when WEM's set of offers is thin. chrome_extension is a page that compares the same product on any retailer page, including shops without an affiliate programme.
scoreNoInternal ranking score. Not a price and not a rating — do not quote it.
reasonYesWhy this was picked, or why nothing was.
searchNoPresent when this result names no offer. `url` is WEM's results page for the query and `markdown` is the same link, pre-formatted. WEM searches retailers live on that page, including shops it holds no affiliate programme with, so an empty or withheld result here is not evidence the product is unavailable or unpriced.
partialNoTrue when the live retailer fan-out hit its 3-second budget and some providers had not answered. The recommendation is the lowest among those that did. Do not call it the market floor, and do not retry automatically.
coverageNoPresent when surviving rows include a marketplace cluster at similar prices. That is not a retail floor — the cheapest marketplace listing is not the deal. The listings stay in the payload, each with its url. `next`, when present, is the Chrome extension page for shops WEM does not yet hold as partners.
degradedNoPresent when this call hit its time budget and skipped enrichment. The offers returned are COMPLETE — only the extras were dropped. A missing catalogue block or missing observed retailers does not mean WEM holds nothing, and no retry is needed.
filteredNoWithheld candidates tallied by reason (e.g. accessories, another model, a bundle or multipack, a replica, a listing priced far below the product’s other offers). Report this count rather than implying the search was exhaustive, and never quote a withheld listing’s price as the cheapest or as a deal.
disclosureNoWEM’s affiliate disclosure for this answer, written to be quoted as it is. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. A version from an earlier answer may not fit this one: a row marked `affiliate: false` earns WEM nothing.
alternativesNoListings still worth showing, including when recommendation is null.
catalogMatchNoOffers WEM holds under one catalogue product. Check `identityBasis`: on `barcode` the product carries a GTIN and every offer here is that same item, so prefer them and cite their prices over anything in `products`. On `curated-grouping` the product carries no barcode, the grouping is an inference like any title match, and a cheaper row in `products` may well be the same item — see `cheaperElsewhere`. Whether the shopper’s words reached this product by barcode or by name is `identity`, a separate question: on `inferred`, say WEM matched it by name.
recommendationYesThe single lowest-priced plausible match, or null when nothing matched confidently.
liveSearchSkippedNoTrue when a catalogue hit answered the question without spending retailer API quota.
pending_providersNoProviders still running when the budget expired. Present only with partial. Their prices are not in this answer.
get_categoriesList shopping categoriesA
Read-only
Inspect

Lists the six broad shopping categories WEM covers (electronics, fashion, beauty, home, sports, collectibles), each with example products, the shops WEM has read a price from in the last 14 days (busiest first, with how many shops there are in all) and the default currency (GBP). Use it to help a shopper narrow a vague request. It returns no prices, the category names are labels for the shopper, not filter values, and a shop on the list is not a promise that WEM holds a given product there: compare_offers says which shops WEM has for one product.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
currencyYes
providersYesShops WEM has read a price from in the last 14 days, busiest first, at most 40: one row per shop, with how many of its products WEM read. Say which shops WEM covers from this list, never from a shop's absence: it is not every shop WEM has ever held, and a shop on it may not sell the product the shopper wants (compare_offers says which shops WEM holds for one product).
shopCountNoHow many shops WEM read a price from in the last 14 days, listed or not. Null with an empty `providers` means the list could not be read just now, not that WEM has no shops.
categoriesYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, non-destructive), and the description adds substantive behavioral context beyond them: it returns no prices, category names are labels rather than filter values, and a listed shop does not guarantee product availability. These are non-obvious caveats an agent would otherwise mis-infer.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Content is front-loaded with what the tool returns, followed by usage and caveats. The second sentence is a dense run-on packing three separate caveats, which slightly hurts readability but every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, yet the description still frames the semantics an agent needs (no prices, labels not filters). For a zero-param, read-only listing tool, nothing relevant is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline is 4; there is nothing for the description to disambiguate. It correctly spends no words on parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Lists the six broad shopping categories WEM covers') and enumerates the actual content (examples, shops with prices read in last 14 days, default currency). It also names the sibling it is not, compare_offers, so an agent can separate the two without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use ('Use it to help a shopper narrow a vague request') and an implicit when-not by routing single-product shop questions to compare_offers. Nothing is left to inference about which tool to pick.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_evidence_receiptLook up a verification receipt by idA
Read-only
Inspect

Fetches an evidence receipt by its id (wem-evr- followed by 32 hex characters), as issued with a verify_offer result. Returns the receipt's fields: verdict, observed_at, source, amount, currency and amount_minor, identity_method, verifier, standardVersion and issuedAt, with signed true and an HMAC signature when WEM signed it. It holds the citation, not the product's offers. A receipt issued moments ago may not be fetchable yet.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesReceipt id (wem-evr- followed by 32 hex characters), as returned in a verify_offer result's receipt.id.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYes
amountNo
signedYes
sourceYes
verdictNo
currencyNo
issuedAtNo
verifierYes
signatureNo
observed_atYes
amount_minorNo
identity_methodNo
standardVersionYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/no-destructive/closed-world, but the description adds real behavioral context: the signed/HMAC signature condition, the specific field set returned, and the eventual-consistency caveat that a just-issued receipt may not be fetchable yet. That freshness warning is the kind of trait an annotation cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the or, and every sentence carries information — provenance, payload, scope boundary, freshness caveat. The mid-sentence field enumeration is long and partially redundant with the output schema, which keeps it from a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter, read-only lookup with an output schema present, the description covers everything the agent needs: id provenance and format, what the payload contains, the signed-signature condition, and the not-yet-fetchable edge case. Nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single id parameter is already fully documented there, so the baseline is 3. The description adds only marginal value by repeating the id shape and noting the value originates from verify_offer's receipt.id.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource combination ('Fetches an evidence receipt by its id') and pins down the id format. It also ties the tool to its issuing sibling ('as issued with a verify_offer result'), so an agent can place it relative to verify_offer without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clear context: use it when you hold a receipt id produced by verify_offer, and the clarifying line 'It holds the citation, not the product's offers' steers an agent away from expecting offer data. It never states an explicit when-not or names a competing lookup tool, so it falls short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_productGet one product
Read-only
Inspect

Returns one product's details. Given provider and product_id from a search result, it returns that listing as its retailer source supplies it (title, price and link, with rating, shipping or features where the source has them); when the source cannot be reached it falls back to WEM's catalogue record of the listing, and an unknown listing is an error. Given wem_id, it returns that catalogue product with the retailer offers WEM holds for it.

ParametersJSON Schema
NameRequiredDescriptionDefault
wem_idNoWEM ID (W + 10 Crockford characters + check). Active catalogue products only.
providerNoRetailer source of the listing, as given in the search result (e.g. "amazon", "awin").
product_idNoThe listing's `id` from the search result.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idNo
urlYesWEM tracked link to the retailer page for this offer. WEM never takes payment.
brandNo
imageNo
priceNoIndicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: the note stands in place of a figure.
titleNo
badgesNo
ratingNo
sellerNo
channelNoretailer is a named shop (Boots, Currys). marketplace is AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers.
inStockNo
currencyNoISO 4217 code.
featuresNo
providerNoRetailer slug, e.g. "amazon", "currys".
shippingNoDelivery as the retailer stated it: `free`, or `cost` in the offer currency. Absent or null means not stated: say delivery is shown at the shop, never that it is free. Offers are ordered by item price; add a stated cost before calling one cheaper delivered.
affiliateNoFalse when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. It is still a real offer, and its link is not affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` states whether all, some or none of the links are tracked.
priceNoteNoPresent only when `price` is null: the words that stand in its place, e.g. "See price at Amazon". An Amazon price is shown only when Amazon’s API supplied it just now.
unitPriceNoPrice per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. Across sizes, value is compared on these, not on the prices: a smaller size is not cheaper because its price is lower. It reads beside the price ("£29.95, £99.83 per 100ml"). Absent does not mean the price is per unit.
disclosureYesWEM’s affiliate disclosure for this answer, written to be quoted as it is. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. A version from an earlier answer may not fit this one: a row marked `affiliate: false` earns WEM nothing.
descriptionNo
priceStatusNo`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Those two read as "last seen £X on 8 Sep" or "price not dated", come after the current ones, and are not compared. Absent on a row a provider answered just now.
reviewCountNo
priceQualifierNoPresent when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. It reads as "from £X"; it is not the item's price or the cheapest. Absent means the price is firm for the row as described.
lookup_productsLook up several products by barcode
Read-only
Inspect

Looks up to 20 product identifiers in one call: barcodes (EAN/UPC/GTIN), Amazon ASINs, WEM IDs, catalogue slugs or wem3.ai/pl URLs. Each row has a status: found (WEM's catalogue holds it; the row gives its number of retailer offers, the lowest current price at a named retailer in the shopper's currency, a marketplace low where there is one, and a link to WEM's product page), not_found (WEM does not hold it yet, which says nothing about whether it exists or has a price), unrecognised (not an identifier, such as a product name) or not_checked (not reached in this call, so not a miss). Identifiers beyond 20 are counted in overLimit.

ParametersJSON Schema
NameRequiredDescriptionDefault
currencyNoISO 4217 code for the shopper's market. Default GBP. Lowest prices are quoted in this currency only, never converted; a product WEM holds only in another currency comes back found with lowPrice null and heldInCurrencies set.
identifiersYes1-20 barcodes (EAN-13, UPC-A, EAN-8, GTIN-14), Amazon ASINs, WEM IDs, catalogue slugs or wem3.ai/pl URLs. Mixed kinds are fine; a comma-separated string is also accepted. Duplicates are looked up once. Each entry must be the identifier alone: not a product name, and not a name with a barcode in it.

Output Schema

ParametersJSON Schema
NameRequiredDescription
nextNoThe WEM tool that answers the follow-up question, and what to pass it.
linksYesThe WEM product-page links for found rows, pre-formatted to quote. Give these to the user when you name a found product.
countsYes
resultsYes
currencyYes
disclosureYesWEM’s affiliate disclosure for this answer, written to be quoted as it is. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. A version from an earlier answer may not fit this one: a row marked `affiliate: false` earns WEM nothing.
unavailableNoPresent and true when WEM could not reach its catalogue. Rows it could not check are not_checked, not not_found — do not report them as products WEM lacks.
overLimitNoteNo
search_productsSearch products across retailers
Read-only
Inspect

Searches WEM's catalogue and its connected retailer sources for products matching a query. The query can be a product name or an identifier: a barcode (EAN/UPC/GTIN), an Amazon ASIN, an MPN, a merchant SKU that names one catalogue product, a WEM ID or a wem3.ai/pl/{slug} URL, and several identifiers may be comma-separated. When the query identifies a product WEM holds, a catalogMatch block (catalogMatches for several) gives that product's retailer offers; a barcode, ASIN, WEM ID or URL match skips the live retailer search, so products then holds catalogue offers only. Barcode, ASIN and slug matches are identity-resolved; MPN, SKU and title matches are inferred. Accessories, bundles, other models and listings priced far below the product's other offers are withheld and counted by reason in filtered.

ParametersJSON Schema
NameRequiredDescriptionDefault
gtinNoA product barcode (EAN/UPC/GTIN) the host already has. When given, retailer sources are searched by this barcode instead of by the query words.
limitNoHow many listings to request from each retailer source (default 10, max 30). The combined list can hold more.
queryYesA product name, or an identifier: barcode (EAN/UPC/GTIN), ASIN, MPN, merchant SKU, WEM ID or wem3.ai/pl URL. Several identifiers may be comma-separated.
sort_byNoOrder of the live retailer listings (default relevance). Not applied when the query identifies a product.
categoryNoOptional. Keeps only live retailer listings whose own category name matches this text exactly; catalogue matches ignore it. Leave it out unless the shopper names a retailer's category.
currencyNoISO 4217 code for the shopper's market. Default GBP. Results and price filters use this currency.
max_priceNoHighest price to include, in `currency`. Applies to retailer listings, not to `catalogMatch`.
min_priceNoLowest price to include, in `currency`. Applies to retailer listings, not to `catalogMatch`.
providersNoRetailer sources to search live, e.g. ["amazon", "awin"]. Omit for all. Catalogue matches are not limited by it.

Output Schema

ParametersJSON Schema
NameRequiredDescription
nextNoPresent when WEM's set of offers is thin. chrome_extension is a page that compares the same product on any retailer page, including shops without an affiliate programme.
queryYes
searchNoPresent when this result names no offer. `url` is WEM's results page for the query and `markdown` is the same link, pre-formatted. WEM searches retailers live on that page, including shops it holds no affiliate programme with, so an empty or withheld result here is not evidence the product is unavailable or unpriced.
partialNoTrue when the live retailer fan-out hit its 3-second budget and some providers had not answered. The rows returned are real; the market may be wider. Ask again for the rest.
coverageNoPresent when surviving rows include a marketplace cluster at similar prices. That is not a retail floor — the cheapest marketplace listing is not the deal. The listings stay in the payload, each with its url. `next`, when present, is the Chrome extension page for shops WEM does not yet hold as partners.
degradedNoPresent when this call hit its time budget and skipped enrichment. The offers returned are COMPLETE — only the extras were dropped. A missing catalogue block or missing observed retailers does not mean WEM holds nothing, and no retry is needed.
filteredNoWithheld candidates tallied by reason (e.g. accessories, another model, a bundle or multipack, a replica, a listing priced far below the product’s other offers). Report this count rather than implying the search was exhaustive, and never quote a withheld listing’s price as the cheapest or as a deal.
productsYes
unpricedNoListings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. The row carries `priceNote` (e.g. "See price at Amazon") in place of a figure. No price is stated, estimated or compared for one; it is not the cheapest and is not counted in a lowest price or a saving.
disclosureYesWEM’s affiliate disclosure for this answer, written to be quoted as it is. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. A version from an earlier answer may not fit this one: a row marked `affiliate: false` earns WEM nothing.
sizeSpreadNoPresent when the returned rows are different sizes and the query named none, so price ordering is meaningless: the cheapest row is cheapest because it is less of the product. Do NOT name a cheapest, a lowest price, or a best deal across these rows. The size belongs beside every price. Where rows carry `unitPrice`, that is the like-for-like figure, and it is the figure to rank on when the question is which is better value. The rows are real listings, each with its url.
catalogMatchNoOffers WEM holds under one catalogue product. Check `identityBasis`: on `barcode` the product carries a GTIN and every offer here is that same item, so prefer them and cite their prices over anything in `products`. On `curated-grouping` the product carries no barcode, the grouping is an inference like any title match, and a cheaper row in `products` may well be the same item — see `cheaperElsewhere`. Whether the shopper’s words reached this product by barcode or by name is `identity`, a separate question: on `inferred`, say WEM matched it by name.
totalResultsYesCount of products returned, after weak matches were withheld.
catalogMatchesNoPresent when the query was a comma-separated batch of identifiers and more than one catalogue product resolved. Each entry has the same shape as `catalogMatch`. Prefer barcode-basis blocks; treat MPN/SKU/title blocks as inferred.
pending_providersNoProviders still running when the budget expired. Present only with partial.
search_promotionsFind current retailer promotionsA
Read-only
Inspect

Lists current promotions (sales and offers) that retailers in WEM's Awin affiliate programmes have published, for the shopper's market. Filter by merchant or by words in the offer. Each row gives the offer, its dates and a tracked link. A promotion is not a price, and it is not a discount on a product unless its terms say it covers that product. Checkout codes are shown only where the retailer's programme lets WEM publish them; other matching promotions are counted by reason in withheld, and a withheld code may still exist. An empty result covers only these programmes, not every offer a retailer runs.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax promotions to return (default 10, max 25).
queryNoWords that must appear in the offer, e.g. "hoverboard" or "free delivery".
currencyNoISO 4217 code for the shopper's market: GBP (default) or USD. Promotions are regional, so this decides which market's offers are read.
merchantNoRetailer name, e.g. "iHoverboard". Omit for every retailer.

Output Schema

ParametersJSON Schema
NameRequiredDescription
moreNoFurther matching promotions beyond `limit`.
noteNo
countYes
linksYesThe tracked links from `promotions`, pre-formatted. Give these to the user when you name a promotion.
marketNoISO country code the promotions were read for.
reasonNoPresent only when no promotion is shown. None of these means the retailer has no offer on — not_configured and upstream_error mean WEM could not look.
searchNoPresent when this result names no offer. `url` is WEM's results page for the query and `markdown` is the same link, pre-formatted. WEM searches retailers live on that page, including shops it holds no affiliate programme with, so an empty or withheld result here is not evidence the product is unavailable or unpriced.
currencyYes
withheldNoMatching promotions WEM did not show, counted by reason: notPublishable (a checkout code or offer the retailer’s programme does not let WEM publish; the code may well exist), notJoined, notActive, outsideMarket, noTrackedLink, otherPublisherLink, incompleteRecord.
disclosureYesWEM’s affiliate disclosure for this answer, written to be quoted as it is. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. A version from an earlier answer may not fit this one: a row marked `affiliate: false` earns WEM nothing.
promotionsYesEnding soonest first. Each row is one live promotion WEM is allowed to show.
withheldNoteNoQuote this rather than paraphrase it when codes were withheld.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover the safety profile (readOnly, openWorld, non-destructive), and the description adds substantial operational context: checkout codes appear only where the retailer's programme permits publication, non-publishable matches are counted in `withheld` and may still exist, and an empty result covers only these programmes rather than all a retailer runs. These are exactly the nuances an agent cannot infer from structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with what the tool returns, then constraints, then edge cases; nearly every sentence carries distinct information. Slightly long at six sentences, but no sentence is pure filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given an output schema exists, the description needn't re-explain row format, yet it usefully flags that each row gives the offer, dates and a tracked link, and it covers the `withheld` edge case and empty-result semantics. Nothing needed to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so all four parameters are already documented, and the description largely restates them (currency governs the market read, merchant omitted means every retailer). It adds no new syntax or format detail beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (lists) and resource (current promotions from Awin affiliate programmes), scoped to the shopper's market, and explicitly distinguishes itself from pricing tools with 'A promotion is not a price, and it is not a discount on a product.' An agent can separate this from search_products, compare_offers or find_lowest_price without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usable context is given: filter by merchant or words in the offer, and the boundaries ('not a price', 'not a discount unless terms say it covers that product') tell the agent when this tool is inappropriate. It stops short of naming a sibling to use instead, so it doesn't reach the explicit alternative-routing of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

verify_offerCheck whether a price claim is trueInspect

Checks a price someone has claimed for a product against the prices WEM has itself observed at retailers (recent readings, within a small tolerance; not a live quote), and reports the cheapest observed offer. Identify the product by gtin (strongest), slug, wem_id, provider + externalId, or title (weakest, relevance-checked). retailer names the shop the claim is about; without it the nearest observed price at any shop is checked. Only offers in the claim's currency are compared. Verdicts: confirmed (WEM observed that price there), price_moved (WEM last observed a different price there), not_at_retailer (WEM has no observed price there, though it may hold a feed price), no_claim (no price given; the offers are returned), unknown_product (the product could not be resolved, or WEM holds no observed price for it in that currency). unknown_product means the claim could not be checked, not that it is false. lastConfirmedAt says when WEM last observed a price in the answer, or is null. Each call records an evidence receipt, whose id can be cited later.

ParametersJSON Schema
NameRequiredDescriptionDefault
gtinNoProduct barcode: EAN-13, UPC-A, EAN-8 or GTIN-14. Strongest identifier.
slugNoWEM canonical slug, as in wem3.ai/pl/{slug}.
priceNoThe price being claimed. Omit to ask only for the observed offers.
titleNoProduct title. The weakest identifier: used only when no id is given, and only if it passes a relevance check.
wem_idNoWEM ID (W + 10 Crockford characters + check). Active catalogue products only.
currencyNoISO 4217 code for the claimed price. Default GBP. Only offers in this currency are compared.
providerNoWith externalId: the retailer source of a listing that identifies the product, e.g. 'amazon'. To name the shop the claim is about, use `retailer`.
retailerNoThe shop the price was claimed at, as a slug or display name. Omit to compare against every shop.
externalIdNoThat listing's own id (an ASIN, or the shop's own item number). Use with provider.

Output Schema

ParametersJSON Schema
NameRequiredDescription
offersYesPrices WEM holds for this product, including indicative ones and shops it has no affiliate programme with yet. When `cheapest` is null, still show these rows and their links: they are a comparison, not a verification. Do not call them confirmed, and do not name a verified cheapest.
sourceYes
productNo
receiptYesCitation handle for this answer. Field names follow ACP suggested_price (observed_at, source, amount). signed is true only when WEM issued an HMAC with a dedicated key; otherwise false (fail closed).
summaryYesWritten so quoting it verbatim is accurate. Prefer quoting it to paraphrasing the verdict code.
verdictYes
betterByNoSaving from taking `cheapest` over the claimed price. Never negative.
cheapestNo
identityNoHow the product was identified — a separate question from whether the price checks out. Never present a `strength` of "inferred" as a verified identity.
sameModelNoPresent only when the maker's own page says another model code is this product and a person at WEM has checked it. These are NOT offers for the product asked about: they are not part of `offers`, and none is this product's lowest price or the best deal. On verify_offer they are not part of the check: `verdict`, `cheapest`, `betterBy`, `summary` and the receipt are about the product asked about, and a cheaper sister code never makes the claimed price wrong. `summary` is written to be quoted as it is. `maker.host` is the source of the claim. `url` is WEM's comparison for that model, not a shop. When `relation` is `differs`, the `differences` are what the maker says differs, and its price is not a saving. Absent is not evidence that no equivalent exists.
disclosureYesWEM’s affiliate disclosure for this answer, written to be quoted as it is. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. A version from an earlier answer may not fit this one: a row marked `affiliate: false` earns WEM nothing.
resolvedByNoWhich identifier resolved the product.
claimMatchedNo
comparisonSetNoHow wide the comparison behind `cheapest` was. `exhaustive` is always false: WEM does not see every retailer, so `cheapest` is the lowest offer WEM holds, never the lowest that exists. Relay it as such.
lastConfirmedAtNoWhen WEM last read a price among the offers compared — the freshness of this answer. Null means none of them carries a dated reading: say the prices are undated.
toleranceAppliedNo

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updates
    • Changedcompare_offers1 field changed
      • changedOutput schema / properties / coverage / properties / provider / description
        Previous value: -"aliexpress, or marketplace when mixed."New value: +"The marketplace (e.g. aliexpress), or marketplace when mixed."
    • Changedfind_lowest_price1 field changed
      • changedOutput schema / properties / coverage / properties / provider / description
        Previous value: -"aliexpress, or marketplace when mixed."New value: +"The marketplace (e.g. aliexpress), or marketplace when mixed."
    • Changedlookup_products1 field changed
      • changedOutput schema / properties / results / items / properties / marketplaceLowPrice / description
        Previous value: -"Cheapest marketplace listing (AliExpress…), present only when it undercuts lowPrice or no named retailer holds the product. A seller’s price, not a retail floor: never quote it as the product’s price or the cheapest."New value: +"Cheapest marketplace listing (AliExpress, Temu…), present only when it undercuts lowPrice or no named retailer holds the product. A seller’s price, not a retail floor: never quote it as the product’s price or the cheapest."
    • Changedsearch_products1 field changed
      • changedOutput schema / properties / coverage / properties / provider / description
        Previous value: -"aliexpress, or marketplace when mixed."New value: +"The marketplace (e.g. aliexpress), or marketplace when mixed."
  2. 8 tool updates
    • Changedcompare_offers3 fields changed
      • changedOutput schema / properties / coverage / properties / provider / description
        Previous value: -"ebay, aliexpress, or marketplace when mixed."New value: +"aliexpress, or marketplace when mixed."
      • changedOutput schema / properties / offers / items / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / offers / items / properties / provider / description
        Previous value: -"Retailer slug, e.g. \"ebay\", \"currys\"."New value: +"Retailer slug, e.g. \"amazon\", \"currys\"."
    • Changedcompare_products2 fields changed
      • changedOutput schema / properties / comparison / items / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / comparison / items / properties / provider / description
        Previous value: -"Retailer slug, e.g. \"ebay\", \"currys\"."New value: +"Retailer slug, e.g. \"amazon\", \"currys\"."
    • Changedfind_lowest_price7 fields changed
      • changedOutput schema / properties / alternatives / items / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / alternatives / items / properties / provider / description
        Previous value: -"Retailer slug, e.g. \"ebay\", \"currys\"."New value: +"Retailer slug, e.g. \"amazon\", \"currys\"."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / provider / description
        Previous value: -"Retailer slug, e.g. \"ebay\", \"currys\"."New value: +"Retailer slug, e.g. \"amazon\", \"currys\"."
      • changedOutput schema / properties / coverage / properties / provider / description
        Previous value: -"ebay, aliexpress, or marketplace when mixed."New value: +"aliexpress, or marketplace when mixed."
      • changedOutput schema / properties / recommendation / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / recommendation / properties / provider / description
        Previous value: -"Retailer slug, e.g. \"ebay\", \"currys\"."New value: +"Retailer slug, e.g. \"amazon\", \"currys\"."
    • Changedget_product3 fields changed
      • changedInput schema / properties / provider / description
        Previous value: -"Retailer source of the listing, as given in the search result (e.g. \"ebay\", \"awin\")."New value: +"Retailer source of the listing, as given in the search result (e.g. \"amazon\", \"awin\")."
      • changedOutput schema / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / provider / description
        Previous value: -"Retailer slug, e.g. \"ebay\", \"currys\"."New value: +"Retailer slug, e.g. \"amazon\", \"currys\"."
    • Changedlookup_products1 field changed
      • changedOutput schema / properties / results / items / properties / marketplaceLowPrice / description
        Previous value: -"Cheapest marketplace listing (eBay, AliExpress…), present only when it undercuts lowPrice or no named retailer holds the product. A seller’s price, not a retail floor: never quote it as the product’s price or the cheapest."New value: +"Cheapest marketplace listing (AliExpress…), present only when it undercuts lowPrice or no named retailer holds the product. A seller’s price, not a retail floor: never quote it as the product’s price or the cheapest."
    • Changedsearch_products8 fields changed
      • changedInput schema / properties / providers / description
        Previous value: -"Retailer sources to search live, e.g. [\"ebay\", \"awin\"]. Omit for all. Catalogue matches are not limited by it."New value: +"Retailer sources to search live, e.g. [\"amazon\", \"awin\"]. Omit for all. Catalogue matches are not limited by it."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / provider / description
        Previous value: -"Retailer slug, e.g. \"ebay\", \"currys\"."New value: +"Retailer slug, e.g. \"amazon\", \"currys\"."
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / provider / description
        Previous value: -"Retailer slug, e.g. \"ebay\", \"currys\"."New value: +"Retailer slug, e.g. \"amazon\", \"currys\"."
      • changedOutput schema / properties / coverage / properties / provider / description
        Previous value: -"ebay, aliexpress, or marketplace when mixed."New value: +"aliexpress, or marketplace when mixed."
      • changedOutput schema / properties / products / items / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / products / items / properties / provider / description
        Previous value: -"Retailer slug, e.g. \"ebay\", \"currys\"."New value: +"Retailer slug, e.g. \"amazon\", \"currys\"."
    • Changedsemantic_search4 fields changed
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / provider / description
        Previous value: -"Retailer slug, e.g. \"ebay\", \"currys\"."New value: +"Retailer slug, e.g. \"amazon\", \"currys\"."
      • changedOutput schema / properties / products / items / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / products / items / properties / provider / description
        Previous value: -"Retailer slug, e.g. \"ebay\", \"currys\"."New value: +"Retailer slug, e.g. \"amazon\", \"currys\"."
    • Changedverify_offer2 fields changed
      • changedInput schema / properties / externalId / description
        Previous value: -"That listing's own id (ASIN, eBay item number). Use with provider."New value: +"That listing's own id (an ASIN, or the shop's own item number). Use with provider."
      • changedInput schema / properties / provider / description
        Previous value: -"With externalId: the retailer source of a listing that identifies the product, e.g. 'amazon' or 'ebay'. To name the shop the claim is about, use `retailer`."New value: +"With externalId: the retailer source of a listing that identifies the product, e.g. 'amazon'. To name the shop the claim is about, use `retailer`."
  3. 1 tool update
    • Changedcompare_offers4 fields changed
      • changedOutput schema / description
        Previous value: -"The retailer offers WEM holds for one catalogue product, current prices first and each group cheapest first. When `found` is false WEM simply does not hold this product yet — that is a normal answer, not a failure, and it says nothing about whether the product exists or what it costs. `nextTool` then names `search_products` and the query. An empty catalogue result is not a statement that the product is unavailable or unpriced; the live retailer search is a separate lookup and routinely finds supply this catalogue has not ingested."New value: +"The retailer offers WEM holds for one catalogue product, current prices first and each group cheapest first. When `found` is false WEM simply does not hold this product yet — that is a normal answer, not a failure, and it says nothing about whether the product exists or what it costs. `nextTool` then names `search_products` and the query. An empty catalogue result is not a statement that the product is unavailable or unpriced."
      • changedOutput schema / properties / nextTool / description
        Previous value: -"Present only when `found` is false. It names `search_products` and the query. A named model that misses the catalogue is the ordinary case; the live search is a separate lookup."New value: +"Present only when `found` is false. It names `search_products` and the query. A named model that misses the catalogue is the ordinary case."
      • changedOutput schema / properties / search / description
        Previous value: -"Present when this result names no offer. `url` is WEM's results page for the query and `markdown` is the same link, pre-formatted. WEM searches retailers live on that page, including shops it holds no affiliate programme with, so an empty or withheld result here is not evidence the product is unavailable or unpriced."New value: +"Present when this result names no offer. `url` is WEM's results page for the query and `markdown` is the same link, pre-formatted. This tool reads the catalogue only, so an empty result here is not evidence the product is unavailable or unpriced."
      • changedOutput schema / properties / unavailable / description
        Previous value: -"Present and true only when WEM could not reach its catalogue at all. `found` is false for the same reason it is on an ordinary miss, so the two are indistinguishable without this flag. When it is set, WEM does not know whether it holds the product. The lookup could not be completed; it does not mean WEM has no offers or no price for it. `nextTool` is still present, because the live retailer search does not depend on the catalogue."New value: +"Present and true only when WEM could not reach its catalogue at all. `found` is false for the same reason it is on an ordinary miss, so the two are indistinguishable without this flag. When it is set, WEM does not know whether it holds the product. The lookup could not be completed; it does not mean WEM has no offers or no price for it. `nextTool` is still present."
  4. 1 tool update
    • Changedget_categories3 fields changed
      • changedOutput schema / properties / providers / description
        Previous value: -"Retailers currently enabled. WEM compares only feeds it is licensed to use."New value: +"Shops WEM has read a price from in the last 14 days, busiest first, at most 40: one row per shop, with how many of its products WEM read. Say which shops WEM covers from this list, never from a shop's absence: it is not every shop WEM has ever held, and a shop on it may not sell the product the shopper wants (compare_offers says which shops WEM holds for one product)."
      • addedOutput schema / properties / providers / items / properties / products
        Added value: +{
        +  "description": "Products WEM read a price for at this shop in the last 14 days.",
        +  "type": "integer"
        +}
      • addedOutput schema / properties / shopCount
        Added value: +{
        +  "description": "How many shops WEM read a price from in the last 14 days, listed or not. Null with an empty `providers` means the list could not be read just now, not that WEM has no shops.",
        +  "type": [
        +    "integer",
        +    "null"
        +  ]
        +}
  5. 6 tool updates
    • Changedcompare_offers1 field changed
      • addedOutput schema / properties / offers / items / properties / shipping / description
        Added value: +"Delivery as the retailer stated it: `free`, or `cost` in the offer currency. Absent or null means not stated: say delivery is shown at the shop, never that it is free. Offers are ordered by item price; add a stated cost before calling one cheaper delivered."
    • Changedcompare_products1 field changed
      • addedOutput schema / properties / comparison / items / properties / shipping / description
        Added value: +"Delivery as the retailer stated it: `free`, or `cost` in the offer currency. Absent or null means not stated: say delivery is shown at the shop, never that it is free. Offers are ordered by item price; add a stated cost before calling one cheaper delivered."
    • Changedfind_lowest_price3 fields changed
      • addedOutput schema / properties / alternatives / items / properties / shipping / description
        Added value: +"Delivery as the retailer stated it: `free`, or `cost` in the offer currency. Absent or null means not stated: say delivery is shown at the shop, never that it is free. Offers are ordered by item price; add a stated cost before calling one cheaper delivered."
      • addedOutput schema / properties / catalogMatch / properties / offers / items / properties / shipping / description
        Added value: +"Delivery as the retailer stated it: `free`, or `cost` in the offer currency. Absent or null means not stated: say delivery is shown at the shop, never that it is free. Offers are ordered by item price; add a stated cost before calling one cheaper delivered."
      • addedOutput schema / properties / recommendation / properties / shipping / description
        Added value: +"Delivery as the retailer stated it: `free`, or `cost` in the offer currency. Absent or null means not stated: say delivery is shown at the shop, never that it is free. Offers are ordered by item price; add a stated cost before calling one cheaper delivered."
    • Changedget_product1 field changed
      • addedOutput schema / properties / shipping / description
        Added value: +"Delivery as the retailer stated it: `free`, or `cost` in the offer currency. Absent or null means not stated: say delivery is shown at the shop, never that it is free. Offers are ordered by item price; add a stated cost before calling one cheaper delivered."
    • Changedsearch_products3 fields changed
      • addedOutput schema / properties / catalogMatch / properties / offers / items / properties / shipping / description
        Added value: +"Delivery as the retailer stated it: `free`, or `cost` in the offer currency. Absent or null means not stated: say delivery is shown at the shop, never that it is free. Offers are ordered by item price; add a stated cost before calling one cheaper delivered."
      • addedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / shipping / description
        Added value: +"Delivery as the retailer stated it: `free`, or `cost` in the offer currency. Absent or null means not stated: say delivery is shown at the shop, never that it is free. Offers are ordered by item price; add a stated cost before calling one cheaper delivered."
      • addedOutput schema / properties / products / items / properties / shipping / description
        Added value: +"Delivery as the retailer stated it: `free`, or `cost` in the offer currency. Absent or null means not stated: say delivery is shown at the shop, never that it is free. Offers are ordered by item price; add a stated cost before calling one cheaper delivered."
    • Changedsemantic_search2 fields changed
      • addedOutput schema / properties / catalogMatch / properties / offers / items / properties / shipping / description
        Added value: +"Delivery as the retailer stated it: `free`, or `cost` in the offer currency. Absent or null means not stated: say delivery is shown at the shop, never that it is free. Offers are ordered by item price; add a stated cost before calling one cheaper delivered."
      • addedOutput schema / properties / products / items / properties / shipping / description
        Added value: +"Delivery as the retailer stated it: `free`, or `cost` in the offer currency. Absent or null means not stated: say delivery is shown at the shop, never that it is free. Offers are ordered by item price; add a stated cost before calling one cheaper delivered."
  6. 10 tool updates
    • Changedcompare_offers43 fields changed
      • changedInput schema / properties / currency / description
        Previous value: -"ISO 4217 code for the shopper's market. Default GBP. Decides which market's offers WEM returns from its catalogue, not just how the answer reads — pass it explicitly, because WEM does not infer the market from IP. When WEM holds the product only in another currency it says so rather than presenting a foreign listing as the answer."New value: +"ISO 4217 code for the shopper's market. Default GBP. Decides which market's offers WEM returns from its catalogue, not just how the answer reads ; WEM does not infer the market from IP. When WEM holds the product only in another currency it says so rather than presenting a foreign listing as the answer."
      • changedInput schema / properties / gtin / description
        Previous value: -"Product barcode: EAN-13, UPC-A, EAN-8 or GTIN-14. Preferred key."New value: +"Product barcode: EAN-13, UPC-A, EAN-8 or GTIN-14. The strongest identifier."
      • changedInput schema / properties / title / description
        Previous value: -"Product or model name, or a bare MPN / merchant SKU (e.g. AF400UK). Weakest identifier — used only when no barcode, slug, or WEM ID is available. Same relevance gate as verify_offer; a miss means fall back to search_products, not a guess."New value: +"Product or model name, or an ASIN, MPN or merchant SKU (e.g. AF400UK). The weakest identifier: used only when no barcode, slug or WEM ID is given, and only if it passes a relevance check; otherwise `found` is false rather than a guess."
      • changedOutput schema / description
        Previous value: -"Every verified retailer offer for one catalogue product, cheapest first. When `found` is false WEM simply does not hold this product yet — that is a normal answer, not a failure, and it says nothing about whether the product exists or what it costs. Call `search_products` with `nextTool.query` before telling the user anything; reporting \"WEM returns nothing\" without doing so is wrong, because the live retailer search routinely finds supply this catalogue has not ingested."New value: +"The retailer offers WEM holds for one catalogue product, current prices first and each group cheapest first. When `found` is false WEM simply does not hold this product yet — that is a normal answer, not a failure, and it says nothing about whether the product exists or what it costs. `nextTool` then names `search_products` and the query. An empty catalogue result is not a statement that the product is unavailable or unpriced; the live retailer search is a separate lookup and routinely finds supply this catalogue has not ingested."
      • changedOutput schema / properties / coverage / description
        Previous value: -"Present when surviving rows include a marketplace cluster at similar prices. That is not a retail floor — do not name the cheapest marketplace listing as the deal. The listings are still in the payload; give the user those links. If `next` points at the Chrome extension, send the shopper there for shops WEM does not yet hold as partners."New value: +"Present when surviving rows include a marketplace cluster at similar prices. That is not a retail floor — the cheapest marketplace listing is not the deal. The listings stay in the payload, each with its url. `next`, when present, is the Chrome extension page for shops WEM does not yet hold as partners."
      • changedOutput schema / properties / degraded / description
        Previous value: -"Present when this call hit its time budget and skipped enrichment. The offers returned are COMPLETE — only the extras were dropped. Do not report a missing catalogue block or missing observed retailers as WEM holding nothing, and do not retry automatically."New value: +"Present when this call hit its time budget and skipped enrichment. The offers returned are COMPLETE — only the extras were dropped. A missing catalogue block or missing observed retailers does not mean WEM holds nothing, and no retry is needed."
      • changedOutput schema / properties / disclosure / description
        Previous value: -"Disclosure to relay once per answer, verbatim. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. Never substitute the version you saw last time — a row marked `affiliate: false` earns WEM nothing, and saying otherwise misdescribes it to the shopper."New value: +"WEM’s affiliate disclosure for this answer, written to be quoted as it is. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. A version from an earlier answer may not fit this one: a row marked `affiliate: false` earns WEM nothing."
      • changedOutput schema / properties / filtered / description
        Previous value: -"Offers of this product WEM held back, tallied by reason. \"Priced far below this product’s other offers\" is a marketplace listing under 40% of what the product sells for elsewhere — the shape of a counterfeit, a part or a mislisted variant. Those prices are not in `offers`, `lowPrice`, `links`, `summary` or `priceHistory.low`: never quote one as the cheapest, a deal or the 90-day low. Say how many were held back."New value: +"Offers of this product WEM held back, tallied by reason. \"Priced far below this product’s other offers\" is a marketplace listing under 40% of what the product sells for elsewhere — the shape of a counterfeit, a part or a mislisted variant. Those prices are not in `offers`, `lowPrice`, `links`, `summary` or `priceHistory.low`: none is the cheapest, a deal or the 90-day low. The tally says how many were held back."
      • changedOutput schema / properties / found / description
        Previous value: -"False when the product is not in WEM’s catalogue. The rest of the fields below are then absent — do not read that as the product being unavailable or unpriced. Check `unavailable` before describing the result, then follow `nextTool`."New value: +"False when the product is not in WEM’s catalogue. The rest of the fields below are then absent ; that does not mean the product is unavailable or unpriced. `unavailable` distinguishes an outage from a miss. `nextTool`, when present, names the next lookup."
      • changedOutput schema / properties / identity / description
        Previous value: -"How the shopper’s words reached this product. Decides how you describe the match: on `inferred`, say WEM matched it by name (not by barcode) and do not call the identity confirmed, even when `identityBasis` is `barcode`; on `exact`, the barcode itself resolved it."New value: +"How the shopper’s words reached this product. On `inferred`, WEM matched it by name (not by barcode) and the identity is not confirmed, even when `identityBasis` is `barcode`; on `exact`, the barcode itself resolved it."
      • changedOutput schema / properties / identityBasis / description
        Previous value: -"How this product’s offers are grouped — NOT how the shopper’s words found the product; that is `identity`. `barcode`: the product carries a GTIN, so every offer here is that same item. `curated-grouping`: it carries none, and the grouping is an inference. Never call a result a barcode match on the strength of this field: when `identity.strength` is `inferred`, say WEM matched the product by name."New value: +"How this product’s offers are grouped — NOT how the shopper’s words found the product; that is `identity`. `barcode`: the product carries a GTIN, so every offer here is that same item. `curated-grouping`: it carries none, and the grouping is an inference. This field does not make a result a barcode match: when `identity.strength` is `inferred`, WEM matched the product by name."
      • changedOutput schema / properties / lastConfirmedAt / description
        Previous value: -"When WEM last actually read any price in this answer. Null means none of them can be dated — say so rather than implying the answer is current."New value: +"When WEM last actually read any price in this answer. Null means none of them can be dated, so the answer is not current."
      • changedOutput schema / properties / links / description
        Previous value: -"The links from `offers`, cheapest first, pre-formatted to quote. Each opens the retailer’s page for the offer WEM priced; a retailer URL found elsewhere may be a different listing or price. State them in text even when the host renders a WEM card: the card may not reach the user."New value: +"The links from `offers`, cheapest first, pre-formatted. Each opens the retailer’s page for the offer WEM priced; a retailer URL found elsewhere may be a different listing or price. The same links are in this array and, when a host renders one, in the card."
      • changedOutput schema / properties / links / items / properties / price / description
        Previous value: -"Null for a listing in `unpriced`: its markdown says \"see price at Amazon\", and so must you."New value: +"Null for a listing in `unpriced`. The markdown says \"see price at Amazon\" in place of a figure."
      • changedOutput schema / properties / links / items / properties / url / description
        Previous value: -"WEM tracked redirect. Relay it exactly; never rewrite or shorten it."New value: +"WEM tracked redirect. The full URL; a shortened or rewritten form is a different link."
      • changedOutput schema / properties / lowPrice / description
        Previous value: -"Lowest CURRENT price in `offers` (read within 14 days). Null when no price is current or WEM holds none it may quote — never fill it from a stale or undated row, or from `unpriced`."New value: +"Lowest CURRENT price in `offers` (read within 14 days). Null when no price is current or WEM holds none it may quote ; it is never taken from a stale or undated row, or from `unpriced`."
      • changedOutput schema / properties / next / description
        Previous value: -"Where to send the shopper when WEM's set is thin. chrome_extension means compare the same product on any retailer page — WEM shows that price even without an affiliate programme."New value: +"Present when WEM's set of offers is thin. chrome_extension is a page that compares the same product on any retailer page, including shops without an affiliate programme."
      • changedOutput schema / properties / nextTool / description
        Previous value: -"Present only when `found` is false: the call to make next, with the text to pass. This is the recovery path, not a suggestion — a named model that misses the catalogue is the ordinary case, and the live search is where its offers are."New value: +"Present only when `found` is false. It names `search_products` and the query. A named model that misses the catalogue is the ordinary case; the live search is a separate lookup."
      • changedOutput schema / properties / offers / description
        Previous value: -"Current prices first (`priceStatus`), each group ascending by price; a stale or undated row is listed, never compared. Barcode, slug and WEM ID rows are the product. A title match is inferred — check identity.strength before stating it as exact."New value: +"Current prices first (`priceStatus`), each group ascending by price; a stale or undated row is listed, never compared. Barcode, slug and WEM ID rows are the product. A title match is inferred; `identity.strength` says which."
      • changedOutput schema / properties / offers / items / properties / affiliate / description
        Previous value: -"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. It is still a real offer, and its link is not affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` states whether all, some or none of the links are tracked."
      • changedOutput schema / properties / offers / items / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. Do not present a marketplace cluster as competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / offers / items / properties / lastSeenAt / description
        Previous value: -"When WEM last READ this price from the retailer or a datafeed — the same reading `priceAgeDays` counts from, so the two always agree. Null means WEM cannot date the price: say it is undated, never that it is current."New value: +"When WEM last READ this price from the retailer or a datafeed — the same reading `priceAgeDays` counts from, so the two always agree. Null means WEM cannot date the price: it is undated, not current."
      • changedOutput schema / properties / offers / items / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: the note stands in place of a figure."
      • changedOutput schema / properties / offers / items / properties / priceAgeDays / description
        Previous value: -"Calendar days (UK time) since WEM last READ this price: 0 read today, 1 yesterday. Null means WEM cannot say. Report null as undated; never present it as current."New value: +"Calendar days (UK time) since WEM last READ this price: 0 read today, 1 yesterday. Null means WEM cannot say. Null is undated, not current."
      • changedOutput schema / properties / offers / items / properties / priceNote / description
        Previous value: -"Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."New value: +"Present only when `price` is null: the words that stand in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."
      • changedOutput schema / properties / offers / items / properties / priceQualifier / description
        Previous value: -"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. Quote it as \"from £X\", never as the price or the cheapest. Absent means the price is firm for the row as described."New value: +"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. It reads as \"from £X\"; it is not the item's price or the cheapest. Absent means the price is firm for the row as described."
      • changedOutput schema / properties / offers / items / properties / priceRefresh / description
        Previous value: -"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `none` nothing on a schedule. `none` means the figure will not move on its own however long it sits — say so rather than quoting it flat, and date it with `priceAgeDays`."New value: +"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `none` nothing on a schedule. `none` means the figure will not move on its own however long it sits ; `priceAgeDays` dates it."
      • changedOutput schema / properties / offers / items / properties / priceStatus / description
        Previous value: -"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now."New value: +"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Those two read as \"last seen £X on 8 Sep\" or \"price not dated\", come after the current ones, and are not compared. Absent on a row a provider answered just now."
      • changedOutput schema / properties / offers / items / properties / unitPrice / description
        Previous value: -"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."New value: +"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. Across sizes, value is compared on these, not on the prices: a smaller size is not cheaper because its price is lower. It reads beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."
      • changedOutput schema / properties / offers / items / properties / url / description
        Previous value: -"WEM tracked link to the retailer. Send the user here — WEM never takes payment."New value: +"WEM tracked link to the retailer page for this offer. WEM never takes payment."
      • removedOutput schema / properties / offers / items / properties / verified
        Removed value: -{
        -  "type": "boolean"
        -}
      • changedOutput schema / properties / product / properties / image / description
        Previous value: -"Product photo, served from wem3.ai. Null when none is available — do not substitute one."New value: +"Product photo, served from wem3.ai. Null when none is available."
      • changedOutput schema / properties / product / properties / wem_id / description
        Previous value: -"WEM ID of this active product. Omit when unknown; never invent one."New value: +"WEM ID of this active product. Null when unknown."
      • changedOutput schema / properties / reason / description
        Previous value: -"Present only when `found` is false: which identifier missed, and why. When `unavailable` is true this describes the outage rather than a missing product — quote it as the reason the lookup failed, not as a fact about the product."New value: +"Present only when `found` is false: which identifier missed, and why. When `unavailable` is true this describes the outage rather than a missing product ; it is the reason the lookup failed, not a fact about the product."
      • changedOutput schema / properties / sameModel / description
        Previous value: -"Present only when the maker's own page says another model code is this product and a person at WEM has checked it. These are NOT offers for the product asked about: never merge them into `offers`, never call one this product's lowest price or the best deal. On verify_offer they are not part of the check: `verdict`, `cheapest`, `betterBy`, `summary` and the receipt are about the product asked about, and a cheaper sister code never makes the claimed price wrong. Mention it as a separate line: quote `summary`, name the maker's page (`maker.host`) as the source, and link `url`, WEM's comparison for that model, not a shop. When `relation` is `differs`, name the `differences` and never call its price a saving. Absent is not evidence that no equivalent exists."New value: +"Present only when the maker's own page says another model code is this product and a person at WEM has checked it. These are NOT offers for the product asked about: they are not part of `offers`, and none is this product's lowest price or the best deal. On verify_offer they are not part of the check: `verdict`, `cheapest`, `betterBy`, `summary` and the receipt are about the product asked about, and a cheaper sister code never makes the claimed price wrong. `summary` is written to be quoted as it is. `maker.host` is the source of the claim. `url` is WEM's comparison for that model, not a shop. When `relation` is `differs`, the `differences` are what the maker says differs, and its price is not a saving. Absent is not evidence that no equivalent exists."
      • changedOutput schema / properties / sameModel / items / properties / cheapest / description
        Previous value: -"The other model's cheapest named shop. Null when no named shop has an in-stock price for it. Give its age; never present it as current without one."New value: +"The other model's cheapest named shop. Null when no named shop has an in-stock price for it. `priceAgeDays` gives its age; without one it is not current."
      • changedOutput schema / properties / sameModel / items / properties / maker / description
        Previous value: -"The maker's own page that says so: the proof. Cite it; WEM is not the source of the claim."New value: +"The maker's own page that says so: the proof. WEM is not the source of the claim."
      • changedOutput schema / properties / sameModel / items / properties / url / description
        Previous value: -"WEM's comparison for that model. Link this, not a shop."New value: +"WEM's comparison for that model, not a shop."
      • changedOutput schema / properties / search / description
        Previous value: -"Present when this result names no offer. GIVE THE USER THIS LINK — it is the answer when WEM has nothing else to say, and `markdown` is ready to paste. WEM searches retailers live on that page, including shops it holds no affiliate programme with, so an empty or withheld result here is not evidence the product is unavailable or unpriced."New value: +"Present when this result names no offer. `url` is WEM's results page for the query and `markdown` is the same link, pre-formatted. WEM searches retailers live on that page, including shops it holds no affiliate programme with, so an empty or withheld result here is not evidence the product is unavailable or unpriced."
      • changedOutput schema / properties / unavailable / description
        Previous value: -"Present and true only when WEM could not reach its catalogue at all. `found` is false for the same reason it is on an ordinary miss, so the two are indistinguishable without this flag. When it is set, WEM does not know whether it holds the product: say the lookup could not be completed, never that WEM has no offers, no price, or does not stock it. Still call `nextTool` — the live retailer search does not depend on the catalogue."New value: +"Present and true only when WEM could not reach its catalogue at all. `found` is false for the same reason it is on an ordinary miss, so the two are indistinguishable without this flag. When it is set, WEM does not know whether it holds the product. The lookup could not be completed; it does not mean WEM has no offers or no price for it. `nextTool` is still present, because the live retailer search does not depend on the catalogue."
      • changedOutput schema / properties / unpriced / description
        Previous value: -"Listings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. Give the link with `priceNote` (\"See price at Amazon\"). Never state, estimate or compare a price for one, never call it the cheapest, and never count it in a lowest price or a saving."New value: +"Listings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. The row carries `priceNote` (e.g. \"See price at Amazon\") in place of a figure. No price is stated, estimated or compared for one; it is not the cheapest and is not counted in a lowest price or a saving."
      • changedOutput schema / properties / unpriced / items / properties / priceNote / description
        Previous value: -"What to show where a price would be, e.g. \"See price at Amazon\"."New value: +"What stands where a price would be, e.g. \"See price at Amazon\"."
      • changedOutput schema / properties / unpriced / items / properties / url / description
        Previous value: -"WEM tracked link. Relay it exactly."New value: +"WEM tracked link. The full URL; a shortened form is a different link."
    • Changedcompare_products10 fields changed
      • changedInput schema / properties / products / description
        Previous value: -"List of products to compare (2-5 items)"New value: +"2 to 5 listings, each with `provider` and `product_id` as given in a search result."
      • changedOutput schema / properties / comparison / items / properties / affiliate / description
        Previous value: -"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. It is still a real offer, and its link is not affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` states whether all, some or none of the links are tracked."
      • changedOutput schema / properties / comparison / items / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. Do not present a marketplace cluster as competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / comparison / items / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: the note stands in place of a figure."
      • changedOutput schema / properties / comparison / items / properties / priceNote / description
        Previous value: -"Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."New value: +"Present only when `price` is null: the words that stand in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."
      • changedOutput schema / properties / comparison / items / properties / priceQualifier / description
        Previous value: -"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. Quote it as \"from £X\", never as the price or the cheapest. Absent means the price is firm for the row as described."New value: +"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. It reads as \"from £X\"; it is not the item's price or the cheapest. Absent means the price is firm for the row as described."
      • changedOutput schema / properties / comparison / items / properties / priceStatus / description
        Previous value: -"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now."New value: +"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Those two read as \"last seen £X on 8 Sep\" or \"price not dated\", come after the current ones, and are not compared. Absent on a row a provider answered just now."
      • changedOutput schema / properties / comparison / items / properties / unitPrice / description
        Previous value: -"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."New value: +"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. Across sizes, value is compared on these, not on the prices: a smaller size is not cheaper because its price is lower. It reads beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."
      • changedOutput schema / properties / comparison / items / properties / url / description
        Previous value: -"WEM tracked link to the retailer. Send the user here — WEM never takes payment."New value: +"WEM tracked link to the retailer page for this offer. WEM never takes payment."
      • changedOutput schema / properties / disclosure / description
        Previous value: -"Disclosure to relay once per answer, verbatim. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. Never substitute the version you saw last time — a row marked `affiliate: false` earns WEM nothing, and saying otherwise misdescribes it to the shopper."New value: +"WEM’s affiliate disclosure for this answer, written to be quoted as it is. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. A version from an earlier answer may not fit this one: a row marked `affiliate: false` earns WEM nothing."
    • Changedfind_lowest_price41 fields changed
      • addedInput schema / properties / condition
        Added value: +{
        +  "description": "Same effect as include_used: \"any\", \"used\" or \"refurbished\" also includes used and refurbished listings; any other value means new only.",
        +  "type": "string"
        +}
      • changedInput schema / properties / max_price / description
        Previous value: -"Budget cap (GBP)"New value: +"Budget cap, in `currency`."
      • changedInput schema / properties / priorities / description
        Previous value: -"What matters most (in order of importance)"New value: +"What matters most, in order. cheapest: lowest price. best_rated: higher rating. free_shipping: free delivery. fastest: states a delivery estimate. Weighed only where listings carry those details."
      • changedInput schema / properties / query / description
        Previous value: -"Product name, barcode, ASIN, WEM ID, or wem3.ai/pl URL. A specific model should prefer compare_offers; this still resolves one if the host sends it here."New value: +"One kind of product or product: a name, barcode, ASIN, WEM ID or wem3.ai/pl URL. A single query, not a list."
      • changedOutput schema / description
        Previous value: -"A null `recommendation` with `coverage.kind` marketplace_only still has listings in `alternatives` — give those links. A null with no alternatives is a genuine miss. Never soften a genuine miss into a suggestion."New value: +"A null `recommendation` with `coverage.kind` marketplace_only still has listings in `alternatives`. A null with no alternatives is a genuine miss. A genuine miss is not a suggestion."
      • changedOutput schema / properties / alternatives / items / properties / affiliate / description
        Previous value: -"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. It is still a real offer, and its link is not affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` states whether all, some or none of the links are tracked."
      • changedOutput schema / properties / alternatives / items / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. Do not present a marketplace cluster as competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / alternatives / items / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: the note stands in place of a figure."
      • changedOutput schema / properties / alternatives / items / properties / priceNote / description
        Previous value: -"Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."New value: +"Present only when `price` is null: the words that stand in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."
      • changedOutput schema / properties / alternatives / items / properties / priceQualifier / description
        Previous value: -"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. Quote it as \"from £X\", never as the price or the cheapest. Absent means the price is firm for the row as described."New value: +"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. It reads as \"from £X\"; it is not the item's price or the cheapest. Absent means the price is firm for the row as described."
      • changedOutput schema / properties / alternatives / items / properties / priceStatus / description
        Previous value: -"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now."New value: +"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Those two read as \"last seen £X on 8 Sep\" or \"price not dated\", come after the current ones, and are not compared. Absent on a row a provider answered just now."
      • changedOutput schema / properties / alternatives / items / properties / unitPrice / description
        Previous value: -"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."New value: +"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. Across sizes, value is compared on these, not on the prices: a smaller size is not cheaper because its price is lower. It reads beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."
      • changedOutput schema / properties / alternatives / items / properties / url / description
        Previous value: -"WEM tracked link to the retailer. Send the user here — WEM never takes payment."New value: +"WEM tracked link to the retailer page for this offer. WEM never takes payment."
      • changedOutput schema / properties / catalogMatch / properties / identity / description
        Previous value: -"How the shopper’s words reached this product. Decides how you describe the match: on `inferred`, say WEM matched it by name (not by barcode) and do not call the identity confirmed, even when `identityBasis` is `barcode`; on `exact`, the barcode itself resolved it."New value: +"How the shopper’s words reached this product. On `inferred`, WEM matched it by name (not by barcode) and the identity is not confirmed, even when `identityBasis` is `barcode`; on `exact`, the barcode itself resolved it."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / affiliate / description
        Previous value: -"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. It is still a real offer, and its link is not affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` states whether all, some or none of the links are tracked."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. Do not present a marketplace cluster as competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / lastSeenAt / description
        Previous value: -"When WEM last READ this price from the retailer or a datafeed — the same reading `priceAgeDays` counts from, so the two always agree. Null means WEM cannot date the price: say it is undated, never that it is current."New value: +"When WEM last READ this price from the retailer or a datafeed — the same reading `priceAgeDays` counts from, so the two always agree. Null means WEM cannot date the price: it is undated, not current."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: the note stands in place of a figure."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceAgeDays / description
        Previous value: -"Calendar days (UK time) since WEM last READ this price: 0 read today, 1 yesterday. Null means WEM cannot say. Report null as undated; never present it as current."New value: +"Calendar days (UK time) since WEM last READ this price: 0 read today, 1 yesterday. Null means WEM cannot say. Null is undated, not current."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceNote / description
        Previous value: -"Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."New value: +"Present only when `price` is null: the words that stand in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceQualifier / description
        Previous value: -"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. Quote it as \"from £X\", never as the price or the cheapest. Absent means the price is firm for the row as described."New value: +"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. It reads as \"from £X\"; it is not the item's price or the cheapest. Absent means the price is firm for the row as described."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceRefresh / description
        Previous value: -"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `none` nothing on a schedule. `none` means the figure will not move on its own however long it sits — say so rather than quoting it flat, and date it with `priceAgeDays`."New value: +"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `none` nothing on a schedule. `none` means the figure will not move on its own however long it sits ; `priceAgeDays` dates it."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceStatus / description
        Previous value: -"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now."New value: +"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Those two read as \"last seen £X on 8 Sep\" or \"price not dated\", come after the current ones, and are not compared. Absent on a row a provider answered just now."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / unitPrice / description
        Previous value: -"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."New value: +"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. Across sizes, value is compared on these, not on the prices: a smaller size is not cheaper because its price is lower. It reads beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / url / description
        Previous value: -"WEM tracked link to the retailer. Send the user here — WEM never takes payment."New value: +"WEM tracked link to the retailer page for this offer. WEM never takes payment."
      • changedOutput schema / properties / catalogMatch / properties / unpriced / description
        Previous value: -"Listings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. Give the link with `priceNote` (\"See price at Amazon\"). Never state, estimate or compare a price for one, never call it the cheapest, and never count it in a lowest price or a saving."New value: +"Listings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. The row carries `priceNote` (e.g. \"See price at Amazon\") in place of a figure. No price is stated, estimated or compared for one; it is not the cheapest and is not counted in a lowest price or a saving."
      • changedOutput schema / properties / catalogMatch / properties / unpriced / items / properties / priceNote / description
        Previous value: -"What to show where a price would be, e.g. \"See price at Amazon\"."New value: +"What stands where a price would be, e.g. \"See price at Amazon\"."
      • changedOutput schema / properties / catalogMatch / properties / unpriced / items / properties / url / description
        Previous value: -"WEM tracked link. Relay it exactly."New value: +"WEM tracked link. The full URL; a shortened form is a different link."
      • changedOutput schema / properties / coverage / description
        Previous value: -"Present when surviving rows include a marketplace cluster at similar prices. That is not a retail floor — do not name the cheapest marketplace listing as the deal. The listings are still in the payload; give the user those links. If `next` points at the Chrome extension, send the shopper there for shops WEM does not yet hold as partners."New value: +"Present when surviving rows include a marketplace cluster at similar prices. That is not a retail floor — the cheapest marketplace listing is not the deal. The listings stay in the payload, each with its url. `next`, when present, is the Chrome extension page for shops WEM does not yet hold as partners."
      • changedOutput schema / properties / degraded / description
        Previous value: -"Present when this call hit its time budget and skipped enrichment. The offers returned are COMPLETE — only the extras were dropped. Do not report a missing catalogue block or missing observed retailers as WEM holding nothing, and do not retry automatically."New value: +"Present when this call hit its time budget and skipped enrichment. The offers returned are COMPLETE — only the extras were dropped. A missing catalogue block or missing observed retailers does not mean WEM holds nothing, and no retry is needed."
      • changedOutput schema / properties / disclosure / description
        Previous value: -"Disclosure to relay once per answer, verbatim. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. Never substitute the version you saw last time — a row marked `affiliate: false` earns WEM nothing, and saying otherwise misdescribes it to the shopper."New value: +"WEM’s affiliate disclosure for this answer, written to be quoted as it is. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. A version from an earlier answer may not fit this one: a row marked `affiliate: false` earns WEM nothing."
      • changedOutput schema / properties / next / description
        Previous value: -"Where to send the shopper when WEM's set is thin. chrome_extension means compare the same product on any retailer page — WEM shows that price even without an affiliate programme."New value: +"Present when WEM's set of offers is thin. chrome_extension is a page that compares the same product on any retailer page, including shops without an affiliate programme."
      • changedOutput schema / properties / recommendation / properties / affiliate / description
        Previous value: -"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. It is still a real offer, and its link is not affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` states whether all, some or none of the links are tracked."
      • changedOutput schema / properties / recommendation / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. Do not present a marketplace cluster as competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / recommendation / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: the note stands in place of a figure."
      • changedOutput schema / properties / recommendation / properties / priceNote / description
        Previous value: -"Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."New value: +"Present only when `price` is null: the words that stand in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."
      • changedOutput schema / properties / recommendation / properties / priceQualifier / description
        Previous value: -"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. Quote it as \"from £X\", never as the price or the cheapest. Absent means the price is firm for the row as described."New value: +"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. It reads as \"from £X\"; it is not the item's price or the cheapest. Absent means the price is firm for the row as described."
      • changedOutput schema / properties / recommendation / properties / priceStatus / description
        Previous value: -"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now."New value: +"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Those two read as \"last seen £X on 8 Sep\" or \"price not dated\", come after the current ones, and are not compared. Absent on a row a provider answered just now."
      • changedOutput schema / properties / recommendation / properties / unitPrice / description
        Previous value: -"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."New value: +"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. Across sizes, value is compared on these, not on the prices: a smaller size is not cheaper because its price is lower. It reads beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."
      • changedOutput schema / properties / recommendation / properties / url / description
        Previous value: -"WEM tracked link to the retailer. Send the user here — WEM never takes payment."New value: +"WEM tracked link to the retailer page for this offer. WEM never takes payment."
      • changedOutput schema / properties / search / description
        Previous value: -"Present when this result names no offer. GIVE THE USER THIS LINK — it is the answer when WEM has nothing else to say, and `markdown` is ready to paste. WEM searches retailers live on that page, including shops it holds no affiliate programme with, so an empty or withheld result here is not evidence the product is unavailable or unpriced."New value: +"Present when this result names no offer. `url` is WEM's results page for the query and `markdown` is the same link, pre-formatted. WEM searches retailers live on that page, including shops it holds no affiliate programme with, so an empty or withheld result here is not evidence the product is unavailable or unpriced."
    • Changedget_evidence_receipt1 field changed
      • changedInput schema / properties / id / description
        Previous value: -"Receipt id, as returned on verify_offer as receipt.id (wem-evr-...)."New value: +"Receipt id (wem-evr- followed by 32 hex characters), as returned in a verify_offer result's receipt.id."
    • Changedget_product11 fields changed
      • changedInput schema / properties / product_id / description
        Previous value: -"Product ID from search results"New value: +"The listing's `id` from the search result."
      • changedInput schema / properties / provider / description
        Previous value: -"Provider name (e.g. \"ebay\", \"awin\")"New value: +"Retailer source of the listing, as given in the search result (e.g. \"ebay\", \"awin\")."
      • changedOutput schema / properties / affiliate / description
        Previous value: -"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. It is still a real offer, and its link is not affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` states whether all, some or none of the links are tracked."
      • changedOutput schema / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. Do not present a marketplace cluster as competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / disclosure / description
        Previous value: -"Disclosure to relay once per answer, verbatim. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. Never substitute the version you saw last time — a row marked `affiliate: false` earns WEM nothing, and saying otherwise misdescribes it to the shopper."New value: +"WEM’s affiliate disclosure for this answer, written to be quoted as it is. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. A version from an earlier answer may not fit this one: a row marked `affiliate: false` earns WEM nothing."
      • changedOutput schema / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: the note stands in place of a figure."
      • changedOutput schema / properties / priceNote / description
        Previous value: -"Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."New value: +"Present only when `price` is null: the words that stand in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."
      • changedOutput schema / properties / priceQualifier / description
        Previous value: -"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. Quote it as \"from £X\", never as the price or the cheapest. Absent means the price is firm for the row as described."New value: +"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. It reads as \"from £X\"; it is not the item's price or the cheapest. Absent means the price is firm for the row as described."
      • changedOutput schema / properties / priceStatus / description
        Previous value: -"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now."New value: +"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Those two read as \"last seen £X on 8 Sep\" or \"price not dated\", come after the current ones, and are not compared. Absent on a row a provider answered just now."
      • changedOutput schema / properties / unitPrice / description
        Previous value: -"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."New value: +"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. Across sizes, value is compared on these, not on the prices: a smaller size is not cheaper because its price is lower. It reads beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."
      • changedOutput schema / properties / url / description
        Previous value: -"WEM tracked link to the retailer. Send the user here — WEM never takes payment."New value: +"WEM tracked link to the retailer page for this offer. WEM never takes payment."
    • Changedlookup_products3 fields changed
      • changedOutput schema / properties / disclosure / description
        Previous value: -"Disclosure to relay once per answer, verbatim. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. Never substitute the version you saw last time — a row marked `affiliate: false` earns WEM nothing, and saying otherwise misdescribes it to the shopper."New value: +"WEM’s affiliate disclosure for this answer, written to be quoted as it is. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. A version from an earlier answer may not fit this one: a row marked `affiliate: false` earns WEM nothing."
      • changedOutput schema / properties / results / items / properties / product / properties / url / description
        Previous value: -"WEM product page listing every retailer WEM holds. Relay it exactly."New value: +"WEM product page listing every retailer WEM holds. The full URL; a shortened form is a different link."
      • changedOutput schema / properties / results / items / properties / status / description
        Previous value: -"not_found: WEM does not hold it yet — never say the product does not exist or has no price; look it up with compare_offers or search_products first. not_checked: not reached in this call, and not a miss. unrecognised: not an identifier this tool reads (product names go to compare_offers)."New value: +"not_found: WEM does not hold it yet — that is not a finding that the product does not exist or has no price. compare_offers and search_products are the lookups for it. not_checked: not reached in this call, and not a miss. unrecognised: not an identifier this tool reads (product names go to compare_offers)."
    • Changedsearch_products56 fields changed
      • changedInput schema / properties / category / description
        Previous value: -"Filter by category (electronics, fashion, beauty, home, sports, collectibles)"New value: +"Optional. Keeps only live retailer listings whose own category name matches this text exactly; catalogue matches ignore it. Leave it out unless the shopper names a retailer's category."
      • addedInput schema / properties / currency
        Added value: +{
        +  "description": "ISO 4217 code for the shopper's market. Default GBP. Results and price filters use this currency.",
        +  "type": "string"
        +}
      • changedInput schema / properties / gtin / description
        Previous value: -"Product barcode (EAN/UPC/GTIN) when the host already has one. Feed rows are matched on this before title."New value: +"A product barcode (EAN/UPC/GTIN) the host already has. When given, retailer sources are searched by this barcode instead of by the query words."
      • changedInput schema / properties / limit / description
        Previous value: -"Max results to return (default 10, max 30)"New value: +"How many listings to request from each retailer source (default 10, max 30). The combined list can hold more."
      • changedInput schema / properties / max_price / description
        Previous value: -"Maximum price filter (GBP)"New value: +"Highest price to include, in `currency`. Applies to retailer listings, not to `catalogMatch`."
      • changedInput schema / properties / min_price / description
        Previous value: -"Minimum price filter (GBP)"New value: +"Lowest price to include, in `currency`. Applies to retailer listings, not to `catalogMatch`."
      • changedInput schema / properties / providers / description
        Previous value: -"Limit to specific providers (e.g. [\"ebay\", \"awin\"]). Omit for all."New value: +"Retailer sources to search live, e.g. [\"ebay\", \"awin\"]. Omit for all. Catalogue matches are not limited by it."
      • changedInput schema / properties / query / description
        Previous value: -"Product name, barcode (EAN/UPC/GTIN), ASIN, MPN, merchant SKU, WEM ID, wem3.ai/pl URL, or comma-separated IDs of those kinds."New value: +"A product name, or an identifier: barcode (EAN/UPC/GTIN), ASIN, MPN, merchant SKU, WEM ID or wem3.ai/pl URL. Several identifiers may be comma-separated."
      • changedInput schema / properties / sort_by / description
        Previous value: -"Sort order for results"New value: +"Order of the live retailer listings (default relevance). Not applied when the query identifies a product."
      • changedOutput schema / properties / catalogMatch / properties / identity / description
        Previous value: -"How the shopper’s words reached this product. Decides how you describe the match: on `inferred`, say WEM matched it by name (not by barcode) and do not call the identity confirmed, even when `identityBasis` is `barcode`; on `exact`, the barcode itself resolved it."New value: +"How the shopper’s words reached this product. On `inferred`, WEM matched it by name (not by barcode) and the identity is not confirmed, even when `identityBasis` is `barcode`; on `exact`, the barcode itself resolved it."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / affiliate / description
        Previous value: -"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. It is still a real offer, and its link is not affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` states whether all, some or none of the links are tracked."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. Do not present a marketplace cluster as competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / lastSeenAt / description
        Previous value: -"When WEM last READ this price from the retailer or a datafeed — the same reading `priceAgeDays` counts from, so the two always agree. Null means WEM cannot date the price: say it is undated, never that it is current."New value: +"When WEM last READ this price from the retailer or a datafeed — the same reading `priceAgeDays` counts from, so the two always agree. Null means WEM cannot date the price: it is undated, not current."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: the note stands in place of a figure."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceAgeDays / description
        Previous value: -"Calendar days (UK time) since WEM last READ this price: 0 read today, 1 yesterday. Null means WEM cannot say. Report null as undated; never present it as current."New value: +"Calendar days (UK time) since WEM last READ this price: 0 read today, 1 yesterday. Null means WEM cannot say. Null is undated, not current."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceNote / description
        Previous value: -"Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."New value: +"Present only when `price` is null: the words that stand in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceQualifier / description
        Previous value: -"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. Quote it as \"from £X\", never as the price or the cheapest. Absent means the price is firm for the row as described."New value: +"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. It reads as \"from £X\"; it is not the item's price or the cheapest. Absent means the price is firm for the row as described."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceRefresh / description
        Previous value: -"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `none` nothing on a schedule. `none` means the figure will not move on its own however long it sits — say so rather than quoting it flat, and date it with `priceAgeDays`."New value: +"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `none` nothing on a schedule. `none` means the figure will not move on its own however long it sits ; `priceAgeDays` dates it."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceStatus / description
        Previous value: -"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now."New value: +"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Those two read as \"last seen £X on 8 Sep\" or \"price not dated\", come after the current ones, and are not compared. Absent on a row a provider answered just now."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / unitPrice / description
        Previous value: -"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."New value: +"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. Across sizes, value is compared on these, not on the prices: a smaller size is not cheaper because its price is lower. It reads beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / url / description
        Previous value: -"WEM tracked link to the retailer. Send the user here — WEM never takes payment."New value: +"WEM tracked link to the retailer page for this offer. WEM never takes payment."
      • changedOutput schema / properties / catalogMatch / properties / unpriced / description
        Previous value: -"Listings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. Give the link with `priceNote` (\"See price at Amazon\"). Never state, estimate or compare a price for one, never call it the cheapest, and never count it in a lowest price or a saving."New value: +"Listings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. The row carries `priceNote` (e.g. \"See price at Amazon\") in place of a figure. No price is stated, estimated or compared for one; it is not the cheapest and is not counted in a lowest price or a saving."
      • changedOutput schema / properties / catalogMatch / properties / unpriced / items / properties / priceNote / description
        Previous value: -"What to show where a price would be, e.g. \"See price at Amazon\"."New value: +"What stands where a price would be, e.g. \"See price at Amazon\"."
      • changedOutput schema / properties / catalogMatch / properties / unpriced / items / properties / url / description
        Previous value: -"WEM tracked link. Relay it exactly."New value: +"WEM tracked link. The full URL; a shortened form is a different link."
      • changedOutput schema / properties / catalogMatches / items / properties / identity / description
        Previous value: -"How the shopper’s words reached this product. Decides how you describe the match: on `inferred`, say WEM matched it by name (not by barcode) and do not call the identity confirmed, even when `identityBasis` is `barcode`; on `exact`, the barcode itself resolved it."New value: +"How the shopper’s words reached this product. On `inferred`, WEM matched it by name (not by barcode) and the identity is not confirmed, even when `identityBasis` is `barcode`; on `exact`, the barcode itself resolved it."
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / affiliate / description
        Previous value: -"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. It is still a real offer, and its link is not affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` states whether all, some or none of the links are tracked."
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. Do not present a marketplace cluster as competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / lastSeenAt / description
        Previous value: -"When WEM last READ this price from the retailer or a datafeed — the same reading `priceAgeDays` counts from, so the two always agree. Null means WEM cannot date the price: say it is undated, never that it is current."New value: +"When WEM last READ this price from the retailer or a datafeed — the same reading `priceAgeDays` counts from, so the two always agree. Null means WEM cannot date the price: it is undated, not current."
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: the note stands in place of a figure."
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / priceAgeDays / description
        Previous value: -"Calendar days (UK time) since WEM last READ this price: 0 read today, 1 yesterday. Null means WEM cannot say. Report null as undated; never present it as current."New value: +"Calendar days (UK time) since WEM last READ this price: 0 read today, 1 yesterday. Null means WEM cannot say. Null is undated, not current."
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / priceNote / description
        Previous value: -"Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."New value: +"Present only when `price` is null: the words that stand in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / priceQualifier / description
        Previous value: -"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. Quote it as \"from £X\", never as the price or the cheapest. Absent means the price is firm for the row as described."New value: +"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. It reads as \"from £X\"; it is not the item's price or the cheapest. Absent means the price is firm for the row as described."
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / priceRefresh / description
        Previous value: -"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `none` nothing on a schedule. `none` means the figure will not move on its own however long it sits — say so rather than quoting it flat, and date it with `priceAgeDays`."New value: +"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `none` nothing on a schedule. `none` means the figure will not move on its own however long it sits ; `priceAgeDays` dates it."
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / priceStatus / description
        Previous value: -"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now."New value: +"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Those two read as \"last seen £X on 8 Sep\" or \"price not dated\", come after the current ones, and are not compared. Absent on a row a provider answered just now."
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / unitPrice / description
        Previous value: -"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."New value: +"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. Across sizes, value is compared on these, not on the prices: a smaller size is not cheaper because its price is lower. It reads beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / url / description
        Previous value: -"WEM tracked link to the retailer. Send the user here — WEM never takes payment."New value: +"WEM tracked link to the retailer page for this offer. WEM never takes payment."
      • changedOutput schema / properties / catalogMatches / items / properties / unpriced / description
        Previous value: -"Listings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. Give the link with `priceNote` (\"See price at Amazon\"). Never state, estimate or compare a price for one, never call it the cheapest, and never count it in a lowest price or a saving."New value: +"Listings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. The row carries `priceNote` (e.g. \"See price at Amazon\") in place of a figure. No price is stated, estimated or compared for one; it is not the cheapest and is not counted in a lowest price or a saving."
      • changedOutput schema / properties / catalogMatches / items / properties / unpriced / items / properties / priceNote / description
        Previous value: -"What to show where a price would be, e.g. \"See price at Amazon\"."New value: +"What stands where a price would be, e.g. \"See price at Amazon\"."
      • changedOutput schema / properties / catalogMatches / items / properties / unpriced / items / properties / url / description
        Previous value: -"WEM tracked link. Relay it exactly."New value: +"WEM tracked link. The full URL; a shortened form is a different link."
      • changedOutput schema / properties / coverage / description
        Previous value: -"Present when surviving rows include a marketplace cluster at similar prices. That is not a retail floor — do not name the cheapest marketplace listing as the deal. The listings are still in the payload; give the user those links. If `next` points at the Chrome extension, send the shopper there for shops WEM does not yet hold as partners."New value: +"Present when surviving rows include a marketplace cluster at similar prices. That is not a retail floor — the cheapest marketplace listing is not the deal. The listings stay in the payload, each with its url. `next`, when present, is the Chrome extension page for shops WEM does not yet hold as partners."
      • changedOutput schema / properties / degraded / description
        Previous value: -"Present when this call hit its time budget and skipped enrichment. The offers returned are COMPLETE — only the extras were dropped. Do not report a missing catalogue block or missing observed retailers as WEM holding nothing, and do not retry automatically."New value: +"Present when this call hit its time budget and skipped enrichment. The offers returned are COMPLETE — only the extras were dropped. A missing catalogue block or missing observed retailers does not mean WEM holds nothing, and no retry is needed."
      • changedOutput schema / properties / disclosure / description
        Previous value: -"Disclosure to relay once per answer, verbatim. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. Never substitute the version you saw last time — a row marked `affiliate: false` earns WEM nothing, and saying otherwise misdescribes it to the shopper."New value: +"WEM’s affiliate disclosure for this answer, written to be quoted as it is. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. A version from an earlier answer may not fit this one: a row marked `affiliate: false` earns WEM nothing."
      • changedOutput schema / properties / next / description
        Previous value: -"Where to send the shopper when WEM's set is thin. chrome_extension means compare the same product on any retailer page — WEM shows that price even without an affiliate programme."New value: +"Present when WEM's set of offers is thin. chrome_extension is a page that compares the same product on any retailer page, including shops without an affiliate programme."
      • changedOutput schema / properties / products / items / properties / affiliate / description
        Previous value: -"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. It is still a real offer, and its link is not affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` states whether all, some or none of the links are tracked."
      • changedOutput schema / properties / products / items / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. Do not present a marketplace cluster as competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / products / items / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: the note stands in place of a figure."
      • changedOutput schema / properties / products / items / properties / priceNote / description
        Previous value: -"Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."New value: +"Present only when `price` is null: the words that stand in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."
      • changedOutput schema / properties / products / items / properties / priceQualifier / description
        Previous value: -"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. Quote it as \"from £X\", never as the price or the cheapest. Absent means the price is firm for the row as described."New value: +"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. It reads as \"from £X\"; it is not the item's price or the cheapest. Absent means the price is firm for the row as described."
      • changedOutput schema / properties / products / items / properties / priceStatus / description
        Previous value: -"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now."New value: +"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Those two read as \"last seen £X on 8 Sep\" or \"price not dated\", come after the current ones, and are not compared. Absent on a row a provider answered just now."
      • changedOutput schema / properties / products / items / properties / unitPrice / description
        Previous value: -"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."New value: +"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. Across sizes, value is compared on these, not on the prices: a smaller size is not cheaper because its price is lower. It reads beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."
      • changedOutput schema / properties / products / items / properties / url / description
        Previous value: -"WEM tracked link to the retailer. Send the user here — WEM never takes payment."New value: +"WEM tracked link to the retailer page for this offer. WEM never takes payment."
      • changedOutput schema / properties / search / description
        Previous value: -"Present when this result names no offer. GIVE THE USER THIS LINK — it is the answer when WEM has nothing else to say, and `markdown` is ready to paste. WEM searches retailers live on that page, including shops it holds no affiliate programme with, so an empty or withheld result here is not evidence the product is unavailable or unpriced."New value: +"Present when this result names no offer. `url` is WEM's results page for the query and `markdown` is the same link, pre-formatted. WEM searches retailers live on that page, including shops it holds no affiliate programme with, so an empty or withheld result here is not evidence the product is unavailable or unpriced."
      • changedOutput schema / properties / sizeSpread / description
        Previous value: -"Present when the returned rows are different sizes and the query named none, so price ordering is meaningless: the cheapest row is cheapest because it is less of the product. Do NOT name a cheapest, a lowest price, or a best deal across these rows. State the size beside every price and ask the shopper which size they want. Where rows carry `unitPrice`, that is the like-for-like figure: quote it, and rank on it if the shopper asks which is better value. The rows are real — give the user those links."New value: +"Present when the returned rows are different sizes and the query named none, so price ordering is meaningless: the cheapest row is cheapest because it is less of the product. Do NOT name a cheapest, a lowest price, or a best deal across these rows. The size belongs beside every price. Where rows carry `unitPrice`, that is the like-for-like figure, and it is the figure to rank on when the question is which is better value. The rows are real listings, each with its url."
      • changedOutput schema / properties / unpriced / description
        Previous value: -"Listings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. Give the link with `priceNote` (\"See price at Amazon\"). Never state, estimate or compare a price for one, never call it the cheapest, and never count it in a lowest price or a saving."New value: +"Listings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. The row carries `priceNote` (e.g. \"See price at Amazon\") in place of a figure. No price is stated, estimated or compared for one; it is not the cheapest and is not counted in a lowest price or a saving."
      • changedOutput schema / properties / unpriced / items / properties / priceNote / description
        Previous value: -"What to show where a price would be, e.g. \"See price at Amazon\"."New value: +"What stands where a price would be, e.g. \"See price at Amazon\"."
      • changedOutput schema / properties / unpriced / items / properties / url / description
        Previous value: -"WEM tracked link. Relay it exactly."New value: +"WEM tracked link. The full URL; a shortened form is a different link."
    • Changedsearch_promotions5 fields changed
      • changedInput schema / properties / currency / description
        Previous value: -"ISO 4217 code for the shopper's market: GBP (default) or USD. Promotions are regional, so this decides which retailers' offers are read."New value: +"ISO 4217 code for the shopper's market: GBP (default) or USD. Promotions are regional, so this decides which market's offers are read."
      • changedOutput schema / properties / disclosure / description
        Previous value: -"Disclosure to relay once per answer, verbatim. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. Never substitute the version you saw last time — a row marked `affiliate: false` earns WEM nothing, and saying otherwise misdescribes it to the shopper."New value: +"WEM’s affiliate disclosure for this answer, written to be quoted as it is. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. A version from an earlier answer may not fit this one: a row marked `affiliate: false` earns WEM nothing."
      • changedOutput schema / properties / promotions / items / properties / url / description
        Previous value: -"WEM tracked redirect to the retailer’s promotion page. Relay it exactly; never rewrite it."New value: +"WEM tracked redirect to the retailer’s promotion page. The full URL; a shortened or rewritten form is a different link."
      • changedOutput schema / properties / search / description
        Previous value: -"Present when this result names no offer. GIVE THE USER THIS LINK — it is the answer when WEM has nothing else to say, and `markdown` is ready to paste. WEM searches retailers live on that page, including shops it holds no affiliate programme with, so an empty or withheld result here is not evidence the product is unavailable or unpriced."New value: +"Present when this result names no offer. `url` is WEM's results page for the query and `markdown` is the same link, pre-formatted. WEM searches retailers live on that page, including shops it holds no affiliate programme with, so an empty or withheld result here is not evidence the product is unavailable or unpriced."
      • changedOutput schema / properties / withheld / description
        Previous value: -"Matching promotions WEM did not show, by reason. codeNotPermitted and mentionsCode mean a checkout code WEM may not publish: the code may well exist — never say there is none."New value: +"Matching promotions WEM did not show, counted by reason: notPublishable (a checkout code or offer the retailer’s programme does not let WEM publish; the code may well exist), notJoined, notActive, outsideMarket, noTrackedLink, otherPublisherLink, incompleteRecord."
    • Changedsemantic_search32 fields changed
      • changedInput schema / properties / category / description
        Previous value: -"Optional category filter"New value: +"Optional. Keeps only products whose feed category matches this text exactly."
      • changedInput schema / properties / description / description
        Previous value: -"Natural language description of what the user is looking for"New value: +"Plain-language description of what the shopper needs."
      • changedInput schema / properties / limit / description
        Previous value: -"Max results (default 10, max 20)"New value: +"Max products to return (default 10, max 20)."
      • changedInput schema / properties / max_price / description
        Previous value: -"Maximum price (GBP)"New value: +"Optional upper price bound, compared with each product's listed price (currencies are not converted)."
      • changedInput schema / properties / min_price / description
        Previous value: -"Minimum price (GBP)"New value: +"Optional lower price bound, compared with each product's listed price (currencies are not converted)."
      • addedInput schema / properties / provider
        Added value: +{
        +  "description": "Optional. Keeps only products from this partner feed, e.g. \"awin\".",
        +  "type": "string"
        +}
      • changedOutput schema / properties / catalogMatch / properties / identity / description
        Previous value: -"How the shopper’s words reached this product. Decides how you describe the match: on `inferred`, say WEM matched it by name (not by barcode) and do not call the identity confirmed, even when `identityBasis` is `barcode`; on `exact`, the barcode itself resolved it."New value: +"How the shopper’s words reached this product. On `inferred`, WEM matched it by name (not by barcode) and the identity is not confirmed, even when `identityBasis` is `barcode`; on `exact`, the barcode itself resolved it."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / affiliate / description
        Previous value: -"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. It is still a real offer, and its link is not affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` states whether all, some or none of the links are tracked."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. Do not present a marketplace cluster as competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / lastSeenAt / description
        Previous value: -"When WEM last READ this price from the retailer or a datafeed — the same reading `priceAgeDays` counts from, so the two always agree. Null means WEM cannot date the price: say it is undated, never that it is current."New value: +"When WEM last READ this price from the retailer or a datafeed — the same reading `priceAgeDays` counts from, so the two always agree. Null means WEM cannot date the price: it is undated, not current."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: the note stands in place of a figure."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceAgeDays / description
        Previous value: -"Calendar days (UK time) since WEM last READ this price: 0 read today, 1 yesterday. Null means WEM cannot say. Report null as undated; never present it as current."New value: +"Calendar days (UK time) since WEM last READ this price: 0 read today, 1 yesterday. Null means WEM cannot say. Null is undated, not current."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceNote / description
        Previous value: -"Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."New value: +"Present only when `price` is null: the words that stand in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceQualifier / description
        Previous value: -"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. Quote it as \"from £X\", never as the price or the cheapest. Absent means the price is firm for the row as described."New value: +"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. It reads as \"from £X\"; it is not the item's price or the cheapest. Absent means the price is firm for the row as described."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceRefresh / description
        Previous value: -"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `none` nothing on a schedule. `none` means the figure will not move on its own however long it sits — say so rather than quoting it flat, and date it with `priceAgeDays`."New value: +"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `none` nothing on a schedule. `none` means the figure will not move on its own however long it sits ; `priceAgeDays` dates it."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceStatus / description
        Previous value: -"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now."New value: +"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Those two read as \"last seen £X on 8 Sep\" or \"price not dated\", come after the current ones, and are not compared. Absent on a row a provider answered just now."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / unitPrice / description
        Previous value: -"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."New value: +"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. Across sizes, value is compared on these, not on the prices: a smaller size is not cheaper because its price is lower. It reads beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / url / description
        Previous value: -"WEM tracked link to the retailer. Send the user here — WEM never takes payment."New value: +"WEM tracked link to the retailer page for this offer. WEM never takes payment."
      • changedOutput schema / properties / catalogMatch / properties / unpriced / description
        Previous value: -"Listings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. Give the link with `priceNote` (\"See price at Amazon\"). Never state, estimate or compare a price for one, never call it the cheapest, and never count it in a lowest price or a saving."New value: +"Listings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. The row carries `priceNote` (e.g. \"See price at Amazon\") in place of a figure. No price is stated, estimated or compared for one; it is not the cheapest and is not counted in a lowest price or a saving."
      • changedOutput schema / properties / catalogMatch / properties / unpriced / items / properties / priceNote / description
        Previous value: -"What to show where a price would be, e.g. \"See price at Amazon\"."New value: +"What stands where a price would be, e.g. \"See price at Amazon\"."
      • changedOutput schema / properties / catalogMatch / properties / unpriced / items / properties / url / description
        Previous value: -"WEM tracked link. Relay it exactly."New value: +"WEM tracked link. The full URL; a shortened form is a different link."
      • changedOutput schema / properties / disclosure / description
        Previous value: -"Disclosure to relay once per answer, verbatim. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. Never substitute the version you saw last time — a row marked `affiliate: false` earns WEM nothing, and saying otherwise misdescribes it to the shopper."New value: +"WEM’s affiliate disclosure for this answer, written to be quoted as it is. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. A version from an earlier answer may not fit this one: a row marked `affiliate: false` earns WEM nothing."
      • changedOutput schema / properties / next / description
        Previous value: -"Where to send the shopper when WEM's set is thin. chrome_extension means compare the same product on any retailer page — WEM shows that price even without an affiliate programme."New value: +"Present when WEM's set of offers is thin. chrome_extension is a page that compares the same product on any retailer page, including shops without an affiliate programme."
      • changedOutput schema / properties / products / items / properties / affiliate / description
        Previous value: -"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. It is still a real offer, and its link is not affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` states whether all, some or none of the links are tracked."
      • changedOutput schema / properties / products / items / properties / channel / description
        Previous value: -"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. Do not present a marketplace cluster as competing authorised retailers."New value: +"retailer is a named shop (Boots, Currys). marketplace is eBay/AliExpress/Temu-style parallel listings. A marketplace cluster is not a set of competing authorised retailers."
      • changedOutput schema / properties / products / items / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: the note stands in place of a figure."
      • changedOutput schema / properties / products / items / properties / priceNote / description
        Previous value: -"Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."New value: +"Present only when `price` is null: the words that stand in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now."
      • changedOutput schema / properties / products / items / properties / priceQualifier / description
        Previous value: -"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. Quote it as \"from £X\", never as the price or the cheapest. Absent means the price is firm for the row as described."New value: +"Present when `price` is the OPENING price of a range, not the price of this item: a multi-variation listing where the seller advertises its cheapest variant and the shopper picks a size on the page. It reads as \"from £X\"; it is not the item's price or the cheapest. Absent means the price is firm for the row as described."
      • changedOutput schema / properties / products / items / properties / priceStatus / description
        Previous value: -"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now."New value: +"`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Those two read as \"last seen £X on 8 Sep\" or \"price not dated\", come after the current ones, and are not compared. Absent on a row a provider answered just now."
      • changedOutput schema / properties / products / items / properties / unitPrice / description
        Previous value: -"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."New value: +"Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. Across sizes, value is compared on these, not on the prices: a smaller size is not cheaper because its price is lower. It reads beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit."
      • changedOutput schema / properties / products / items / properties / url / description
        Previous value: -"WEM tracked link to the retailer. Send the user here — WEM never takes payment."New value: +"WEM tracked link to the retailer page for this offer. WEM never takes payment."
      • changedOutput schema / properties / search / description
        Previous value: -"Present when this result names no offer. GIVE THE USER THIS LINK — it is the answer when WEM has nothing else to say, and `markdown` is ready to paste. WEM searches retailers live on that page, including shops it holds no affiliate programme with, so an empty or withheld result here is not evidence the product is unavailable or unpriced."New value: +"Present when this result names no offer. `url` is WEM's results page for the query and `markdown` is the same link, pre-formatted. WEM searches retailers live on that page, including shops it holds no affiliate programme with, so an empty or withheld result here is not evidence the product is unavailable or unpriced."
    • Changedverify_offer14 fields changed
      • changedInput schema / properties / currency / description
        Previous value: -"ISO 4217 code for the claimed price. Default GBP."New value: +"ISO 4217 code for the claimed price. Default GBP. Only offers in this currency are compared."
      • changedInput schema / properties / externalId / description
        Previous value: -"The retailer's own product id (ASIN, eBay item number). Use with provider."New value: +"That listing's own id (ASIN, eBay item number). Use with provider."
      • changedInput schema / properties / price / description
        Previous value: -"The price being claimed. Omit to ask only what the verified offers are."New value: +"The price being claimed. Omit to ask only for the observed offers."
      • changedInput schema / properties / provider / description
        Previous value: -"Retailer slug for the listing being checked, e.g. 'currys'."New value: +"With externalId: the retailer source of a listing that identifies the product, e.g. 'amazon' or 'ebay'. To name the shop the claim is about, use `retailer`."
      • changedInput schema / properties / retailer / description
        Previous value: -"Retailer the price was claimed at — slug or display name."New value: +"The shop the price was claimed at, as a slug or display name. Omit to compare against every shop."
      • changedInput schema / properties / title / description
        Previous value: -"Product title. Weakest identifier — used only when no id is available."New value: +"Product title. The weakest identifier: used only when no id is given, and only if it passes a relevance check."
      • changedOutput schema / properties / cheapest / properties / affiliate / description
        Previous value: -"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. It is still a real offer, and its link is not affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` states whether all, some or none of the links are tracked."
      • changedOutput schema / properties / claimMatched / properties / affiliate / description
        Previous value: -"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. It is still a real offer, and its link is not affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` states whether all, some or none of the links are tracked."
      • changedOutput schema / properties / disclosure / description
        Previous value: -"Disclosure to relay once per answer, verbatim. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. Never substitute the version you saw last time — a row marked `affiliate: false` earns WEM nothing, and saying otherwise misdescribes it to the shopper."New value: +"WEM’s affiliate disclosure for this answer, written to be quoted as it is. Its wording changes with the rows: it states whether every outbound link is affiliate-tracked, only some are, or none are. A version from an earlier answer may not fit this one: a row marked `affiliate: false` earns WEM nothing."
      • changedOutput schema / properties / offers / items / properties / affiliate / description
        Previous value: -"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. It is still a real offer, and its link is not affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` states whether all, some or none of the links are tracked."
      • changedOutput schema / properties / sameModel / description
        Previous value: -"Present only when the maker's own page says another model code is this product and a person at WEM has checked it. These are NOT offers for the product asked about: never merge them into `offers`, never call one this product's lowest price or the best deal. On verify_offer they are not part of the check: `verdict`, `cheapest`, `betterBy`, `summary` and the receipt are about the product asked about, and a cheaper sister code never makes the claimed price wrong. Mention it as a separate line: quote `summary`, name the maker's page (`maker.host`) as the source, and link `url`, WEM's comparison for that model, not a shop. When `relation` is `differs`, name the `differences` and never call its price a saving. Absent is not evidence that no equivalent exists."New value: +"Present only when the maker's own page says another model code is this product and a person at WEM has checked it. These are NOT offers for the product asked about: they are not part of `offers`, and none is this product's lowest price or the best deal. On verify_offer they are not part of the check: `verdict`, `cheapest`, `betterBy`, `summary` and the receipt are about the product asked about, and a cheaper sister code never makes the claimed price wrong. `summary` is written to be quoted as it is. `maker.host` is the source of the claim. `url` is WEM's comparison for that model, not a shop. When `relation` is `differs`, the `differences` are what the maker says differs, and its price is not a saving. Absent is not evidence that no equivalent exists."
      • changedOutput schema / properties / sameModel / items / properties / cheapest / description
        Previous value: -"The other model's cheapest named shop. Null when no named shop has an in-stock price for it. Give its age; never present it as current without one."New value: +"The other model's cheapest named shop. Null when no named shop has an in-stock price for it. `priceAgeDays` gives its age; without one it is not current."
      • changedOutput schema / properties / sameModel / items / properties / maker / description
        Previous value: -"The maker's own page that says so: the proof. Cite it; WEM is not the source of the claim."New value: +"The maker's own page that says so: the proof. WEM is not the source of the claim."
      • changedOutput schema / properties / sameModel / items / properties / url / description
        Previous value: -"WEM's comparison for that model. Link this, not a shop."New value: +"WEM's comparison for that model, not a shop."
  7. 1 tool update
    • Changedcompare_offers2 fields changed
      • changedInput schema / properties / currency / description
        Previous value: -"ISO 4217 code for the shopper's market. Default GBP. Decides which retailers are searched, not just how the answer reads — pass it explicitly, because WEM does not infer the market from IP. When WEM holds the product only in another currency it says so rather than presenting a foreign listing as the answer."New value: +"ISO 4217 code for the shopper's market. Default GBP. Decides which market's offers WEM returns from its catalogue, not just how the answer reads — pass it explicitly, because WEM does not infer the market from IP. When WEM holds the product only in another currency it says so rather than presenting a foreign listing as the answer."
      • changedOutput schema / properties / links / description
        Previous value: -"The tracked links from `offers`, cheapest first, pre-formatted to quote. Give these to the user when you name an offer: they carry the attribution WEM is funded by, and a retailer URL you compose yourself does not. Present even when the host renders a WEM card — never assume the card reached the user."New value: +"The links from `offers`, cheapest first, pre-formatted to quote. Each opens the retailer’s page for the offer WEM priced; a retailer URL found elsewhere may be a different listing or price. State them in text even when the host renders a WEM card: the card may not reach the user."
  8. 7 tool updates
    • Changedcompare_offers13 fields changed
      • addedOutput schema / properties / highPrice / description
        Added value: +"Highest current price in `offers`; null with lowPrice."
      • changedOutput schema / properties / links / items / properties / currency / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
      • addedOutput schema / properties / links / items / properties / price / description
        Added value: +"Null for a listing in `unpriced`: its markdown says \"see price at Amazon\", and so must you."
      • changedOutput schema / properties / links / items / properties / price / type
        Previous value: -"number"New value: +[
        +  "number",
        +  "null"
        +]
      • addedOutput schema / properties / lowPrice / description
        Added value: +"Lowest CURRENT price in `offers` (read within 14 days). Null when no price is current or WEM holds none it may quote — never fill it from a stale or undated row, or from `unpriced`."
      • changedOutput schema / properties / offers / description
        Previous value: -"Ascending by price. Barcode, slug and WEM ID rows are the product. A title match is inferred — check identity.strength before stating it as exact."New value: +"Current prices first (`priceStatus`), each group ascending by price; a stale or undated row is listed, never compared. Barcode, slug and WEM ID rows are the product. A title match is inferred — check identity.strength before stating it as exact."
      • changedOutput schema / properties / offers / items / properties / lastSeenAt / description
        Previous value: -"When WEM last VISITED this offer row — not when it read the price. The refresh sweep touches this even when the retailer lookup fails, so it is not evidence the price is current. Use `priceAgeDays` to date a price; never this."New value: +"When WEM last READ this price from the retailer or a datafeed — the same reading `priceAgeDays` counts from, so the two always agree. Null means WEM cannot date the price: say it is undated, never that it is current."
      • changedOutput schema / properties / offers / items / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."
      • changedOutput schema / properties / offers / items / properties / price / type
        Previous value: -"number"New value: +[
        +  "number",
        +  "null"
        +]
      • changedOutput schema / properties / offers / items / properties / priceAgeDays / description
        Previous value: -"Whole days since WEM last actually READ this price from the retailer or a datafeed. Null means WEM cannot say — common and correct for Amazon, whose licence caps price retention at 24 hours. Report null as undated; never present it as current."New value: +"Calendar days (UK time) since WEM last READ this price: 0 read today, 1 yesterday. Null means WEM cannot say. Report null as undated; never present it as current."
      • addedOutput schema / properties / offers / items / properties / priceNote
        Added value: +{
        +  "description": "Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / offers / items / properties / priceStatus
        Added value: +{
        +  "description": "`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now.",
        +  "enum": [
        +    "current",
        +    "stale",
        +    "undated"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / unpriced
        Added value: +{
        +  "description": "Listings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. Give the link with `priceNote` (\"See price at Amazon\"). Never state, estimate or compare a price for one, never call it the cheapest, and never count it in a lowest price or a saving.",
        +  "items": {
        +    "properties": {
        +      "channel": {
        +        "enum": [
        +          "retailer",
        +          "marketplace"
        +        ],
        +        "type": "string"
        +      },
        +      "id": {
        +        "type": "string"
        +      },
        +      "priceNote": {
        +        "description": "What to show where a price would be, e.g. \"See price at Amazon\".",
        +        "type": "string"
        +      },
        +      "provider": {
        +        "type": "string"
        +      },
        +      "title": {
        +        "type": "string"
        +      },
        +      "url": {
        +        "description": "WEM tracked link. Relay it exactly.",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedcompare_products4 fields changed
      • changedOutput schema / properties / comparison / items / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."
      • changedOutput schema / properties / comparison / items / properties / price / type
        Previous value: -"number"New value: +[
        +  "number",
        +  "null"
        +]
      • addedOutput schema / properties / comparison / items / properties / priceNote
        Added value: +{
        +  "description": "Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / comparison / items / properties / priceStatus
        Added value: +{
        +  "description": "`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now.",
        +  "enum": [
        +    "current",
        +    "stale",
        +    "undated"
        +  ],
        +  "type": "string"
        +}
    • Changedfind_lowest_price16 fields changed
      • changedOutput schema / properties / alternatives / items / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."
      • changedOutput schema / properties / alternatives / items / properties / price / type
        Previous value: -"number"New value: +[
        +  "number",
        +  "null"
        +]
      • addedOutput schema / properties / alternatives / items / properties / priceNote
        Added value: +{
        +  "description": "Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / alternatives / items / properties / priceStatus
        Added value: +{
        +  "description": "`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now.",
        +  "enum": [
        +    "current",
        +    "stale",
        +    "undated"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / catalogMatch / properties / lowPrice / description
        Added value: +"Lowest CURRENT price in `offers` (priceStatus `current`). Null when none is current: never fill it from an older or undated row."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / lastSeenAt / description
        Previous value: -"When WEM last VISITED this offer row — not when it read the price. The refresh sweep touches this even when the retailer lookup fails, so it is not evidence the price is current. Use `priceAgeDays` to date a price; never this."New value: +"When WEM last READ this price from the retailer or a datafeed — the same reading `priceAgeDays` counts from, so the two always agree. Null means WEM cannot date the price: say it is undated, never that it is current."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / price / type
        Previous value: -"number"New value: +[
        +  "number",
        +  "null"
        +]
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceAgeDays / description
        Previous value: -"Whole days since WEM last actually READ this price from the retailer or a datafeed. Null means WEM cannot say — common and correct for Amazon, whose licence caps price retention at 24 hours. Report null as undated; never present it as current."New value: +"Calendar days (UK time) since WEM last READ this price: 0 read today, 1 yesterday. Null means WEM cannot say. Report null as undated; never present it as current."
      • addedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceNote
        Added value: +{
        +  "description": "Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceStatus
        Added value: +{
        +  "description": "`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now.",
        +  "enum": [
        +    "current",
        +    "stale",
        +    "undated"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / catalogMatch / properties / unpriced
        Added value: +{
        +  "description": "Listings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. Give the link with `priceNote` (\"See price at Amazon\"). Never state, estimate or compare a price for one, never call it the cheapest, and never count it in a lowest price or a saving.",
        +  "items": {
        +    "properties": {
        +      "channel": {
        +        "enum": [
        +          "retailer",
        +          "marketplace"
        +        ],
        +        "type": "string"
        +      },
        +      "id": {
        +        "type": "string"
        +      },
        +      "priceNote": {
        +        "description": "What to show where a price would be, e.g. \"See price at Amazon\".",
        +        "type": "string"
        +      },
        +      "provider": {
        +        "type": "string"
        +      },
        +      "title": {
        +        "type": "string"
        +      },
        +      "url": {
        +        "description": "WEM tracked link. Relay it exactly.",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / recommendation / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."
      • changedOutput schema / properties / recommendation / properties / price / type
        Previous value: -"number"New value: +[
        +  "number",
        +  "null"
        +]
      • addedOutput schema / properties / recommendation / properties / priceNote
        Added value: +{
        +  "description": "Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / recommendation / properties / priceStatus
        Added value: +{
        +  "description": "`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now.",
        +  "enum": [
        +    "current",
        +    "stale",
        +    "undated"
        +  ],
        +  "type": "string"
        +}
    • Changedget_product4 fields changed
      • changedOutput schema / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."
      • changedOutput schema / properties / price / type
        Previous value: -"number"New value: +[
        +  "number",
        +  "null"
        +]
      • addedOutput schema / properties / priceNote
        Added value: +{
        +  "description": "Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / priceStatus
        Added value: +{
        +  "description": "`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now.",
        +  "enum": [
        +    "current",
        +    "stale",
        +    "undated"
        +  ],
        +  "type": "string"
        +}
    • Changedlookup_products1 field changed
      • changedOutput schema / properties / results / items / properties / lowPrice / description
        Previous value: -"Lowest indicative price at a named retailer in `currency`. Null when WEM holds the product only in another currency (see heldInCurrencies) — never convert one yourself — or only as marketplace listings."New value: +"Lowest current indicative price (read within 14 days) at a named retailer in `currency`. Null when WEM holds the product only in another currency (see heldInCurrencies) — never convert one yourself — only as marketplace listings, or with no current price (see note)."
    • Changedsearch_products21 fields changed
      • addedOutput schema / properties / catalogMatch / properties / lowPrice / description
        Added value: +"Lowest CURRENT price in `offers` (priceStatus `current`). Null when none is current: never fill it from an older or undated row."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / lastSeenAt / description
        Previous value: -"When WEM last VISITED this offer row — not when it read the price. The refresh sweep touches this even when the retailer lookup fails, so it is not evidence the price is current. Use `priceAgeDays` to date a price; never this."New value: +"When WEM last READ this price from the retailer or a datafeed — the same reading `priceAgeDays` counts from, so the two always agree. Null means WEM cannot date the price: say it is undated, never that it is current."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / price / type
        Previous value: -"number"New value: +[
        +  "number",
        +  "null"
        +]
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceAgeDays / description
        Previous value: -"Whole days since WEM last actually READ this price from the retailer or a datafeed. Null means WEM cannot say — common and correct for Amazon, whose licence caps price retention at 24 hours. Report null as undated; never present it as current."New value: +"Calendar days (UK time) since WEM last READ this price: 0 read today, 1 yesterday. Null means WEM cannot say. Report null as undated; never present it as current."
      • addedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceNote
        Added value: +{
        +  "description": "Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceStatus
        Added value: +{
        +  "description": "`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now.",
        +  "enum": [
        +    "current",
        +    "stale",
        +    "undated"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / catalogMatch / properties / unpriced
        Added value: +{
        +  "description": "Listings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. Give the link with `priceNote` (\"See price at Amazon\"). Never state, estimate or compare a price for one, never call it the cheapest, and never count it in a lowest price or a saving.",
        +  "items": {
        +    "properties": {
        +      "channel": {
        +        "enum": [
        +          "retailer",
        +          "marketplace"
        +        ],
        +        "type": "string"
        +      },
        +      "id": {
        +        "type": "string"
        +      },
        +      "priceNote": {
        +        "description": "What to show where a price would be, e.g. \"See price at Amazon\".",
        +        "type": "string"
        +      },
        +      "provider": {
        +        "type": "string"
        +      },
        +      "title": {
        +        "type": "string"
        +      },
        +      "url": {
        +        "description": "WEM tracked link. Relay it exactly.",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / catalogMatches / items / properties / lowPrice / description
        Added value: +"Lowest CURRENT price in `offers` (priceStatus `current`). Null when none is current: never fill it from an older or undated row."
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / lastSeenAt / description
        Previous value: -"When WEM last VISITED this offer row — not when it read the price. The refresh sweep touches this even when the retailer lookup fails, so it is not evidence the price is current. Use `priceAgeDays` to date a price; never this."New value: +"When WEM last READ this price from the retailer or a datafeed — the same reading `priceAgeDays` counts from, so the two always agree. Null means WEM cannot date the price: say it is undated, never that it is current."
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / price / type
        Previous value: -"number"New value: +[
        +  "number",
        +  "null"
        +]
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / priceAgeDays / description
        Previous value: -"Whole days since WEM last actually READ this price from the retailer or a datafeed. Null means WEM cannot say — common and correct for Amazon, whose licence caps price retention at 24 hours. Report null as undated; never present it as current."New value: +"Calendar days (UK time) since WEM last READ this price: 0 read today, 1 yesterday. Null means WEM cannot say. Report null as undated; never present it as current."
      • addedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / priceNote
        Added value: +{
        +  "description": "Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / priceStatus
        Added value: +{
        +  "description": "`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now.",
        +  "enum": [
        +    "current",
        +    "stale",
        +    "undated"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / catalogMatches / items / properties / unpriced
        Added value: +{
        +  "description": "Listings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. Give the link with `priceNote` (\"See price at Amazon\"). Never state, estimate or compare a price for one, never call it the cheapest, and never count it in a lowest price or a saving.",
        +  "items": {
        +    "properties": {
        +      "channel": {
        +        "enum": [
        +          "retailer",
        +          "marketplace"
        +        ],
        +        "type": "string"
        +      },
        +      "id": {
        +        "type": "string"
        +      },
        +      "priceNote": {
        +        "description": "What to show where a price would be, e.g. \"See price at Amazon\".",
        +        "type": "string"
        +      },
        +      "provider": {
        +        "type": "string"
        +      },
        +      "title": {
        +        "type": "string"
        +      },
        +      "url": {
        +        "description": "WEM tracked link. Relay it exactly.",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / products / items / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."
      • changedOutput schema / properties / products / items / properties / price / type
        Previous value: -"number"New value: +[
        +  "number",
        +  "null"
        +]
      • addedOutput schema / properties / products / items / properties / priceNote
        Added value: +{
        +  "description": "Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / products / items / properties / priceStatus
        Added value: +{
        +  "description": "`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now.",
        +  "enum": [
        +    "current",
        +    "stale",
        +    "undated"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / unpriced
        Added value: +{
        +  "description": "Listings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. Give the link with `priceNote` (\"See price at Amazon\"). Never state, estimate or compare a price for one, never call it the cheapest, and never count it in a lowest price or a saving.",
        +  "items": {
        +    "properties": {
        +      "channel": {
        +        "enum": [
        +          "retailer",
        +          "marketplace"
        +        ],
        +        "type": "string"
        +      },
        +      "id": {
        +        "type": "string"
        +      },
        +      "priceNote": {
        +        "description": "What to show where a price would be, e.g. \"See price at Amazon\".",
        +        "type": "string"
        +      },
        +      "provider": {
        +        "type": "string"
        +      },
        +      "title": {
        +        "type": "string"
        +      },
        +      "url": {
        +        "description": "WEM tracked link. Relay it exactly.",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedsemantic_search12 fields changed
      • addedOutput schema / properties / catalogMatch / properties / lowPrice / description
        Added value: +"Lowest CURRENT price in `offers` (priceStatus `current`). Null when none is current: never fill it from an older or undated row."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / lastSeenAt / description
        Previous value: -"When WEM last VISITED this offer row — not when it read the price. The refresh sweep touches this even when the retailer lookup fails, so it is not evidence the price is current. Use `priceAgeDays` to date a price; never this."New value: +"When WEM last READ this price from the retailer or a datafeed — the same reading `priceAgeDays` counts from, so the two always agree. Null means WEM cannot date the price: say it is undated, never that it is current."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / price / type
        Previous value: -"number"New value: +[
        +  "number",
        +  "null"
        +]
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceAgeDays / description
        Previous value: -"Whole days since WEM last actually READ this price from the retailer or a datafeed. Null means WEM cannot say — common and correct for Amazon, whose licence caps price retention at 24 hours. Report null as undated; never present it as current."New value: +"Calendar days (UK time) since WEM last READ this price: 0 read today, 1 yesterday. Null means WEM cannot say. Report null as undated; never present it as current."
      • addedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceNote
        Added value: +{
        +  "description": "Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceStatus
        Added value: +{
        +  "description": "`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now.",
        +  "enum": [
        +    "current",
        +    "stale",
        +    "undated"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / catalogMatch / properties / unpriced
        Added value: +{
        +  "description": "Listings whose price WEM may not show — today, Amazon rows Amazon’s API did not price just now. Give the link with `priceNote` (\"See price at Amazon\"). Never state, estimate or compare a price for one, never call it the cheapest, and never count it in a lowest price or a saving.",
        +  "items": {
        +    "properties": {
        +      "channel": {
        +        "enum": [
        +          "retailer",
        +          "marketplace"
        +        ],
        +        "type": "string"
        +      },
        +      "id": {
        +        "type": "string"
        +      },
        +      "priceNote": {
        +        "description": "What to show where a price would be, e.g. \"See price at Amazon\".",
        +        "type": "string"
        +      },
        +      "provider": {
        +        "type": "string"
        +      },
        +      "title": {
        +        "type": "string"
        +      },
        +      "url": {
        +        "description": "WEM tracked link. Relay it exactly.",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / products / items / properties / price / description
        Previous value: -"Indicative price. The retailer sets the final price at checkout."New value: +"Indicative price. The retailer sets the final price at checkout. Null, with `priceNote`, when WEM may not show this listing’s price: show the note and the link, never a figure of your own."
      • changedOutput schema / properties / products / items / properties / price / type
        Previous value: -"number"New value: +[
        +  "number",
        +  "null"
        +]
      • addedOutput schema / properties / products / items / properties / priceNote
        Added value: +{
        +  "description": "Present only when `price` is null: the words to show in its place, e.g. \"See price at Amazon\". An Amazon price is shown only when Amazon’s API supplied it just now.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / products / items / properties / priceStatus
        Added value: +{
        +  "description": "`current`: WEM read this price within the last 14 days; only a current price may lead, be called the cheapest or lowest, be compared or enter a saving. `stale`: read longer ago. `undated`: WEM cannot say when. Show those two as \"last seen £X on 8 Sep\" or \"price not dated\", after the current ones, and never compare them. Absent on a row a provider answered just now.",
        +  "enum": [
        +    "current",
        +    "stale",
        +    "undated"
        +  ],
        +  "type": "string"
        +}
  9. 7 tool updates
    • Changedcompare_offers2 fields changed
      • addedOutput schema / properties / filtered
        Added value: +{
        +  "additionalProperties": {
        +    "type": "number"
        +  },
        +  "description": "Offers of this product WEM held back, tallied by reason. \"Priced far below this product’s other offers\" is a marketplace listing under 40% of what the product sells for elsewhere — the shape of a counterfeit, a part or a mislisted variant. Those prices are not in `offers`, `lowPrice`, `links`, `summary` or `priceHistory.low`: never quote one as the cheapest, a deal or the 90-day low. Say how many were held back.",
        +  "type": [
        +    "object",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / offers / items / properties / affiliate / description
        Previous value: -"False when this is a retailer page WEM observed without a programme. Still a real listing; the click is not commission-bearing. Absent means the usual partner path."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."
    • Changedcompare_products1 field changed
      • changedOutput schema / properties / comparison / items / properties / affiliate / description
        Previous value: -"False when this is a retailer page WEM observed without a programme. Still a real listing; the click is not commission-bearing. Absent means the usual partner path."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."
    • Changedfind_lowest_price4 fields changed
      • changedOutput schema / properties / alternatives / items / properties / affiliate / description
        Previous value: -"False when this is a retailer page WEM observed without a programme. Still a real listing; the click is not commission-bearing. Absent means the usual partner path."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / affiliate / description
        Previous value: -"False when this is a retailer page WEM observed without a programme. Still a real listing; the click is not commission-bearing. Absent means the usual partner path."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."
      • changedOutput schema / properties / filtered / description
        Previous value: -"Withheld candidates tallied by reason (e.g. accessories, wrong model). Report this count rather than implying the search was exhaustive."New value: +"Withheld candidates tallied by reason (e.g. accessories, another model, a bundle or multipack, a replica, a listing priced far below the product’s other offers). Report this count rather than implying the search was exhaustive, and never quote a withheld listing’s price as the cheapest or as a deal."
      • changedOutput schema / properties / recommendation / properties / affiliate / description
        Previous value: -"False when this is a retailer page WEM observed without a programme. Still a real listing; the click is not commission-bearing. Absent means the usual partner path."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."
    • Changedget_product1 field changed
      • changedOutput schema / properties / affiliate / description
        Previous value: -"False when this is a retailer page WEM observed without a programme. Still a real listing; the click is not commission-bearing. Absent means the usual partner path."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."
    • Changedsearch_products4 fields changed
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / affiliate / description
        Previous value: -"False when this is a retailer page WEM observed without a programme. Still a real listing; the click is not commission-bearing. Absent means the usual partner path."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / affiliate / description
        Previous value: -"False when this is a retailer page WEM observed without a programme. Still a real listing; the click is not commission-bearing. Absent means the usual partner path."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."
      • changedOutput schema / properties / filtered / description
        Previous value: -"Withheld candidates tallied by reason (e.g. accessories, wrong model). Report this count rather than implying the search was exhaustive."New value: +"Withheld candidates tallied by reason (e.g. accessories, another model, a bundle or multipack, a replica, a listing priced far below the product’s other offers). Report this count rather than implying the search was exhaustive, and never quote a withheld listing’s price as the cheapest or as a deal."
      • changedOutput schema / properties / products / items / properties / affiliate / description
        Previous value: -"False when this is a retailer page WEM observed without a programme. Still a real listing; the click is not commission-bearing. Absent means the usual partner path."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."
    • Changedsemantic_search3 fields changed
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / affiliate / description
        Previous value: -"False when this is a retailer page WEM observed without a programme. Still a real listing; the click is not commission-bearing. Absent means the usual partner path."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."
      • changedOutput schema / properties / filtered / description
        Previous value: -"Withheld candidates tallied by reason (e.g. accessories, wrong model). Report this count rather than implying the search was exhaustive."New value: +"Withheld candidates tallied by reason (e.g. accessories, another model, a bundle or multipack, a replica, a listing priced far below the product’s other offers). Report this count rather than implying the search was exhaustive, and never quote a withheld listing’s price as the cheapest or as a deal."
      • changedOutput schema / properties / products / items / properties / affiliate / description
        Previous value: -"False when this is a retailer page WEM observed without a programme. Still a real listing; the click is not commission-bearing. Absent means the usual partner path."New value: +"False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording."
    • Changedverify_offer3 fields changed
      • addedOutput schema / properties / cheapest / properties / affiliate
        Added value: +{
        +  "description": "False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording.",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / claimMatched / properties / affiliate
        Added value: +{
        +  "description": "False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording.",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / offers / items / properties / affiliate
        Added value: +{
        +  "description": "False when this link earns WEM nothing: the shop has no affiliate programme with WEM, or this link does not carry one. Still a real offer: list it with the others, and never call its link affiliate-tracked. Absent (or true) means the link is affiliate-tracked. `disclosure` already states whether all, some or none of the links are tracked; relay that rather than your own wording.",
        +  "type": "boolean"
        +}
  10. 1 tool update
    • Changedverify_offer1 field changed
      • addedOutput schema / properties / offers / description
        Added value: +"Prices WEM holds for this product, including indicative ones and shops it has no affiliate programme with yet. When `cheapest` is null, still show these rows and their links: they are a comparison, not a verification. Do not call them confirmed, and do not name a verified cheapest."
  11. 4 tool updates
    • Changedcompare_offers2 fields changed
      • changedOutput schema / properties / offers / items / properties / priceRefresh / description
        Previous value: -"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `crawl` WEM reading the retailer’s own public product page, `none` nothing at all. `none` means the figure is frozen at whatever seeded it and will not move however long it sits — say so rather than quoting it flat. A `crawl` price was observed on the retailer’s page rather than supplied by them, so date it with `priceAgeDays` and expect `affiliate: false` unless a programme also exists."New value: +"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `none` nothing on a schedule. `none` means the figure will not move on its own however long it sits — say so rather than quoting it flat, and date it with `priceAgeDays`."
      • changedOutput schema / properties / offers / items / properties / priceRefresh / enum
        Previous value: -[
        -  "live-api",
        -  "feed",
        -  "crawl",
        -  "none"
        -]New value: +[
        +  "live-api",
        +  "feed",
        +  "none"
        +]
    • Changedfind_lowest_price2 fields changed
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceRefresh / description
        Previous value: -"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `crawl` WEM reading the retailer’s own public product page, `none` nothing at all. `none` means the figure is frozen at whatever seeded it and will not move however long it sits — say so rather than quoting it flat. A `crawl` price was observed on the retailer’s page rather than supplied by them, so date it with `priceAgeDays` and expect `affiliate: false` unless a programme also exists."New value: +"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `none` nothing on a schedule. `none` means the figure will not move on its own however long it sits — say so rather than quoting it flat, and date it with `priceAgeDays`."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceRefresh / enum
        Previous value: -[
        -  "live-api",
        -  "feed",
        -  "crawl",
        -  "none"
        -]New value: +[
        +  "live-api",
        +  "feed",
        +  "none"
        +]
    • Changedsearch_products4 fields changed
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceRefresh / description
        Previous value: -"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `crawl` WEM reading the retailer’s own public product page, `none` nothing at all. `none` means the figure is frozen at whatever seeded it and will not move however long it sits — say so rather than quoting it flat. A `crawl` price was observed on the retailer’s page rather than supplied by them, so date it with `priceAgeDays` and expect `affiliate: false` unless a programme also exists."New value: +"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `none` nothing on a schedule. `none` means the figure will not move on its own however long it sits — say so rather than quoting it flat, and date it with `priceAgeDays`."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceRefresh / enum
        Previous value: -[
        -  "live-api",
        -  "feed",
        -  "crawl",
        -  "none"
        -]New value: +[
        +  "live-api",
        +  "feed",
        +  "none"
        +]
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / priceRefresh / description
        Previous value: -"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `crawl` WEM reading the retailer’s own public product page, `none` nothing at all. `none` means the figure is frozen at whatever seeded it and will not move however long it sits — say so rather than quoting it flat. A `crawl` price was observed on the retailer’s page rather than supplied by them, so date it with `priceAgeDays` and expect `affiliate: false` unless a programme also exists."New value: +"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `none` nothing on a schedule. `none` means the figure will not move on its own however long it sits — say so rather than quoting it flat, and date it with `priceAgeDays`."
      • changedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / priceRefresh / enum
        Previous value: -[
        -  "live-api",
        -  "feed",
        -  "crawl",
        -  "none"
        -]New value: +[
        +  "live-api",
        +  "feed",
        +  "none"
        +]
    • Changedsemantic_search2 fields changed
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceRefresh / description
        Previous value: -"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `crawl` WEM reading the retailer’s own public product page, `none` nothing at all. `none` means the figure is frozen at whatever seeded it and will not move however long it sits — say so rather than quoting it flat. A `crawl` price was observed on the retailer’s page rather than supplied by them, so date it with `priceAgeDays` and expect `affiliate: false` unless a programme also exists."New value: +"What re-reads this retailer’s prices: `live-api` a product-lookup API, `feed` a partner datafeed, `none` nothing on a schedule. `none` means the figure will not move on its own however long it sits — say so rather than quoting it flat, and date it with `priceAgeDays`."
      • changedOutput schema / properties / catalogMatch / properties / offers / items / properties / priceRefresh / enum
        Previous value: -[
        -  "live-api",
        -  "feed",
        -  "crawl",
        -  "none"
        -]New value: +[
        +  "live-api",
        +  "feed",
        +  "none"
        +]
  12. 2 tool updates
    • Changedcompare_offers1 field changed
      • changedOutput schema / properties / sameModel / description
        Previous value: -"Present only when the maker's own page says another model code is this product and a person at WEM has checked it. These are NOT offers for the product asked about: never merge them into `offers`, never call one this product's lowest price or the best deal, and never let one change a verify_offer verdict. Mention it as a separate line: quote `summary`, name the maker's page (`maker.host`) as the source, and link `url`, WEM's comparison for that model, not a shop. When `relation` is `differs`, name the `differences` and never call its price a saving. Absent means WEM holds no checked equivalent, not that none exists."New value: +"Present only when the maker's own page says another model code is this product and a person at WEM has checked it. These are NOT offers for the product asked about: never merge them into `offers`, never call one this product's lowest price or the best deal. On verify_offer they are not part of the check: `verdict`, `cheapest`, `betterBy`, `summary` and the receipt are about the product asked about, and a cheaper sister code never makes the claimed price wrong. Mention it as a separate line: quote `summary`, name the maker's page (`maker.host`) as the source, and link `url`, WEM's comparison for that model, not a shop. When `relation` is `differs`, name the `differences` and never call its price a saving. Absent is not evidence that no equivalent exists."
    • Changedverify_offer1 field changed
      • addedOutput schema / properties / sameModel
        Added value: +{
        +  "description": "Present only when the maker's own page says another model code is this product and a person at WEM has checked it. These are NOT offers for the product asked about: never merge them into `offers`, never call one this product's lowest price or the best deal. On verify_offer they are not part of the check: `verdict`, `cheapest`, `betterBy`, `summary` and the receipt are about the product asked about, and a cheaper sister code never makes the claimed price wrong. Mention it as a separate line: quote `summary`, name the maker's page (`maker.host`) as the source, and link `url`, WEM's comparison for that model, not a shop. When `relation` is `differs`, name the `differences` and never call its price a saving. Absent is not evidence that no equivalent exists.",
        +  "items": {
        +    "properties": {
        +      "cheapest": {
        +        "description": "The other model's cheapest named shop. Null when no named shop has an in-stock price for it. Give its age; never present it as current without one.",
        +        "properties": {
        +          "currency": {
        +            "type": "string"
        +          },
        +          "price": {
        +            "type": "number"
        +          },
        +          "priceAgeDays": {
        +            "description": "Days since WEM read that price. Null means undated.",
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "shop": {
        +            "type": "string"
        +          }
        +        },
        +        "type": [
        +          "object",
        +          "null"
        +        ]
        +      },
        +      "checkedOn": {
        +        "description": "When a person at WEM read the maker’s page (YYYY-MM-DD).",
        +        "type": "string"
        +      },
        +      "differences": {
        +        "description": "What the maker says differs. Empty when identical.",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "maker": {
        +        "description": "The maker's own page that says so: the proof. Cite it; WEM is not the source of the claim.",
        +        "properties": {
        +          "host": {
        +            "type": "string"
        +          },
        +          "says": {
        +            "description": "The page's words, as checked.",
        +            "type": "string"
        +          },
        +          "url": {
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "model": {
        +        "description": "The other model code, as the maker writes it.",
        +        "type": "string"
        +      },
        +      "relation": {
        +        "description": "`identical`: the maker says it is the same product. `differs`: the same product except `differences`; not like for like.",
        +        "enum": [
        +          "identical",
        +          "differs"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "WEM’s words for it, written to be quoted as they are.",
        +        "type": "string"
        +      },
        +      "url": {
        +        "description": "WEM's comparison for that model. Link this, not a shop.",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      }
        +    },
        +    "required": [
        +      "model",
        +      "relation",
        +      "differences",
        +      "maker",
        +      "checkedOn",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
  13. 1 tool update
    • Changedcompare_offers1 field changed
      • addedOutput schema / properties / sameModel
        Added value: +{
        +  "description": "Present only when the maker's own page says another model code is this product and a person at WEM has checked it. These are NOT offers for the product asked about: never merge them into `offers`, never call one this product's lowest price or the best deal, and never let one change a verify_offer verdict. Mention it as a separate line: quote `summary`, name the maker's page (`maker.host`) as the source, and link `url`, WEM's comparison for that model, not a shop. When `relation` is `differs`, name the `differences` and never call its price a saving. Absent means WEM holds no checked equivalent, not that none exists.",
        +  "items": {
        +    "properties": {
        +      "cheapest": {
        +        "description": "The other model's cheapest named shop. Null when no named shop has an in-stock price for it. Give its age; never present it as current without one.",
        +        "properties": {
        +          "currency": {
        +            "type": "string"
        +          },
        +          "price": {
        +            "type": "number"
        +          },
        +          "priceAgeDays": {
        +            "description": "Days since WEM read that price. Null means undated.",
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "shop": {
        +            "type": "string"
        +          }
        +        },
        +        "type": [
        +          "object",
        +          "null"
        +        ]
        +      },
        +      "checkedOn": {
        +        "description": "When a person at WEM read the maker’s page (YYYY-MM-DD).",
        +        "type": "string"
        +      },
        +      "differences": {
        +        "description": "What the maker says differs. Empty when identical.",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "maker": {
        +        "description": "The maker's own page that says so: the proof. Cite it; WEM is not the source of the claim.",
        +        "properties": {
        +          "host": {
        +            "type": "string"
        +          },
        +          "says": {
        +            "description": "The page's words, as checked.",
        +            "type": "string"
        +          },
        +          "url": {
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "model": {
        +        "description": "The other model code, as the maker writes it.",
        +        "type": "string"
        +      },
        +      "relation": {
        +        "description": "`identical`: the maker says it is the same product. `differs`: the same product except `differences`; not like for like.",
        +        "enum": [
        +          "identical",
        +          "differs"
        +        ],
        +        "type": "string"
        +      },
        +      "summary": {
        +        "description": "WEM’s words for it, written to be quoted as they are.",
        +        "type": "string"
        +      },
        +      "url": {
        +        "description": "WEM's comparison for that model. Link this, not a shop.",
        +        "type": [
        +          "string",
        +          "null"
        +        ]
        +      }
        +    },
        +    "required": [
        +      "model",
        +      "relation",
        +      "differences",
        +      "maker",
        +      "checkedOn",
        +      "summary"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
  14. 6 tool updates
    • Changedcompare_offers1 field changed
      • addedOutput schema / properties / offers / items / properties / unitPrice
        Added value: +{
        +  "description": "Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit.",
        +  "properties": {
        +    "amount": {
        +      "type": "number"
        +    },
        +    "currency": {
        +      "description": "ISO 4217 code.",
        +      "type": "string"
        +    },
        +    "per": {
        +      "enum": [
        +        "100ml",
        +        "litre",
        +        "100g",
        +        "kg",
        +        "item"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedcompare_products1 field changed
      • addedOutput schema / properties / comparison / items / properties / unitPrice
        Added value: +{
        +  "description": "Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit.",
        +  "properties": {
        +    "amount": {
        +      "type": "number"
        +    },
        +    "currency": {
        +      "description": "ISO 4217 code.",
        +      "type": "string"
        +    },
        +    "per": {
        +      "enum": [
        +        "100ml",
        +        "litre",
        +        "100g",
        +        "kg",
        +        "item"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedfind_lowest_price3 fields changed
      • addedOutput schema / properties / alternatives / items / properties / unitPrice
        Added value: +{
        +  "description": "Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit.",
        +  "properties": {
        +    "amount": {
        +      "type": "number"
        +    },
        +    "currency": {
        +      "description": "ISO 4217 code.",
        +      "type": "string"
        +    },
        +    "per": {
        +      "enum": [
        +        "100ml",
        +        "litre",
        +        "100g",
        +        "kg",
        +        "item"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / catalogMatch / properties / offers / items / properties / unitPrice
        Added value: +{
        +  "description": "Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit.",
        +  "properties": {
        +    "amount": {
        +      "type": "number"
        +    },
        +    "currency": {
        +      "description": "ISO 4217 code.",
        +      "type": "string"
        +    },
        +    "per": {
        +      "enum": [
        +        "100ml",
        +        "litre",
        +        "100g",
        +        "kg",
        +        "item"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / recommendation / properties / unitPrice
        Added value: +{
        +  "description": "Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit.",
        +  "properties": {
        +    "amount": {
        +      "type": "number"
        +    },
        +    "currency": {
        +      "description": "ISO 4217 code.",
        +      "type": "string"
        +    },
        +    "per": {
        +      "enum": [
        +        "100ml",
        +        "litre",
        +        "100g",
        +        "kg",
        +        "item"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedget_product1 field changed
      • addedOutput schema / properties / unitPrice
        Added value: +{
        +  "description": "Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit.",
        +  "properties": {
        +    "amount": {
        +      "type": "number"
        +    },
        +    "currency": {
        +      "description": "ISO 4217 code.",
        +      "type": "string"
        +    },
        +    "per": {
        +      "enum": [
        +        "100ml",
        +        "litre",
        +        "100g",
        +        "kg",
        +        "item"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedsearch_products4 fields changed
      • addedOutput schema / properties / catalogMatch / properties / offers / items / properties / unitPrice
        Added value: +{
        +  "description": "Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit.",
        +  "properties": {
        +    "amount": {
        +      "type": "number"
        +    },
        +    "currency": {
        +      "description": "ISO 4217 code.",
        +      "type": "string"
        +    },
        +    "per": {
        +      "enum": [
        +        "100ml",
        +        "litre",
        +        "100g",
        +        "kg",
        +        "item"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / catalogMatches / items / properties / offers / items / properties / unitPrice
        Added value: +{
        +  "description": "Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit.",
        +  "properties": {
        +    "amount": {
        +      "type": "number"
        +    },
        +    "currency": {
        +      "description": "ISO 4217 code.",
        +      "type": "string"
        +    },
        +    "per": {
        +      "enum": [
        +        "100ml",
        +        "litre",
        +        "100g",
        +        "kg",
        +        "item"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / products / items / properties / unitPrice
        Added value: +{
        +  "description": "Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit.",
        +  "properties": {
        +    "amount": {
        +      "type": "number"
        +    },
        +    "currency": {
        +      "description": "ISO 4217 code.",
        +      "type": "string"
        +    },
        +    "per": {
        +      "enum": [
        +        "100ml",
        +        "litre",
        +        "100g",
        +        "kg",
        +        "item"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / properties / sizeSpread / description
        Previous value: -"Present when the returned rows are different sizes and the query named none, so price ordering is meaningless: the cheapest row is cheapest because it is less of the product. Do NOT name a cheapest, a lowest price, or a best deal across these rows. State the size beside every price and ask the shopper which size they want. The rows are real — give the user those links."New value: +"Present when the returned rows are different sizes and the query named none, so price ordering is meaningless: the cheapest row is cheapest because it is less of the product. Do NOT name a cheapest, a lowest price, or a best deal across these rows. State the size beside every price and ask the shopper which size they want. Where rows carry `unitPrice`, that is the like-for-like figure: quote it, and rank on it if the shopper asks which is better value. The rows are real — give the user those links."
    • Changedsemantic_search2 fields changed
      • addedOutput schema / properties / catalogMatch / properties / offers / items / properties / unitPrice
        Added value: +{
        +  "description": "Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit.",
        +  "properties": {
        +    "amount": {
        +      "type": "number"
        +    },
        +    "currency": {
        +      "description": "ISO 4217 code.",
        +      "type": "string"
        +    },
        +    "per": {
        +      "enum": [
        +        "100ml",
        +        "litre",
        +        "100g",
        +        "kg",
        +        "item"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
      • addedOutput schema / properties / products / items / properties / unitPrice
        Added value: +{
        +  "description": "Price per 100ml, 100g, litre, kg or item, from the size this row's title states. Present only when the rows differ in size, in one unit across all of them, and only for things bought by the amount (beauty, food, supplements), never an appliance's capacity. When comparing value across sizes, compare these, never the prices: a smaller size is not cheaper because its price is lower. Quote it beside the price (\"£29.95, £99.83 per 100ml\"). Absent does not mean the price is per unit.",
        +  "properties": {
        +    "amount": {
        +      "type": "number"
        +    },
        +    "currency": {
        +      "description": "ISO 4217 code.",
        +      "type": "string"
        +    },
        +    "per": {
        +      "enum": [
        +        "100ml",
        +        "litre",
        +        "100g",
        +        "kg",
        +        "item"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
  15. 4 tool updates
    • Changedcompare_offers3 fields changed
      • changedOutput schema / properties / identity / description
        Previous value: -"How the product was identified. Never present a strength of \"inferred\" as a barcode-exact identity."New value: +"How the shopper’s words reached this product. Decides how you describe the match: on `inferred`, say WEM matched it by name (not by barcode) and do not call the identity confirmed, even when `identityBasis` is `barcode`; on `exact`, the barcode itself resolved it."
      • changedOutput schema / properties / identity / properties / strength / description
        Previous value: -"exact = barcode; catalogued = a WEM key or listing id; inferred = matched on the product name and still a guess."New value: +"exact = barcode; catalogued = a WEM key or listing id; inferred = matched on the product name, MPN or SKU and still a guess."
      • addedOutput schema / properties / identityBasis
        Added value: +{
        +  "description": "How this product’s offers are grouped — NOT how the shopper’s words found the product; that is `identity`. `barcode`: the product carries a GTIN, so every offer here is that same item. `curated-grouping`: it carries none, and the grouping is an inference. Never call a result a barcode match on the strength of this field: when `identity.strength` is `inferred`, say WEM matched the product by name.",
        +  "enum": [
        +    "barcode",
        +    "curated-grouping"
        +  ],
        +  "type": "string"
        +}
    • Changedfind_lowest_price3 fields changed
      • changedOutput schema / properties / catalogMatch / description
        Previous value: -"Offers WEM holds under one catalogue product. Check `identityBasis`: on `barcode` these are resolved by GTIN rather than by matching titles, so prefer them and cite their prices over anything in `products`. On `curated-grouping` the product carries no barcode, the grouping is an inference like any title match, and a cheaper row in `products` may well be the same item — see `cheaperElsewhere`."New value: +"Offers WEM holds under one catalogue product. Check `identityBasis`: on `barcode` the product carries a GTIN and every offer here is that same item, so prefer them and cite their prices over anything in `products`. On `curated-grouping` the product carries no barcode, the grouping is an inference like any title match, and a cheaper row in `products` may well be the same item — see `cheaperElsewhere`. Whether the shopper’s words reached this product by barcode or by name is `identity`, a separate question: on `inferred`, say WEM matched it by name."
      • addedOutput schema / properties / catalogMatch / properties / identity
        Added value: +{
        +  "description": "How the shopper’s words reached this product. Decides how you describe the match: on `inferred`, say WEM matched it by name (not by barcode) and do not call the identity confirmed, even when `identityBasis` is `barcode`; on `exact`, the barcode itself resolved it.",
        +  "properties": {
        +    "method": {
        +      "enum": [
        +        "gtin",
        +        "slug",
        +        "listing",
        +        "title"
        +      ],
        +      "type": "string"
        +    },
        +    "strength": {
        +      "description": "exact = barcode; catalogued = a WEM key or listing id; inferred = matched on the product name, MPN or SKU and still a guess.",
        +      "enum": [
        +        "exact",
        +        "catalogued",
        +        "inferred"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": [
        +    "object",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / catalogMatch / properties / identityBasis / description
        Previous value: -"What this block’s identity rests on. `barcode` — the canonical product carries a GTIN and these offers are the same physical item. `curated-grouping` — it carries none, so the grouping is an inference of the same kind a title match is; do not describe it to the user as barcode-confirmed, and do not let it outrank a cheaper row in `products` on price alone."New value: +"What this block’s identity rests on. `barcode` — the canonical product carries a GTIN and these offers are the same physical item. `curated-grouping` — it carries none, so the grouping is an inference of the same kind a title match is; do not describe it to the user as barcode-confirmed, and do not let it outrank a cheaper row in `products` on price alone. This is how the offers are grouped, not how the query matched the product — see `identity`."
    • Changedsearch_products6 fields changed
      • changedOutput schema / properties / catalogMatch / description
        Previous value: -"Offers WEM holds under one catalogue product. Check `identityBasis`: on `barcode` these are resolved by GTIN rather than by matching titles, so prefer them and cite their prices over anything in `products`. On `curated-grouping` the product carries no barcode, the grouping is an inference like any title match, and a cheaper row in `products` may well be the same item — see `cheaperElsewhere`."New value: +"Offers WEM holds under one catalogue product. Check `identityBasis`: on `barcode` the product carries a GTIN and every offer here is that same item, so prefer them and cite their prices over anything in `products`. On `curated-grouping` the product carries no barcode, the grouping is an inference like any title match, and a cheaper row in `products` may well be the same item — see `cheaperElsewhere`. Whether the shopper’s words reached this product by barcode or by name is `identity`, a separate question: on `inferred`, say WEM matched it by name."
      • addedOutput schema / properties / catalogMatch / properties / identity
        Added value: +{
        +  "description": "How the shopper’s words reached this product. Decides how you describe the match: on `inferred`, say WEM matched it by name (not by barcode) and do not call the identity confirmed, even when `identityBasis` is `barcode`; on `exact`, the barcode itself resolved it.",
        +  "properties": {
        +    "method": {
        +      "enum": [
        +        "gtin",
        +        "slug",
        +        "listing",
        +        "title"
        +      ],
        +      "type": "string"
        +    },
        +    "strength": {
        +      "description": "exact = barcode; catalogued = a WEM key or listing id; inferred = matched on the product name, MPN or SKU and still a guess.",
        +      "enum": [
        +        "exact",
        +        "catalogued",
        +        "inferred"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": [
        +    "object",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / catalogMatch / properties / identityBasis / description
        Previous value: -"What this block’s identity rests on. `barcode` — the canonical product carries a GTIN and these offers are the same physical item. `curated-grouping` — it carries none, so the grouping is an inference of the same kind a title match is; do not describe it to the user as barcode-confirmed, and do not let it outrank a cheaper row in `products` on price alone."New value: +"What this block’s identity rests on. `barcode` — the canonical product carries a GTIN and these offers are the same physical item. `curated-grouping` — it carries none, so the grouping is an inference of the same kind a title match is; do not describe it to the user as barcode-confirmed, and do not let it outrank a cheaper row in `products` on price alone. This is how the offers are grouped, not how the query matched the product — see `identity`."
      • changedOutput schema / properties / catalogMatches / items / description
        Previous value: -"Offers WEM holds under one catalogue product. Check `identityBasis`: on `barcode` these are resolved by GTIN rather than by matching titles, so prefer them and cite their prices over anything in `products`. On `curated-grouping` the product carries no barcode, the grouping is an inference like any title match, and a cheaper row in `products` may well be the same item — see `cheaperElsewhere`."New value: +"Offers WEM holds under one catalogue product. Check `identityBasis`: on `barcode` the product carries a GTIN and every offer here is that same item, so prefer them and cite their prices over anything in `products`. On `curated-grouping` the product carries no barcode, the grouping is an inference like any title match, and a cheaper row in `products` may well be the same item — see `cheaperElsewhere`. Whether the shopper’s words reached this product by barcode or by name is `identity`, a separate question: on `inferred`, say WEM matched it by name."
      • addedOutput schema / properties / catalogMatches / items / properties / identity
        Added value: +{
        +  "description": "How the shopper’s words reached this product. Decides how you describe the match: on `inferred`, say WEM matched it by name (not by barcode) and do not call the identity confirmed, even when `identityBasis` is `barcode`; on `exact`, the barcode itself resolved it.",
        +  "properties": {
        +    "method": {
        +      "enum": [
        +        "gtin",
        +        "slug",
        +        "listing",
        +        "title"
        +      ],
        +      "type": "string"
        +    },
        +    "strength": {
        +      "description": "exact = barcode; catalogued = a WEM key or listing id; inferred = matched on the product name, MPN or SKU and still a guess.",
        +      "enum": [
        +        "exact",
        +        "catalogued",
        +        "inferred"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": [
        +    "object",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / catalogMatches / items / properties / identityBasis / description
        Previous value: -"What this block’s identity rests on. `barcode` — the canonical product carries a GTIN and these offers are the same physical item. `curated-grouping` — it carries none, so the grouping is an inference of the same kind a title match is; do not describe it to the user as barcode-confirmed, and do not let it outrank a cheaper row in `products` on price alone."New value: +"What this block’s identity rests on. `barcode` — the canonical product carries a GTIN and these offers are the same physical item. `curated-grouping` — it carries none, so the grouping is an inference of the same kind a title match is; do not describe it to the user as barcode-confirmed, and do not let it outrank a cheaper row in `products` on price alone. This is how the offers are grouped, not how the query matched the product — see `identity`."
    • Changedsemantic_search3 fields changed
      • changedOutput schema / properties / catalogMatch / description
        Previous value: -"Offers WEM holds under one catalogue product. Check `identityBasis`: on `barcode` these are resolved by GTIN rather than by matching titles, so prefer them and cite their prices over anything in `products`. On `curated-grouping` the product carries no barcode, the grouping is an inference like any title match, and a cheaper row in `products` may well be the same item — see `cheaperElsewhere`."New value: +"Offers WEM holds under one catalogue product. Check `identityBasis`: on `barcode` the product carries a GTIN and every offer here is that same item, so prefer them and cite their prices over anything in `products`. On `curated-grouping` the product carries no barcode, the grouping is an inference like any title match, and a cheaper row in `products` may well be the same item — see `cheaperElsewhere`. Whether the shopper’s words reached this product by barcode or by name is `identity`, a separate question: on `inferred`, say WEM matched it by name."
      • addedOutput schema / properties / catalogMatch / properties / identity
        Added value: +{
        +  "description": "How the shopper’s words reached this product. Decides how you describe the match: on `inferred`, say WEM matched it by name (not by barcode) and do not call the identity confirmed, even when `identityBasis` is `barcode`; on `exact`, the barcode itself resolved it.",
        +  "properties": {
        +    "method": {
        +      "enum": [
        +        "gtin",
        +        "slug",
        +        "listing",
        +        "title"
        +      ],
        +      "type": "string"
        +    },
        +    "strength": {
        +      "description": "exact = barcode; catalogued = a WEM key or listing id; inferred = matched on the product name, MPN or SKU and still a guess.",
        +      "enum": [
        +        "exact",
        +        "catalogued",
        +        "inferred"
        +      ],
        +      "type": "string"
        +    }
        +  },
        +  "type": [
        +    "object",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / catalogMatch / properties / identityBasis / description
        Previous value: -"What this block’s identity rests on. `barcode` — the canonical product carries a GTIN and these offers are the same physical item. `curated-grouping` — it carries none, so the grouping is an inference of the same kind a title match is; do not describe it to the user as barcode-confirmed, and do not let it outrank a cheaper row in `products` on price alone."New value: +"What this block’s identity rests on. `barcode` — the canonical product carries a GTIN and these offers are the same physical item. `curated-grouping` — it carries none, so the grouping is an inference of the same kind a title match is; do not describe it to the user as barcode-confirmed, and do not let it outrank a cheaper row in `products` on price alone. This is how the offers are grouped, not how the query matched the product — see `identity`."
  16. 3 tool updates
    • Changedcompare_offers1 field changed
      • addedOutput schema / properties / degraded
        Added value: +{
        +  "description": "Present when this call hit its time budget and skipped enrichment. The offers returned are COMPLETE — only the extras were dropped. Do not report a missing catalogue block or missing observed retailers as WEM holding nothing, and do not retry automatically.",
        +  "properties": {
        +    "note": {
        +      "type": "string"
        +    },
        +    "skipped": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedfind_lowest_price1 field changed
      • addedOutput schema / properties / degraded
        Added value: +{
        +  "description": "Present when this call hit its time budget and skipped enrichment. The offers returned are COMPLETE — only the extras were dropped. Do not report a missing catalogue block or missing observed retailers as WEM holding nothing, and do not retry automatically.",
        +  "properties": {
        +    "note": {
        +      "type": "string"
        +    },
        +    "skipped": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedsemantic_search2 fields changed
      • changedOutput schema / description
        Previous value: -"Empty when the vector path cannot rank (`semantic: false`), with `reason` naming which of the five causes applies — they have different fixes, so do not read them all as an empty index. `semantic` is true only when pgvector actually ranked products."New value: +"Empty when the vector path cannot rank (`semantic: false`), with `reason` naming which cause applies — they have different fixes, so do not read them all as an empty index. `semantic` is true only when pgvector actually ranked products."
      • changedOutput schema / properties / reason / description
        Previous value: -"Present when semantic is false, and never a judgement on the shopper query. `index_empty` — the vector query ran and matched nothing. `no_catalogue_client` / `no_embedding_key` — WEM is misconfigured, not the catalogue empty. `embedding_failed` / `query_failed` — an upstream call failed; retrying later may succeed."New value: +"Present when semantic is false, and never a judgement on the shopper query. `index_empty` — the vector query ran and matched nothing. `no_catalogue_client` / `no_embedding_key` — WEM is misconfigured, not the catalogue empty. `embedding_failed` / `query_failed` — an upstream call failed; retrying later may succeed. `timed_out` — an upstream call did not answer in time; this says nothing about the catalogue."
  17. 1 tool update
    • Changedfind_lowest_price2 fields changed
      • addedOutput schema / properties / partial
        Added value: +{
        +  "description": "True when the live retailer fan-out hit its 3-second budget and some providers had not answered. The recommendation is the lowest among those that did. Do not call it the market floor, and do not retry automatically.",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / pending_providers
        Added value: +{
        +  "description": "Providers still running when the budget expired. Present only with partial. Their prices are not in this answer.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
  18. 1 tool update
    • Changedverify_offer2 fields changed
      • changedOutput schema / properties / lastConfirmedAt / description
        Previous value: -"When WEM last read these offers — the freshness of this answer."New value: +"When WEM last read a price among the offers compared — the freshness of this answer. Null means none of them carries a dated reading: say the prices are undated."
      • changedOutput schema / properties / receipt / properties / observed_at / description
        Previous value: -"When WEM last read the offers, or \"unobserved\". ACP #197."New value: +"When WEM read the price in amount, or \"unobserved\" when nothing dates it — then do not present amount as current. ACP #197."

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    B
    maintenance
    Sourced product prices, dated price history, specs and independent-test coverage across 4,764 hardware products and 2,064 software vendors — every figure returned with its source URL and the date it was captured. Unknown values come back as null rather than a guess, so an agent can cite what it surfaces.
    -
  • A
    license
    Not graded
    quality
    F
    maintenance
    Enables product search, price comparison, and price history analysis across 6 European marketplaces (DE, AT, GB, FR, IT, ES).
    19
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables searching and comparing product prices across major Indian quick-commerce and e-commerce platforms, ranking results by landed price, returning product links, storing price history, and providing 15–30 day price direction forecasts with best-buy recommendations.
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    DTC competitor intelligence: catalog snapshots, price history, cross-brand product comparison, and drop/restock detection for 84 Shopify-powered brands. Pay-per-call via Apify.
    -
Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources