# Vivino API — live wine data scraper for the world's largest wine database and marketplace: wine search by grape, region, country, vintage, price and rating band; the wine record with its rating, rating count, per-vintage ratings, grape composition, food pairings and taste structure; the merchants selling it and their prices; and the published reviews — no API key, no login

> Search Vivino's wine database. Filters by free text, grape, region, country of origin, wine type, vintage year, price band and rating band, and every filter here was measured to change the result count. Returns the vintage id and the wine id, the rating Vivino prints on the card AND the all-vintages pool beside it, the region/winery/style, and the cheapest live merchant offer.
> ReefAPI engine `vivino` · 13 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/vivino/v1/<action>` with a JSON body.
- **Auth:** header `x-api-key: <YOUR_REEFAPI_KEY>` — create one free (1,000 credits, no card): https://reefapi.com/signup
- **Response (every call):** `{ ok: boolean, data: ..., meta: { record_count, credits, ... }, error: { code, message } }` — branch on `ok`. Failed calls are free except verified SHEIN NOT_FOUND on product/detail and price (4 credits).
- **One key + one shared credit pool** across every ReefAPI API. Per-call credits are listed on each endpoint below.
- **Use it from an AI agent (MCP):** connect `https://api.reefapi.com/mcp` (remote streamable-http). Send the key as `Authorization: Bearer <key>`, or put it in the URL (`?key=<key>`) when the client has no header field, as ChatGPT does.

## Endpoints

### POST https://api.reefapi.com/vivino/v1/search — 3 credits
Search Vivino's wine database. Filters by free text, grape, region, country of origin, wine type, vintage year, price band and rating band, and every filter here was measured to change the result count. Returns the vintage id and the wine id, the rating Vivino prints on the card AND the all-vintages pool beside it, the region/winery/style, and the cheapest live merchant offer.

**Parameters:**
- `query` (string, optional) — Free text: a wine name, a producer, a grape or a region ('catena zapata', 'barolo', 'malbec', 'grower champagne').
- `market` (enum, optional, default "us") — Which Vivino storefront to read. This changes the answer: the US and DE storefronts returned 1740 vs 740 matches for the same search and share ZERO merchants (measured 2026-09-23). Prices and availability are per storefront. [one of: us, de]
- `currency` (string, optional) — ISO currency for the prices, e.g. USD, EUR, GBP, JPY. Defaults to the market's own currency (us -> USD, de -> EUR).
- `wine_type` (enum, optional) — Wine type. Repeatable (comma-separated). [one of: red, white, sparkling, rose, dessert, fortified]
- `country_codes` (array, optional) — Country of ORIGIN of the wine, ISO-2 (ar, fr, it, es). This is the wine's origin, not the storefront — use `market` for the storefront.
- `grape_ids` (array, optional) — Grape ids from the `grapes` action (9 = Malbec).
- `region_ids` (array, optional) — Region ids (454 = Mendoza). From a search result's region.id or the `region/detail` action.
- `wine_style_ids` (array, optional) — Style ids from the `wine_styles` action.
- `winery_ids` (array, optional) — Winery ids. REFINES a search — the source rejects it as the only filter, so pass it with a query or another filter.
- `food_ids` (array, optional) — Food-pairing ids from the `foods` action (4 = Beef).
- `years` (array, optional) — Vintage year(s), e.g. 2019.
- `min_rating` (number, optional) — Lowest acceptable rating, 1-5.
- `min_ratings_count` (integer, optional) — Only wines with at least this many ratings. REFINES only.
- `price_min` (number, optional) — Lowest price, in the requested currency.
- `price_max` (number, optional) — Highest price, in the requested currency.
- `natural_only` (boolean, optional, default false) — Only natural wines.
- `discount_only` (boolean, optional, default false) — Only wines currently discounted.
- `order_by` (enum, optional) — Sort order. Measured to reorder the result set, not merely be echoed back. [one of: ratings_average, ratings_count, price, discount_percent, relevance, best_picks]
- `order` (enum, optional) — Sort direction. Defaults to desc, except order_by=price which defaults to asc. [one of: desc, asc]
- `page` (integer, optional, default 1) — 1-based page number.
- `per_page` (integer, optional, default 25) — Results per page, 1-50. The source refuses more than 50 (HTTP 400).

