{"openapi":"3.1.0","info":{"title":"Suplementoscanner Catalog API","version":"1.0.0","description":"Read-only access to supplement prices, normalized to price-per-unit (per kg \/ serving \/ capsule) across 25 stores. Money is integer cents plus a string preformatted in the market's locale; every response states the market it is scoped to. Every product carries a buy_url, a link to the shop through our redirect that may be an affiliate link (see affiliate_disclosure).\n\n## Identifying your integration (required)\n\nEvery integration must identify its operator in a request header, on the JSON API and the\nMCP endpoint alike:\n\n- `Client-Name` (required): the company, organisation or individual operating the integration,\n  e.g. `Client-Name: Acme Labs`. Name the operator, not each of its end users; for a personal\n  project a project name or handle is enough.\n- `Client-Domain` (recommended): the bare domain of the operator's website, e.g.\n  `Client-Domain: example.com`. A hostname only: no scheme, path or port, and an\n  internationalised domain in its ASCII (punycode) form.\n\nUse plain ASCII and keep each value under 100 characters. Both are self-declared and are\nnot credentials: they grant no access and do not raise rate limits. Keep them truthful, and\nnever put keys, tokens, passwords, email addresses or details about your end users in them.\n\nWe may throttle or block, without notice, requests that do not send `Client-Name`, that\nidentify their operator falsely, or that exceed the rate limits. A client that cannot set\ncustom headers, such as a chat assistant's connector a person adds for their own use, is\nexempt; there is no query-parameter equivalent. MCP clients that accept extra HTTP headers\nmust send them, and so must browser callers (the CORS preflight they trigger is answered).","termsOfService":"https:\/\/suplementoscanner.pt\/agentes-ia#api-terms"},"servers":[{"url":"https:\/\/api.suplementoscanner.pt\/v1"}],"paths":{"\/search":{"get":{"operationId":"searchProducts","summary":"Search as the website does: by name or brand, or by a need with its qualities, answered as a category with filters (see interpreted_as).","parameters":[{"name":"q","in":"query","required":true,"description":"What the user is looking for: a name or brand (\"whey isolaat\" or \"magnesium bisglycinaat\"), or a need with its qualities (\"vegan eiwitrepen zonder toegevoegde suiker\" or \"lab-tested creatine powder\").","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Max results (1-50, default 20).","schema":{"type":"integer"}},{"name":"in_stock","in":"query","required":false,"description":"Only in-stock products.","schema":{"type":"boolean"}},{"name":"category_slug","in":"query","required":false,"description":"Restrict to this category and all of its subcategories, so a parent slug works too. Must be a slug from \/categories; an unknown slug is rejected with a 422.","schema":{"type":"string"}},{"name":"max_unit_price_cents","in":"query","required":false,"description":"Cap on normalized unit price, in whole cents (a product whose unit price rounds to at most this many cents).","schema":{"type":"integer"}},{"name":"market","in":"query","required":false,"description":"Country market to query (nl, be, fr, gb, pl, es, dk, at, de, cz, pt). Defaults to the requested domain's market.","schema":{"type":"string","enum":["nl","be","fr","gb","pl","es","dk","at","de","cz","pt"]}}],"responses":{"200":{"description":"Success. A JSON object carrying the results plus last_scraped_at and affiliate_disclosure.","content":{"application\/json":{"schema":{"type":"object"}}}}}}},"\/categories":{"get":{"operationId":"listCategories","summary":"Browsable categories with live counts and lowest unit price.","parameters":[{"name":"market","in":"query","required":false,"description":"Country market to query (nl, be, fr, gb, pl, es, dk, at, de, cz, pt). Defaults to the requested domain's market.","schema":{"type":"string","enum":["nl","be","fr","gb","pl","es","dk","at","de","cz","pt"]}}],"responses":{"200":{"description":"Success. A JSON object carrying the results plus last_scraped_at and affiliate_disclosure.","content":{"application\/json":{"schema":{"type":"object"}}}}}}},"\/categories\/{category}\/cheapest":{"get":{"operationId":"cheapestInCategory","summary":"Cheapest products by normalized unit price across a category subtree.","parameters":[{"name":"category","in":"path","required":true,"description":"Category slug (see \/categories).","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Max results (1-50, default 10).","schema":{"type":"integer"}},{"name":"in_stock","in":"query","required":false,"description":"Only in-stock products.","schema":{"type":"boolean"}},{"name":"filters","in":"query","required":false,"description":"Comma-separated attribute filters, as on the category page, e.g. is_vegan,is_lab_tested,form:powder. Every response lists the ids this category offers in available_filters; an id it does not offer is rejected with a 422.","schema":{"type":"string"}},{"name":"brand","in":"query","required":false,"description":"Only this brand, by name or slug as it appears in the results.","schema":{"type":"string"}},{"name":"market","in":"query","required":false,"description":"Country market to query (nl, be, fr, gb, pl, es, dk, at, de, cz, pt). Defaults to the requested domain's market.","schema":{"type":"string","enum":["nl","be","fr","gb","pl","es","dk","at","de","cz","pt"]}}],"responses":{"200":{"description":"Success. A JSON object carrying the results plus last_scraped_at and affiliate_disclosure.","content":{"application\/json":{"schema":{"type":"object"}}}}}}},"\/products\/{product}":{"get":{"operationId":"getProduct","summary":"One product with detail and recent price history.","parameters":[{"name":"product","in":"path","required":true,"description":"Numeric product id.","schema":{"type":"integer"}},{"name":"market","in":"query","required":false,"description":"Country market to query (nl, be, fr, gb, pl, es, dk, at, de, cz, pt). Defaults to the requested domain's market.","schema":{"type":"string","enum":["nl","be","fr","gb","pl","es","dk","at","de","cz","pt"]}}],"responses":{"200":{"description":"Success. A JSON object carrying the results plus last_scraped_at and affiliate_disclosure.","content":{"application\/json":{"schema":{"type":"object"}}}},"404":{"description":"Product not found or not currently listable."}}}}}}