AI assistants are starting to answer “what should I buy?” — and to state prices as fact while doing it. Existing standards describe how an offer is expressed and how an agentic transaction is executed; what they do not define is the evidence an independent checker should hold before presenting a retail price as verified. These are the criteria WEM requires of itself, published so that someone who does not trust us can test them.
1. Resolved product identity
The offer is tied to a specific product identity: a global identifier (GTIN/EAN/UPC) where one exists, otherwise brand plus manufacturer model and the variant attributes that distinguish it, otherwise a retailer's own listing id already linked to a catalogue product. Where identity rests on a name match instead, the answer says so and is never presented as exact.
Normative requirement
A resolution made by title similarity alone MUST NOT be reported as an exact identity, and an offer MUST carry the method by which it was identified.
Most wrong price comparisons are not wrong prices; they are the wrong product. A 100ml bottle compared against a 50ml one produces a real number about the wrong thing, and no amount of price accuracy repairs it. Not every product carries a barcode, so the rule is a ladder rather than a gate — what it forbids is presenting the bottom rung as the top one.
WEM implementation: gtin.ts (check-digit validated), canonical-lookup.ts; verify_offer returns identity.method and identity.strength
2. Observed at the retailer's own surface, not submitted through a feed
The price was read by WEM from a surface the retailer serves to shoppers — their product page, or a first-party API that returns the customer-facing transactional offer. A price taken from an affiliate, comparison or promotional feed does not qualify as an observation, whichever transport delivers it.
Normative requirement
A verified price MUST come from an observation of the retailer's customer-facing or transactional surface. A feed MAY identify candidate products and offers, but MUST NOT be the sole evidence for a verified price — and an endpoint that serves syndicated feed data MUST be treated as a feed regardless of being called an API.
A feed is evidence of what a merchant said. An observation is evidence of what a shopper could actually see. Both surfaces belong to the retailer — the difference is not who controls them but what they bind: the page is the one a customer transacts on, while a feed is a copy prepared for redistribution that can drift from it without consequence. Detecting that drift is the whole job, and it cannot be done from the copy alone.
WEM implementation: price-observation.ts — feed:* is never an observation
3. Timestamped, and the age is disclosed
Every observation carries the moment it was made, and anything published says how old it is rather than implying "now".
Normative requirement
Every observation MUST carry the time it was made, and any published price MUST disclose that time or its age.
A price with no time attached is unfalsifiable — it cannot be shown wrong, so it cannot be shown right either. "Checked 4 hours ago" is a weaker claim than "live" and an honest one.
WEM implementation: price_history.recorded_at; verify_offer returns lastConfirmedAt
4. Labelled provenance, on every single row
Each observation records how it was made, and the label travels with it: retailer API, browser extension reading the page, or a human who opened it.
Normative requirement
Provenance MUST be recorded per observation at the moment of collection, not asserted per dataset.
Provenance is a property of the price, not of the dataset. Once observations of different kinds are pooled without a row-level label, no later filter can reconstruct how each price was obtained — so the label is written when the row is, or the row is not admissible.
WEM implementation: price_history.source — api:, extension, operator
5. Availability stated only where it was checked
Availability has three states, not two: reported available, reported unavailable, and not reported. The third is recorded as unknown and never rendered as "in stock".
Normative requirement
Availability MUST NOT be inferred where the source did not report it. Unknown MUST NOT be rendered, ranked, or published as available.
A price for something nobody can buy is not a cheaper option. Defaulting unknown to available is the single easiest way to make a comparison look better than reality — and it is usually done by a database default rather than a decision, which is why the rule forbids the default rather than trusting the intention.
WEM implementation: observedInStock(); canonical_offers.in_stock is nullable and NULL means not reported
6. Silence when the evidence is missing
Where an offer cannot meet these rules, it is excluded from verified results. Nothing is estimated, inferred, or filled in to complete a comparison.
Normative requirement
A missing value MUST NOT be estimated or substituted to complete a comparison. Where evidence is absent the answer MUST be an explicit no-verification result, not a plausible one.
The pressure in comparison is always to show something. A gap teaches a shopper that the absence means something; a plausible guess teaches them nothing and costs them the ability to trust the rest. An offer WEM cannot verify may still be shown as a discovery result — it is verified status it cannot have, and the two are kept apart.
WEM implementation: isPublishableSource() gates every published aggregate and press RPC
7. The answer does not know what it earns
Ranking, selection and verification are computed without reference to commercial terms. Funding is disclosed; it never reaches the ordering.
Normative requirement
No commission, revenue-share or commercial-priority value MUST be available to the code path that verifies an offer or orders results.
Verification is only worth something if the verifier is not paid for the verdict. WEM is funded by affiliate commission and does not pretend that conflict is absent; it is a data-isolation property instead of a promise — the commercial value exists, and the ranking path cannot read it.
WEM implementation: find_lowest_price sorts on price; no commission field reaches ranking
8. Lawful to retain and to republish
An observation is only published where the source's terms permit retention and republication. Where they do not, the data is refused at the writer, not filtered at the reader.
Normative requirement
Data whose terms restrict the retention, comparison or republication a verified result depends on MUST NOT enter the verification corpus, and MUST be refused at collection rather than filtered at publication.
A verification corpus that cannot be shown is not evidence. Sources whose licences cap retention or bar comparison use are excluded before collection, because a clean provenance story does not create a retention right. Which sources those are is an implementation matter and changes as terms do.
WEM implementation: named source exclusions applied in the publishing predicate and both press RPCs
The distinction that does most of the work
Criterion 2 separates two things the word “price” hides. An advertised price is supplied for distribution — through an affiliate, comparison or promotional feed. An observed price is captured by the verifier from the surface the retailer serves to shoppers, whether or not any commercial relationship exists.
A feed is evidence of what a merchant said. An observation is evidence of what a shopper could actually see.
Both surfaces belong to the retailer, so the distinction is not who controls them. It is what they bind: the page is the one a customer transacts on, while a feed is a copy prepared for redistribution that can drift from it without consequence. A feed cannot verify its own price — detecting that drift needs a separate observation path, and that remains true no matter how large the feed is.
Using it
The standard is free to read, cite and apply. If you build commerce data and want to state that you meet it, do — and say which criteria you meet, because the ones a dataset fails are usually the informative ones.
Conformance. An implementation conforms to version 1.2 only if all eight normative requirements are satisfied for every offer it describes as verified. Partial adoption is welcome and useful, but it is not conformance, and should be stated as the specific criteria met rather than as compliance with the standard.
Machine-readable: schema.json defines the verified-offer object, and examples.json carries a worked case for every verdict, including the two that refuse to confirm. The examples are generated from the same function that answers verify_offer in production, so they cannot drift from what the API actually returns.
Agents can call the criteria rather than read them: WEM’s MCP server exposes verify_offer, which answers whether a specific price is supported by observation. It never invents or infers a price; it returns an explicit non-confirming verdict instead, and the three are not the same claim. unknown_product and not_at_retailer mean the claim could not be checked — unchecked, never false. price_moved is stronger: the product and retailer resolved, and WEM’s own reading differs from the claim.
Cite it as: The WEM Verified Offer Standard, version 1.2, wem3.ai/standard/verified-offer.