**Returns:** records_matched, wines[]{vintage_id, wine_id, name, year, url, wine_type, rating, ratings_count, wine_rating, wine_ratings_count, region, country, winery, style, taste, best_price, prices[]}. NOTE: `rating`/`ratings_count` are the figures Vivino prints on the card, which for a vintage it has not yet rated on its own are the WINE-level pool (measured on 16 of 18 rows). `wine/detail` returns the vintage's own numbers.

**Example request body:**
```json
{
  "query": "barolo",
  "per_page": 10
}
```

### POST https://api.reefapi.com/vivino/v1/wine/detail — 2 credits
One VINTAGE in full: the vintage's own rating, rating count and review count (and the flag saying whether Vivino rates this vintage on its own), the wine-level pool beside it, the ratings histogram, the global/country/region/winery ranks, the grape composition in percent, food pairings, the crowd taste structure, both published alcohol figures, the drinking window and the critic scores.

**Parameters:**
- `vintage_id` (integer, optional) — The VINTAGE to read — one specific year of one wine. Accepts the numeric vintage id from search, or a vivino.com wine URL. Vintage, not wine: the same wine rates and prices differently per year.
- `market` (enum, optional, default "us") — Which Vivino storefront to read. This changes the answer: the US and DE storefronts returned 1740 vs 740 matches for the same search and share ZERO merchants (measured 2026-09-23). Prices and availability are per storefront. [one of: us, de]
- `include_taste` (boolean, optional, default true) — Fetch the crowd taste structure and flavour groups. Vivino serves these on a separate route, so this costs one extra upstream request; set false to skip it.

**Returns:** A vintage record: vintage_rating, vintage_ratings_count, vintage_reviews_count, vintage_rating_status, wine_rating, wine_ratings_count, ratings_distribution, ranking, grapes, grape_composition[]{grape_id,name,percent}, food_pairings, taste{structure,flavors}, alcohol_percent_wine, alcohol_percent_vintage, closure, drinking_window, critic_reviews[], region, country, winery, style.

**Example request body:**
```json
{
  "vintage_id": 2459253
}
```

### POST https://api.reefapi.com/vivino/v1/wine/vintages — 1 credit
Every year of the same wine with that year's OWN rating, rating count and review count. This is the row a collector compares, and it is the honest answer to 'is the 2019 better than the 2018' — the search card cannot answer it.

**Parameters:**
- `vintage_id` (integer, optional) — The VINTAGE to read — one specific year of one wine. Accepts the numeric vintage id from search, or a vivino.com wine URL. Vintage, not wine: the same wine rates and prices differently per year.
- `market` (enum, optional, default "us") — Which Vivino storefront to read. This changes the answer: the US and DE storefronts returned 1740 vs 740 matches for the same search and share ZERO merchants (measured 2026-09-23). Prices and availability are per storefront. [one of: us, de]

**Returns:** wine_id, wine_name, wine_rating, wine_ratings_count, vintages[]{vintage_id, year, rating, ratings_count, reviews_count, rating_status, url} newest year first.

**Example request body:**
```json
{
  "vintage_id": 2459253
}
```

### POST https://api.reefapi.com/vivino/v1/wine/prices — 1 credit
The marketplace half: every merchant Vivino lists for one vintage, with its price, bottle size, discount and link. Also the median, cheapest and dearest offer. The merchant set is per storefront — the US and DE markets share none.

**Parameters:**
- `vintage_id` (integer, optional) — The VINTAGE to read — one specific year of one wine. Accepts the numeric vintage id from search, or a vivino.com wine URL. Vintage, not wine: the same wine rates and prices differently per year.
- `market` (enum, optional, default "us") — Which Vivino storefront to read. This changes the answer: the US and DE storefronts returned 1740 vs 740 matches for the same search and share ZERO merchants (measured 2026-09-23). Prices and availability are per storefront. [one of: us, de]
- `currency` (string, optional) — ISO currency for the prices, e.g. USD, EUR, GBP, JPY. Defaults to the market's own currency (us -> USD, de -> EUR).

