{"openapi":"3.1.0","info":{"title":"Deal Verdict API","description":"Answers one question for any product: is it meaningfully discounted right now at any retailer we can reach? Returns a resolved verdict - deal / no deal / insufficient data - never a data feed.","version":"2.0.0","x-guidance":"Ask whether a specific product is meaningfully discounted right now. Describe the product in plain language; the service resolves it to canonical models, checks every retailer it can reach, and returns ONE resolved verdict - deal_found / no_deal / insufficient_data - with the discount, a confidence level, and a coverage report naming which retailers were reachable. It sells the answer, not the underlying listings: individual listing URLs and seller details are never returned. POST /verdict covers new goods. POST /verdict/used is a SEPARATE, independently priced resource for the used / refurbished / open-box market, judged against a condition-adjusted used-market basis rather than new retail; it is standalone, so call it directly without calling /verdict first. POST /verdict/quote is FREE and returns the price tier a given request would cost before you commit to paying. Payment: /verdict and /verdict/used take x402 on Base mainnet; /verdict/mpp serves the same new-goods verdict over MPP on Tempo mainnet.","contact":{"email":"bestbuy@megachat.xyz","url":"https://deal-verdict-frontend-production.up.railway.app"}},"paths":{"/health":{"get":{"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Health Health Get"}}}}},"security":[]}},"/verdict/mpp":{"post":{"summary":"Verdict Mpp","description":"The same new-goods verdict, paid over MPP (Stripe/Tempo) instead of x402.\n\nDeliberately a separate route from /verdict: the x402 middleware gates that\none, and running two payment protocols over a single path would mean two\ncompeting 402 challenges. This route is NOT in the x402 `routes` map, so the\nmiddleware ignores it and MPP is the sole gate here.","operationId":"verdict_mpp_verdict_mpp_post","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/VerdictRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"title":"Response Verdict Mpp Verdict Mpp Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"402":{"description":"Payment Required"}},"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.05"},"protocols":[{"mpp":{"method":"tempo","intent":"charge","currency":"0x20C000000000000000000000b9537d11c60E8b50"}}]}}},"/verdict/quote":{"post":{"summary":"Verdict Quote","description":"Free pre-flight: the tiered price this exact request would be quoted.\n\nLets an agent see the price (cache-hit vs fresh, ready-reference vs computed)\nbefore committing to pay - a single indexed cache lookup, no model calls.","operationId":"verdict_quote_verdict_quote_post","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/VerdictRequest"},{"type":"null"}],"title":"Request"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Verdict Quote Verdict Quote Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[]}},"/":{"get":{"summary":"Discover","description":"Free service manifest, so a buyer agent can decide before paying.\n\nContent-negotiated: a browser (``Accept: text/html``) gets a human landing\npage, everything else gets the JSON manifest byte-for-byte as before. Every\ndirectory links to this origin, so a person following one of those links must\nnot land on raw JSON - but no agent's Accept header flips this (see\n``landing.wants_html``), so the machine contract is untouched.","operationId":"discover__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[]}},"/verdict":{"post":{"summary":"Verdict","description":"Paid. Runs the engine and returns the resolved verdict.\n\nReached only after the middleware has verified payment.","operationId":"verdict_verdict_post","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/VerdictRequest"},{"type":"null"}],"title":"Request"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"title":"Response Verdict Verdict Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"402":{"description":"Payment Required"}},"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.05"},"protocols":[{"x402":{}}]}}},"/verdict/used":{"post":{"summary":"Verdict Used","description":"Paid, standalone. Used/refurb/open-box verdict judged on a used-market basis.\n\nFully self-contained: no prior /verdict call is assumed. Reached only after\nthe middleware has verified payment for the used-lane price.","operationId":"verdict_used_verdict_used_post","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/UsedVerdictRequest"},{"type":"null"}],"title":"Request"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"title":"Response Verdict Used Verdict Used Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"402":{"description":"Payment Required"}},"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.08"},"protocols":[{"x402":{}}]}}}},"components":{"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"UsedVerdictRequest":{"properties":{"product":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Product","description":"Free-text product to shop for, used/refurb/open-box."},"variants":{"items":{"type":"string"},"type":"array","title":"Variants","description":"Optional size/variant hints."},"attribute":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Attribute","description":"A required attribute."},"category":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Category","description":"Optional coarse category hint."},"discount_threshold":{"anyOf":[{"type":"number","exclusiveMaximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Discount Threshold","description":"Fraction under the used-market basis required to count as a used deal."},"product_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Product Url","description":"Optional product page; its title/model/SKU sharpen the used match. Never echoed."},"location":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Location","description":"City or ZIP. Required to include Facebook Marketplace; also localizes results."},"include_marketplace":{"type":"boolean","title":"Include Marketplace","description":"Opt in to Facebook Marketplace (slow, unreliable, its own city/radius). Off by default; eBay is always used. Requires `location` and a configured dataset.","default":false},"radius_miles":{"type":"integer","maximum":500.0,"minimum":1.0,"title":"Radius Miles","description":"Search radius for Facebook Marketplace, in miles.","default":25}},"type":"object","title":"UsedVerdictRequest","description":"A used-goods question for the standalone /verdict/used resource.\n\nFully self-contained: a caller hits this directly with just a `product`, no\nprior /verdict call required. There is no `reference_price` - used goods are\njudged against a used-market basis, never a caller/new-goods reference."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VerdictRequest":{"properties":{"product":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Product","description":"Free-text product to shop for, e.g. 'Bosch 800 series dishwasher'."},"variants":{"items":{"type":"string"},"type":"array","title":"Variants","description":"Optional size/variant hints to constrain matching, e.g. ['50 gallon']."},"attribute":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Attribute","description":"A required attribute the product must have, e.g. 'gas', 'stainless'."},"category":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Category","description":"Optional coarse category hint."},"discount_threshold":{"anyOf":[{"type":"number","exclusiveMaximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Discount Threshold","description":"Fraction under reference required to count as a deal (e.g. 0.30 = 30% off)."},"reference_price":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"null"}],"title":"Reference Price","description":"Your own reference price. If given, it is used instead of the computed baseline."},"product_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Product Url","description":"Optional link to a specific product page. If given, the page's title, model/SKU, and price are used to sharpen the match and default the reference price (a reference_price you pass still wins). The page content, URL, and text never appear in the result."},"location":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Location","description":"Optional city or ZIP. Passed as location context to the price searches so results reflect that area. A city name suits the aggregated feed; a ZIP localizes store-delivery pricing."}},"type":"object","title":"VerdictRequest","description":"A shopping question. Every field is optional; `{}` uses the service default."}}},"externalDocs":{"description":"Human UI - connect a wallet and ask in your browser","url":"https://deal-verdict-frontend-production.up.railway.app"}}