{"openapi":"3.0.3","info":{"version":"1.0.0","x-category":"Food","x-website":"https:\/\/wine.mediashare.ro","x-version-lifecycle":"active","title":"Vivino Wine Search API - Direct Clients","description":"Direct\/internal OpenAPI document for server-to-server clients using bearer token authentication.","x-long-description":"This direct-client variant documents the same wine search API for private or first-party integrations. Authenticate with an API client token sent as an Authorization bearer token."},"servers":[{"url":"https:\/\/wine.mediashare.ro","description":"Production server"}],"tags":[{"name":"Wine","description":"Wine search and enrichment endpoints."},{"name":"Usage","description":"API key usage and rate limit visibility."},{"name":"Health","description":"Service health and availability endpoints."}],"paths":{"\/api\/usage":{"get":{"tags":["Usage"],"summary":"Get API key usage","description":"Returns usage stats for the authenticated API key, including requests used, requests remaining, percentage used, and the reset time for the current rate limit window.","operationId":"getApiUsage","responses":{"200":{"description":"Current monthly API key usage and per-minute burst usage.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Per-minute burst limit."},"X-RateLimit-Used":{"schema":{"type":"integer"},"description":"Requests used in the current per-minute window."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests remaining in the current per-minute window."},"X-RateLimit-Used-Percent":{"schema":{"type":"number"},"description":"Percentage of the current per-minute window used."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix timestamp when the per-minute window resets."},"X-RateLimit-Reset-After":{"schema":{"type":"integer"},"description":"Seconds until the per-minute window resets."},"X-MonthlyLimit-Limit":{"schema":{"type":"integer"},"description":"Monthly subscription quota. Omitted for unlimited clients."},"X-MonthlyLimit-Used":{"schema":{"type":"integer"},"description":"Requests used in the current 30-day subscription window."},"X-MonthlyLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests remaining in the current 30-day subscription window. Omitted for unlimited clients."},"X-MonthlyLimit-Used-Percent":{"schema":{"type":"number"},"description":"Percentage of the current monthly quota used. Omitted for unlimited clients."},"X-MonthlyLimit-Reset":{"schema":{"type":"integer"},"description":"Unix timestamp when the monthly subscription window resets."},"X-MonthlyLimit-Reset-After":{"schema":{"type":"integer"},"description":"Seconds until the monthly subscription window resets."},"X-MonthlyLimit-Unlimited":{"schema":{"type":"boolean"},"description":"Present as true when the client has no monthly quota."}},"content":{"application\/json":{"schema":{"type":"object","required":["usage","per_minute"],"properties":{"usage":{"$ref":"#\/components\/schemas\/ApiUsage"},"per_minute":{"$ref":"#\/components\/schemas\/PerMinuteUsage"}}},"example":{"usage":{"client_id":1,"client_name":"Storefront importer","period":"subscription_30_days","unlimited":false,"limit":2592000,"used":12,"remaining":2591988,"used_percent":0.01,"reset_at":1782316860,"reset_after_seconds":42},"per_minute":{"limit":60,"used":1,"remaining":59,"used_percent":1.67,"reset_at":1782316860,"reset_after_seconds":42}}}}},"401":{"description":"Missing, invalid, or inactive API key.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":"Invalid or inactive API key."}}}},"429":{"description":"Rate limit exceeded.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":"Rate limit exceeded."}}}}},"security":[{"BearerAuth":[]}]}},"\/api\/wine\/search":{"get":{"tags":["Wine"],"summary":"Search for a wine","description":"Returns the best matching wine for a natural-language product name or wine title, including winery, vintage, ratings, source URL, and average price data when available.","operationId":"searchWine","parameters":[{"name":"q","in":"query","required":true,"description":"Wine name, product title, or search phrase to match.","schema":{"type":"string","example":"Purcari Malbec"}}],"responses":{"200":{"description":"A matching wine object, or an empty array when no match is found.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Per-minute burst limit."},"X-RateLimit-Used":{"schema":{"type":"integer"},"description":"Requests used in the current per-minute window."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests remaining in the current per-minute window."},"X-RateLimit-Used-Percent":{"schema":{"type":"number"},"description":"Percentage of the current per-minute window used."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix timestamp when the per-minute window resets."},"X-RateLimit-Reset-After":{"schema":{"type":"integer"},"description":"Seconds until the per-minute window resets."},"X-MonthlyLimit-Limit":{"schema":{"type":"integer"},"description":"Monthly subscription quota. Omitted for unlimited clients."},"X-MonthlyLimit-Used":{"schema":{"type":"integer"},"description":"Requests used in the current 30-day subscription window."},"X-MonthlyLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests remaining in the current 30-day subscription window. Omitted for unlimited clients."},"X-MonthlyLimit-Used-Percent":{"schema":{"type":"number"},"description":"Percentage of the current monthly quota used. Omitted for unlimited clients."},"X-MonthlyLimit-Reset":{"schema":{"type":"integer"},"description":"Unix timestamp when the monthly subscription window resets."},"X-MonthlyLimit-Reset-After":{"schema":{"type":"integer"},"description":"Seconds until the monthly subscription window resets."},"X-MonthlyLimit-Unlimited":{"schema":{"type":"boolean"},"description":"Present as true when the client has no monthly quota."}},"content":{"application\/json":{"schema":{"oneOf":[{"$ref":"#\/components\/schemas\/Wine"},{"type":"array","maxItems":0,"items":{}}]},"examples":{"wine":{"summary":"Wine found","value":{"name":"Malbec","winery":"Purcari","year":2020,"score":4.3,"reviews":250,"url":"https:\/\/www.vivino.com\/purcari-malbec\/w\/1234567","avg_price":"99.99","currency":"EUR"}},"packagedWine":{"summary":"Wine found","value":{"name":"Leaf","winery":"Migdal-P - Chateau Cojusna","year":null,"score":3.7,"reviews":12,"url":"https:\/\/www.vivino.com\/leaf-cabernet-sauvignon\/w\/1","avg_price":"99.99","currency":"EUR"}},"noMatch":{"summary":"No matching wine","value":[]}}}}},"400":{"description":"Invalid search request.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"examples":{"missingQuery":{"summary":"Missing search query","value":{"error":"The search query is required."}},"invalidPrice":{"summary":"Invalid price","value":{"error":"The price query parameter must be numeric."}}}}}},"401":{"description":"Missing, invalid, or inactive API key.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":"Invalid or inactive API key."}}}},"429":{"description":"Per-minute burst rate limit or monthly usage limit exceeded.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Per-minute burst limit."},"X-RateLimit-Used":{"schema":{"type":"integer"},"description":"Requests used in the current per-minute window."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests remaining in the current per-minute window."},"X-RateLimit-Used-Percent":{"schema":{"type":"number"},"description":"Percentage of the current per-minute window used."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix timestamp when the per-minute window resets."},"X-RateLimit-Reset-After":{"schema":{"type":"integer"},"description":"Seconds until the per-minute window resets."},"X-MonthlyLimit-Limit":{"schema":{"type":"integer"},"description":"Monthly subscription quota. Omitted for unlimited clients."},"X-MonthlyLimit-Used":{"schema":{"type":"integer"},"description":"Requests used in the current 30-day subscription window."},"X-MonthlyLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests remaining in the current 30-day subscription window. Omitted for unlimited clients."},"X-MonthlyLimit-Used-Percent":{"schema":{"type":"number"},"description":"Percentage of the current monthly quota used. Omitted for unlimited clients."},"X-MonthlyLimit-Reset":{"schema":{"type":"integer"},"description":"Unix timestamp when the monthly subscription window resets."},"X-MonthlyLimit-Reset-After":{"schema":{"type":"integer"},"description":"Seconds until the monthly subscription window resets."},"X-MonthlyLimit-Unlimited":{"schema":{"type":"boolean"},"description":"Present as true when the client has no monthly quota."}},"content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"examples":{"perMinute":{"summary":"Per-minute burst limit exceeded","value":{"error":"Rate limit exceeded."}},"monthly":{"summary":"Monthly quota exceeded","value":{"error":"Monthly usage limit exceeded."}}}}}},"500":{"description":"Unexpected search failure.","content":{"application\/json":{"schema":{"$ref":"#\/components\/schemas\/Error"},"example":{"error":"An error occurred during search."}}}}},"security":[{"BearerAuth":[]}]}},"\/health":{"get":{"tags":["Health"],"summary":"Health check","description":"Returns a simple service status response for uptime monitoring. This endpoint does not require authentication.","operationId":"healthCheck","security":[],"responses":{"200":{"description":"The API is reachable.","content":{"application\/json":{"schema":{"type":"object","required":["status","service"],"properties":{"status":{"type":"string","example":"ok"},"service":{"type":"string","example":"vivino-wine-search-api"}}},"example":{"status":"ok","service":"vivino-wine-search-api"}}}}}}}},"components":{"schemas":{"Wine":{"type":"object","properties":{"name":{"type":"string","nullable":true,"example":"Malbec"},"winery":{"type":"string","nullable":true,"example":"Purcari"},"year":{"type":"integer","nullable":true,"example":2020},"score":{"type":"number","format":"float","nullable":true,"example":4.3},"reviews":{"type":"integer","nullable":true,"example":250},"url":{"type":"string","nullable":true,"example":"https:\/\/www.vivino.com\/purcari-malbec\/w\/1234567"},"avg_price":{"type":"string","nullable":true,"example":"99.99"},"currency":{"type":"string","nullable":true,"example":"EUR"}}},"ApiUsage":{"type":"object","required":["client_id","client_name","period","unlimited","limit","used","remaining","used_percent","reset_at","reset_after_seconds"],"properties":{"client_id":{"type":"integer","example":1},"client_name":{"type":"string","example":"Storefront importer"},"period":{"type":"string","example":"subscription_30_days"},"unlimited":{"type":"boolean","example":false},"limit":{"type":"integer","nullable":true,"example":2592000},"used":{"type":"integer","example":12},"remaining":{"type":"integer","nullable":true,"example":2591988},"used_percent":{"type":"number","format":"float","nullable":true,"example":0.01},"reset_at":{"type":"integer","nullable":true,"example":1782316860},"reset_after_seconds":{"type":"integer","example":42}}},"PerMinuteUsage":{"type":"object","required":["limit","used","remaining","used_percent","reset_at","reset_after_seconds"],"properties":{"limit":{"type":"integer","example":60},"used":{"type":"integer","example":1},"remaining":{"type":"integer","example":59},"used_percent":{"type":"number","format":"float","example":1.67},"reset_at":{"type":"integer","nullable":true,"example":1782316860},"reset_after_seconds":{"type":"integer","example":42}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string","example":"Invalid or inactive API key."}}}},"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API key","description":"Direct client API key sent as Authorization: Bearer {api_key}."}}},"security":[{"BearerAuth":[]}]}