**Returns:** vintage_id, market_country, market_state, currency, median_price, min_price, max_price, best_price, offers[]{merchant{id,name,country,state,shipping_note}, price{amount,currency,discounted_from,discount_percent_source,discount_percent_computed,bottle_volume_ml,bottle_type,url}}. Current prices only — Vivino does not publish price history on the logged-out surface.

**Example request body:**
```json
{
  "vintage_id": 2459253
}
```

### POST https://api.reefapi.com/vivino/v1/wine/reviews — 2 credits
The published reviews for a wine, newest first, with the star rating, the note and the reviewer Vivino shows on the page. Pass `year` to read one vintage's reviews.

**Parameters:**
- `wine_id` (integer, optional) — The WINE (all vintages pooled). Accepts the numeric wine id from search or a vivino.com wine URL.
- `year` (integer, optional) — Restrict to one vintage year.
- `market` (enum, optional, default "us") — Which Vivino storefront to read. This changes the answer: the US and DE storefronts returned 1740 vs 740 matches for the same search and share ZERO merchants (measured 2026-09-23). Prices and availability are per storefront. [one of: us, de]
- `page` (integer, optional, default 1) — 1-based page number.
- `per_page` (integer, optional, default 25) — Reviews per page, 1-50. Asking for more returns 50.

**Returns:** wine_id, reviews[]{review_id, rating, note, language, created_at, reviewer{id,alias,handle,profile_url,is_featured,is_premium}, vintage_id, vintage_year}.

**Example request body:**
```json
{
  "wine_id": 82199,
  "per_page": 10
}
```

### POST https://api.reefapi.com/vivino/v1/wine/highlights — 1 credit
The badges and ranks Vivino awards a vintage: global rank, rank within its country, its region and its winery, plus the critic scores behind them.

**Parameters:**
- `vintage_id` (integer, optional) — The VINTAGE to read — one specific year of one wine. Accepts the numeric vintage id from search, or a vivino.com wine URL. Vintage, not wine: the same wine rates and prices differently per year.
- `market` (enum, optional, default "us") — Which Vivino storefront to read. This changes the answer: the US and DE storefronts returned 1740 vs 740 matches for the same search and share ZERO merchants (measured 2026-09-23). Prices and availability are per storefront. [one of: us, de]

**Returns:** vintage_id, ranking{global,country,region,winery}{rank,out_of,description}, highlights[]{type,message}.

**Example request body:**
```json
{
  "vintage_id": 2459253
}
```

### POST https://api.reefapi.com/vivino/v1/wines/batch — 3 credits
Up to 50 vintages in ONE call — how a catalogue of thousands is refreshed without spending a call per wine. `full=false` returns the identity and rating block at about a fifth of the bytes.

**Parameters:**
- `vintage_ids` (array, required) — Vintage ids, up to 50 per call.
- `market` (enum, optional, default "us") — Which Vivino storefront to read. This changes the answer: the US and DE storefronts returned 1740 vs 740 matches for the same search and share ZERO merchants (measured 2026-09-23). Prices and availability are per storefront. [one of: us, de]
- `full` (boolean, optional, default true) — true = the complete vintage record; false = identity, year and ratings only, about 5x smaller.

**Returns:** wines[] in the same shape as wine/detail (full=true) or an identity+rating row (full=false), plus requested/returned counts and missing_ids[].

**Example request body:**
```json
{
  "vintage_ids": [
    2459253,
    2459252
  ]
}
```

### POST https://api.reefapi.com/vivino/v1/winery/wines — 3 credits
A winery's catalogue: every wine it makes, with the wine-level rating and the best-rated vintage of each.

**Parameters:**
- `winery_id` (integer, required) — Winery id, from any search result's winery.id.
- `market` (enum, optional, default "us") — Which Vivino storefront to read. This changes the answer: the US and DE storefronts returned 1740 vs 740 matches for the same search and share ZERO merchants (measured 2026-09-23). Prices and availability are per storefront. [one of: us, de]

**Returns:** winery_id, wines[]{wine_id, name, url, wine_type, wine_rating, wine_ratings_count, region, country, style, best_vintage_id, best_vintage_year}.

**Example request body:**
```json
{
  "winery_id": 11472
}
```

### POST https://api.reefapi.com/vivino/v1/region/detail — 1 credit
One wine region: its country, parent and sub-regions, its top grapes and how many wines and wineries Vivino holds for it.

