{"openapi":"3.1.0","info":{"title":"Muwazin Data API","description":"Saudi grocery prices as data: the catalog behind Muwazin, every chain the app compares, matched across retailers and priced per branch, refreshed every night. Authenticate with `Authorization: Bearer mw_live_…`. Every price carries its retailer, collection timestamp and source URL; `/v1/retailers` lists the chains with their price source and branch count.","version":"1.2.9"},"servers":[{"url":"https://api.muwazin.me","description":"Production"}],"paths":{"/v1/health":{"get":{"tags":["meta"],"summary":"Liveness (no key needed)","operationId":"health_v1_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/me":{"get":{"tags":["meta"],"summary":"Your key, plan, usage and terms status","operationId":"me_v1_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"ApiKey":[]}]}},"/v1/terms":{"post":{"tags":["meta"],"summary":"Accept the terms of use with your key","description":"Every data endpoint answers `403 terms_required` until the account behind the key has accepted the current terms, either here or in the console. Read them at https://muwazin.me/developers/terms/, then send the version you read with `accept: true`. Costs no units. Accepting once covers every key on the account; a revised version has to be accepted again.","operationId":"accept_terms_v1_terms_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TermsAccept"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvalidRequest"}}}}},"security":[{"ApiKey":[]}]}},"/v1/retailers":{"get":{"tags":["catalog"],"summary":"Retailers and their last scrape","operationId":"retailers_v1_retailers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"ApiKey":[]}]}},"/v1/categories":{"get":{"tags":["catalog"],"summary":"Category tree with product counts","operationId":"categories_v1_categories_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"ApiKey":[]}]}},"/v1/products/{product_id}":{"get":{"tags":["products"],"summary":"One product with every retailer's price","operationId":"product_v1_products__product_id__get","security":[{"ApiKey":[]}],"parameters":[{"name":"product_id","in":"path","required":true,"schema":{"type":"string","maxLength":64,"title":"Product Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Product"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvalidRequest"}}}}}}},"/v1/barcodes/{gtin}":{"get":{"tags":["products"],"summary":"Look a product up by barcode (GTIN)","operationId":"barcode_v1_barcodes__gtin__get","security":[{"ApiKey":[]}],"parameters":[{"name":"gtin","in":"path","required":true,"schema":{"type":"string","maxLength":20,"title":"Gtin"}}],"responses":{"200":{"description":"The product, or `matches` when several products carry the barcode.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/Product"},{"$ref":"#/components/schemas/BarcodeMatches"}],"title":"Response 200 Barcode V1 Barcodes  Gtin  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvalidRequest"}}}}}}},"/v1/products":{"get":{"tags":["products"],"summary":"Search (q=) or browse the catalog","operationId":"products_v1_products_get","security":[{"ApiKey":[]}],"parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"Search text (Arabic or English). Omit to browse.","title":"Q"},"description":"Search text (Arabic or English). Omit to browse."},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Category"}},{"name":"retailer","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Retailer"}},{"name":"brand","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Brand"}},{"name":"inStock","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Instock"}},{"name":"sort","in":"query","required":false,"schema":{"enum":["relevance","price_asc","price_desc","newest"],"type":"string","default":"relevance","title":"Sort"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductList"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvalidRequest"}}}}}}},"/v1/products/{product_id}/history":{"get":{"tags":["products"],"summary":"Daily price history per retailer","operationId":"history_v1_products__product_id__history_get","security":[{"ApiKey":[]}],"parameters":[{"name":"product_id","in":"path","required":true,"schema":{"type":"string","maxLength":64,"title":"Product Id"}},{"name":"retailer","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Retailer"}},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"From"}},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"To"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvalidRequest"}}}}}}},"/v1/products/{product_id}/branches":{"get":{"tags":["products"],"summary":"The product's price at every branch","description":"One row per branch the per-store collection covers, collected nightly from each\nretailer's own storefront (a branch swept weekly answers `stale`). `store.kind`:\n`store` (a shop with a location), `centre` (a Lulu store whose location we do not\nhold: no distance), `area` (a Carrefour catalogue area on a city probe point: no\ndistance, and left out of `near`). `originalPrice` is the branch's \"was\" price when it is on sale\nthere; `promo`, `limits` and `flags` are the retailer's own, shapes differ by retailer.\nEach row's `priceBasis` says what its `price` and `originalPrice` buy: one kilogram (`kg`,\nan item sold by weight) or one item; the response's own `priceBasis` is the product's.\nKeyset paged by (price, retailer, store) or, with `near`, by (distance, retailer, store).","operationId":"product_branches_v1_products__product_id__branches_get","security":[{"ApiKey":[]}],"parameters":[{"name":"product_id","in":"path","required":true,"schema":{"type":"string","maxLength":64,"title":"Product Id"}},{"name":"city","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}],"description":"a KSA city in any common spelling","title":"City"},"description":"a KSA city in any common spelling"},{"name":"retailer","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Retailer"}},{"name":"near","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"description":"lat,lng — nearest first, real stores only","title":"Near"},"description":"lat,lng — nearest first, real stores only"},{"name":"radiusKm","in":"query","required":false,"schema":{"type":"number","maximum":200,"exclusiveMinimum":0,"default":10,"title":"Radiuskm"}},{"name":"inStock","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Instock"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":100,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchList"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvalidRequest"}}}}}}},"/v1/price-changes":{"get":{"tags":["prices"],"summary":"What moved last night (drops and rises)","operationId":"price_changes_v1_price_changes_get","security":[{"ApiKey":[]}],"parameters":[{"name":"direction","in":"query","required":false,"schema":{"enum":["drop","rise","all"],"type":"string","default":"drop","title":"Direction"}},{"name":"retailer","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Retailer"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Category"}},{"name":"minPct","in":"query","required":false,"schema":{"type":"number","maximum":70,"minimum":0,"description":"Minimum absolute change in percent","default":1.0,"title":"Minpct"},"description":"Minimum absolute change in percent"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvalidRequest"}}}}}}},"/v1/weekly-changes":{"get":{"tags":["prices"],"summary":"What moved week-over-week (drops and rises)","description":"Current in-stock price vs the latest snapshot 7–14 days old, per product×retailer.\nRefreshed nightly into weekly_price_changes_mv; same sanity bounds as /v1/price-changes.","operationId":"weekly_changes_v1_weekly_changes_get","security":[{"ApiKey":[]}],"parameters":[{"name":"direction","in":"query","required":false,"schema":{"enum":["drop","rise","all"],"type":"string","default":"drop","title":"Direction"}},{"name":"retailer","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Retailer"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Category"}},{"name":"minPct","in":"query","required":false,"schema":{"type":"number","maximum":70,"minimum":0,"description":"Minimum absolute change in percent","default":1.0,"title":"Minpct"},"description":"Minimum absolute change in percent"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvalidRequest"}}}}}}},"/v1/stores":{"get":{"tags":["stores"],"summary":"Store locations","description":"Keyset paged like the catalog: one retailer has more branches than the\npage limit, so without a cursor its tail was simply unreachable.","operationId":"stores_v1_stores_get","security":[{"ApiKey":[]}],"parameters":[{"name":"city","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}],"title":"City"}},{"name":"retailer","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Retailer"}},{"name":"near","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"description":"lat,lng","title":"Near"},"description":"lat,lng"},{"name":"radiusKm","in":"query","required":false,"schema":{"type":"number","maximum":200,"exclusiveMinimum":0,"default":10,"title":"Radiuskm"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":100,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvalidRequest"}}}}}}},"/v1/intel/benchmark":{"get":{"tags":["intel"],"summary":"Retailer competitiveness on products 2+ retailers stock","operationId":"intel_benchmark_v1_intel_benchmark_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"ApiKey":[]}]}},"/v1/intel/volatility":{"get":{"tags":["intel"],"summary":"Most volatile prices of the last 30 days","operationId":"intel_volatility_v1_intel_volatility_get","security":[{"ApiKey":[]}],"parameters":[{"name":"retailer","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Retailer"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Category"}},{"name":"minScore","in":"query","required":false,"schema":{"type":"number","minimum":0,"default":0,"title":"Minscore"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvalidRequest"}}}}}}}},"components":{"schemas":{"BarcodeMatches":{"properties":{"matches":{"items":{"$ref":"#/components/schemas/Product"},"type":"array","title":"Matches"}},"type":"object","required":["matches"],"title":"BarcodeMatches"},"BranchCoverage":{"properties":{"total":{"type":"integer","title":"Total"},"inStock":{"type":"integer","title":"Instock"},"url":{"type":"string","title":"Url"}},"type":"object","required":["total","inStock","url"],"title":"BranchCoverage"},"BranchList":{"properties":{"productId":{"type":"string","title":"Productid"},"mergedFrom":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mergedfrom","description":"Only on `/products/{id}` and its `/history` and `/branches`, and only when the id you asked for was merged into another product (two records turned out to be one item): the id you asked for. The response is the product it went into, under that product's id; store that id from now on."},"priceBasis":{"type":"string","enum":["item","kg"],"title":"Pricebasis","description":"`kg`: the product is sold by weight (loose produce, meat and fish, deli counters) and has no pack size. `item`: an item or pack. What one PRICE buys is said by the price itself (`prices[].priceBasis`, a branch row's `priceBasis`): on a product sold by weight most prices are per kilogram, and a retailer that sells it as a pack keeps its pack price, per item."},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"items":{"items":{"$ref":"#/components/schemas/BranchPrice"},"type":"array","title":"Items"},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nextcursor"},"dataAsOf":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dataasof"}},"type":"object","required":["productId","priceBasis","items"],"title":"BranchList"},"BranchPrice":{"properties":{"retailer":{"type":"string","title":"Retailer"},"retailerName":{"$ref":"#/components/schemas/Name"},"store":{"$ref":"#/components/schemas/BranchStore"},"price":{"type":"number","title":"Price","description":"In SAR. The price of one kilogram when this row's `priceBasis` is `kg`."},"priceBasis":{"type":"string","enum":["item","kg"],"title":"Pricebasis","description":"What this price buys. `kg`: one kilogram (a weighed item's price, or a listing of exactly 1 kg of a product sold by weight). `item`: one item or pack, as the retailer lists it. A retailer's history is in the basis of its current price."},"originalPrice":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Originalprice","description":"The branch's \"was\" price when the product is on sale there; the same basis as `price`."},"currency":{"type":"string","const":"SAR","title":"Currency"},"inStock":{"type":"boolean","title":"Instock"},"stockState":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stockstate"},"stockQty":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Stockqty"},"promo":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Promo"},"limits":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Limits"},"flags":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Flags"},"updatedAt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updatedat"},"branchLastSeen":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Branchlastseen"},"stale":{"type":"boolean","title":"Stale"}},"type":"object","required":["retailer","retailerName","store","price","priceBasis","currency","inStock","stale"],"title":"BranchPrice"},"BranchStore":{"properties":{"code":{"type":"string","title":"Code"},"name":{"$ref":"#/components/schemas/Name"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"lat":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lat"},"lng":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lng"},"distanceKm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distancekm"},"kind":{"type":"string","enum":["store","centre","area"],"title":"Kind"}},"type":"object","required":["code","name","kind"],"title":"BranchStore"},"CheapestPrice":{"properties":{"retailer":{"type":"string","title":"Retailer"},"price":{"type":"number","title":"Price"},"priceBasis":{"type":"string","enum":["item","kg"],"title":"Pricebasis","description":"The basis of this price, as in `prices`."}},"type":"object","required":["retailer","price","priceBasis"],"title":"CheapestPrice"},"Name":{"properties":{"ar":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ar"},"en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"En"}},"type":"object","title":"Name"},"Product":{"properties":{"id":{"type":"string","title":"Id"},"barcode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Barcode"},"name":{"$ref":"#/components/schemas/Name"},"brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand"},"size":{"$ref":"#/components/schemas/ProductSize"},"priceBasis":{"type":"string","enum":["item","kg"],"title":"Pricebasis","description":"`kg`: the product is sold by weight (loose produce, meat and fish, deli counters) and has no pack size. `item`: an item or pack. What one PRICE buys is said by the price itself (`prices[].priceBasis`, a branch row's `priceBasis`): on a product sold by weight most prices are per kilogram, and a retailer that sells it as a pack keeps its pack price, per item."},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"subcategory":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subcategory"},"image":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image"},"matchConfidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Matchconfidence"},"cheapest":{"anyOf":[{"$ref":"#/components/schemas/CheapestPrice"},{"type":"null"}],"description":"The lowest price that is in stock and not stale, or null."},"prices":{"items":{"$ref":"#/components/schemas/ProductPrice"},"type":"array","title":"Prices"},"branches":{"$ref":"#/components/schemas/BranchCoverage"},"updatedAt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updatedat"},"mergedFrom":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mergedfrom","description":"Only on `/products/{id}` and its `/history` and `/branches`, and only when the id you asked for was merged into another product (two records turned out to be one item): the id you asked for. The response is the product it went into, under that product's id; store that id from now on."}},"type":"object","required":["id","name","size","priceBasis","prices","branches"],"title":"Product"},"ProductList":{"properties":{"items":{"items":{"$ref":"#/components/schemas/Product"},"type":"array","title":"Items"},"found":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Found","description":"Search only: how many products match."},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nextcursor"},"search":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Search","description":"Search only: `mode` is `keyword` or `hybrid`."},"capped":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Capped","description":"Browse only: the plan's browse allowance ran out on this page."},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","required":["items"],"title":"ProductList"},"ProductPrice":{"properties":{"retailer":{"type":"string","title":"Retailer"},"retailerName":{"$ref":"#/components/schemas/Name"},"price":{"type":"number","title":"Price","description":"In SAR. The price of one kilogram when this price's `priceBasis` is `kg`."},"priceBasis":{"type":"string","enum":["item","kg"],"title":"Pricebasis","description":"What this price buys. `kg`: one kilogram (a weighed item's price, or a listing of exactly 1 kg of a product sold by weight). `item`: one item or pack, as the retailer lists it. A retailer's history is in the basis of its current price."},"currency":{"type":"string","const":"SAR","title":"Currency"},"inStock":{"type":"boolean","title":"Instock"},"stale":{"type":"boolean","title":"Stale","description":"The retailer has not been collected successfully for two nights."},"scrapedAt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scrapedat","description":"When the retailer's collection last listed this price."},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url","description":"The item's page at the retailer, or the narrowest listing that shows it."}},"type":"object","required":["retailer","retailerName","price","priceBasis","currency","inStock","stale"],"title":"ProductPrice"},"ProductSize":{"properties":{"weight":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Weight","description":"The pack size as text, e.g. `2L`. Null when unknown, and for a product with `priceBasis` `kg`: it has no pack size."},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit"}},"type":"object","title":"ProductSize"},"TermsAccept":{"properties":{"version":{"type":"string","maxLength":32,"title":"Version","description":"The terms version you read, as shown in the 403, /v1/me and on the terms page"},"accept":{"type":"boolean","const":true,"title":"Accept","description":"true = I have read and accept the terms of use"}},"type":"object","required":["version","accept"],"title":"TermsAccept"},"InvalidRequest":{"title":"InvalidRequest","type":"object","required":["error"],"description":"A parameter of the wrong type or out of range.","properties":{"error":{"type":"object","required":["code","message","fields"],"properties":{"code":{"type":"string","enum":["invalid_request"]},"message":{"type":"string","description":"Names each parameter that is wrong, and what is wrong with it."},"fields":{"type":"array","description":"The same, one entry per parameter.","items":{"type":"object","required":["in","name","message"],"properties":{"in":{"type":"string","description":"`path`, `query` or `body`."},"name":{"type":"string"},"message":{"type":"string"}}}}}}}}},"securitySchemes":{"ApiKey":{"type":"http","description":"Your API key, e.g. `mw_live_…` (the `X-API-Key` header is accepted too).","scheme":"bearer"}}},"tags":[{"name":"meta","description":"Health and your own key/usage."},{"name":"catalog","description":"Retailers and the category tree."},{"name":"products","description":"Product lookups, search/browse, price history. Every price carries `retailer`, `scrapedAt`, `stale` and the retailer's `url`. Each price's `priceBasis` says what it buys: one `item`, or one `kg` of a product sold by weight."},{"name":"prices","description":"What moved last night."},{"name":"stores","description":"Store locations with coordinates, by city or by distance from a point."}]}