{"openapi":"3.1.0","info":{"title":"Vitalityfit Price API","version":"1.0.0","description":"Prices and offers for health products from German online shops and pharmacies, by name, PZN or EAN. Read-only, no authentication, free for non-commercial use (commercial use only by prior agreement, see the terms); the same data as the MCP server at https://vitality-fit.de/mcp. Offer lists carry a disclosure (affiliate links, price source) and, for medicines, a compliance_notice with the statutory German notice. Prices may have changed since; the price in the shop applies. No medical advice. Limit: 12 requests per 2 minutes per IP (one per 10 seconds on average); above it the answer is 429 with Retry-After (a 429 without it means the service is busy; retry after a few seconds). Responses are cached for up to 1 hour. Product keys can change when products are merged; a 410 means the key is gone and a search by name, PZN or EAN returns the product's current key if it is still listed. Terms: https://vitality-fit.de/api/#bedingungen","termsOfService":"https://vitality-fit.de/api/#bedingungen","contact":{"name":"Vitalityfit","url":"https://vitality-fit.de/api/","email":"service@vitality-fit.de"}},"servers":[{"url":"https://vitality-fit.de/api/v1"}],"paths":{"/products":{"get":{"operationId":"searchProducts","summary":"Search products","description":"Finds up to 10 health products (default 5) by name, PZN or EAN; barcode-style input is normalized. Per product: title, brand, pack sizes, cheapest price, number of shops and the product page URL.","parameters":[{"name":"q","in":"query","required":true,"description":"Product name, PZN or EAN.","schema":{"type":"string","minLength":1,"maxLength":200}},{"name":"limit","in":"query","required":false,"description":"Number of products; values outside 1-10 are clamped.","schema":{"type":"integer","minimum":1,"maximum":10,"default":5}}],"responses":{"200":{"description":"Matching products.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductList"}}}},"400":{"description":"invalid_argument: q missing, empty or too long; limit that is not an integer; or q that looks like a PZN/EAN but is not a valid one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: more than 12 requests in 120 seconds from one IP.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}}}},"500":{"description":"internal: unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"unavailable: price data temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/products/{product_key}/offers":{"get":{"operationId":"listProductOffers","summary":"List offers for a product","description":"The cheapest offers (up to 10, cheapest first) for one product and pack size: shop, price, shipping, delivery time, stock, unit price, shop link, 90-day low, data date.","parameters":[{"name":"product_key","in":"path","required":true,"description":"product_key from searchProducts.","schema":{"type":"string","minLength":1,"maxLength":160}},{"name":"pack_size","in":"query","required":false,"description":"A pack_sizes label (e.g. \"20 st\") or identity_key. Without pack_size: the pack size with the most offers. An unknown pack_size returns the message \"pack size not found\" with available_packs.","schema":{"type":"string","maxLength":100}}],"responses":{"200":{"description":"Offers for the pack.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferList"}}}},"410":{"description":"not_found: the product is not available (unknown key, or merged into another product; a search by name, PZN or EAN returns the product's current key if it is still listed).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"400":{"description":"invalid_argument: product_key or pack_size too long.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited: more than 12 requests in 120 seconds from one IP.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}}}},"500":{"description":"internal: unexpected error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"unavailable: price data temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"PackSize":{"type":"object","required":["label","identity_key"],"properties":{"label":{"type":"string","description":"Pack size as listed, e.g. \"20 st\" or \"100 ml\"."},"identity_key":{"type":["string","null"],"description":"Physical identity of the pack (pzn_<n> or ean_<n>); null when unknown. Accepted as pack_size."}}},"Product":{"type":"object","required":["product_key","title","brand","pack_sizes","cheapest_price","shop_count","url"],"properties":{"product_key":{"type":"string","description":"Key for listProductOffers. Keys can change when products are merged (then 410)."},"title":{"type":["string","null"]},"brand":{"type":["string","null"]},"pack_sizes":{"type":"array","items":{"$ref":"#/components/schemas/PackSize"}},"cheapest_price":{"type":["number","null"],"description":"Lowest current price in EUR."},"shop_count":{"type":["integer","null"],"description":"Number of shops with an offer."},"url":{"type":"string","format":"uri","description":"Product page on vitality-fit.de."},"compliance_notice":{"type":"string","description":"Statutory German notice for medicines; present only for medicines."}}},"ProductList":{"type":"object","required":["products"],"properties":{"products":{"type":"array","maxItems":10,"items":{"$ref":"#/components/schemas/Product"},"description":"Best match first."}}},"UnitPrice":{"type":"object","required":["value","per"],"properties":{"value":{"type":"number","description":"EUR per 1 l, 1 kg or 1 piece."},"per":{"type":"string","enum":["l","kg","pcs"]}}},"Offer":{"type":"object","required":["shop","price","currency","shipping_cost","delivery_time","in_stock","link","affiliate"],"properties":{"shop":{"type":["string","null"]},"price":{"type":"number"},"currency":{"type":["string","null"]},"shipping_cost":{"type":["number","null"],"description":"Shipping cost in EUR; null when the shop states none."},"delivery_time":{"type":["string","null"]},"in_stock":{"type":["boolean","null"]},"link":{"type":["string","null"],"description":"Link to the shop; affiliate links carry the channel marker api."},"affiliate":{"type":"boolean","description":"true for affiliate links (vitality-fit.de may earn a commission)."},"unit_price":{"$ref":"#/components/schemas/UnitPrice"}}},"OfferList":{"type":"object","required":["product_key","title","url","disclosure","shop_count","offers","low_90d","data_date"],"properties":{"product_key":{"type":"string"},"title":{"type":["string","null"]},"url":{"type":"string","format":"uri"},"disclosure":{"type":"string","description":"Affiliate and price-source disclosure for these results."},"compliance_notice":{"type":"string","description":"Statutory German notice for medicines; present only for medicines."},"pack":{"type":"string","description":"The pack size the offers are for; absent without offers."},"shop_count":{"type":"integer"},"offers":{"type":"array","maxItems":10,"items":{"$ref":"#/components/schemas/Offer"},"description":"Cheapest first."},"low_90d":{"type":["number","null"],"description":"Lowest price of this pack in the last 90 days of price history."},"data_date":{"type":["string","null"],"description":"Date of the newest price data."},"message":{"type":"string","description":"\"pack size not found\" or \"no current offers\"; offers is then empty."},"available_packs":{"type":"array","items":{"$ref":"#/components/schemas/PackSize"},"description":"With \"pack size not found\": the pack sizes that have offers."}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"invalid_argument, not_found, rate_limited, internal or unavailable."},"message":{"type":"string"}}}}}}}}