**Parameters:**
- `region_id` (integer, required) — Region id (454 = Mendoza).
- `market` (enum, optional, default "us") — Which Vivino storefront to read. This changes the answer: the US and DE storefronts returned 1740 vs 740 matches for the same search and share ZERO merchants (measured 2026-09-23). Prices and availability are per storefront. [one of: us, de]

**Returns:** region_id, name, country, parent_region_id, description, wines_count, wineries_count, ratings_count, ratings_average, sub_regions[], top_grapes[].

**Example request body:**
```json
{
  "region_id": 504
}
```

### POST https://api.reefapi.com/vivino/v1/grapes — 2 credits
The grape enum behind `grape_ids` — 2229 grape varieties with the id, the name and how many wines Vivino holds for each.

**Parameters:**
- `query` (string, optional) — Filter the list by name, case-insensitive.
- `market` (enum, optional, default "us") — Which Vivino storefront to read. This changes the answer: the US and DE storefronts returned 1740 vs 740 matches for the same search and share ZERO merchants (measured 2026-09-23). Prices and availability are per storefront. [one of: us, de]
- `per_page` (integer, optional, default 25) — Results per page, 1-50. The source refuses more than 50 (HTTP 400).

**Returns:** grapes[]{id, name, seo_name, wines_count, parent_grape_id}.

**Example request body:**
```json
{
  "query": "nebbiolo"
}
```

### POST https://api.reefapi.com/vivino/v1/foods — 1 credit
The food-pairing enum behind `food_ids` — the 23 pairings Vivino uses.

**Parameters:**
- `market` (enum, optional, default "us") — Which Vivino storefront to read. This changes the answer: the US and DE storefronts returned 1740 vs 740 matches for the same search and share ZERO merchants (measured 2026-09-23). Prices and availability are per storefront. [one of: us, de]

**Returns:** foods[]{id, name, seo_name}.

**Example request body:**
```json
{
  "market": "us"
}
```

### POST https://api.reefapi.com/vivino/v1/wine_styles — 2 credits
The style enum behind `wine_style_ids` — 747 regional styles such as 'Argentinian Mendoza Malbec'.

**Parameters:**
- `query` (string, optional) — Filter the list by name, case-insensitive.
- `market` (enum, optional, default "us") — Which Vivino storefront to read. This changes the answer: the US and DE storefronts returned 1740 vs 740 matches for the same search and share ZERO merchants (measured 2026-09-23). Prices and availability are per storefront. [one of: us, de]
- `per_page` (integer, optional, default 25) — Results per page, 1-50. The source refuses more than 50 (HTTP 400).

**Returns:** wine_styles[]{id, name, regional_name, varietal_name, seo_name}.

**Example request body:**
```json
{
  "query": "barolo"
}
```

### POST https://api.reefapi.com/vivino/v1/countries — 2 credits
The country enum behind `country_codes` — 253 countries with how many wines and wineries Vivino holds for each, and their most used grapes.

**Parameters:**
- `market` (enum, optional, default "us") — Which Vivino storefront to read. This changes the answer: the US and DE storefronts returned 1740 vs 740 matches for the same search and share ZERO merchants (measured 2026-09-23). Prices and availability are per storefront. [one of: us, de]

**Returns:** countries[]{code, name, wines_count, wineries_count, regions_count, top_grapes[]}.

**Example request body:**
```json
{
  "market": "us"
}
```

## At scale
- **Volume:** 5M+ requests a day, measured at 60 requests a second across the fleet with no
  central bottleneck. Per-key limits are raised for high-volume accounts; volume pricing on request.
- **Missing a source:** tell us a site we do not cover and it becomes an engine. A customer asked
  for bestprice.gr on 21 Sep 2026 and it was in the catalog on 22 Sep.
- **Support:** 2 minute median time from a question in the live chat to the first answer. Setup
  help included, no support tier to buy.
- **One key, one credit pool** across every API. No per-site plans, no separate subscriptions.

## More
- Try it live, no code: https://reefapi.com/playground?engine=vivino
- Human docs page: https://reefapi.com/docs/vivino
- Overview page: https://reefapi.com/vivino-api
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
