Returns every product of one brand at the warehouse you ask for, with full price and stock data. Filter by category and price range, and sort by popularity or price. The brand value must be the exact name returned by Brands
: matching is case-sensitive (Como Tú and Como tú are different brands). To find a keyword inside a brand, use Search
with q and brand instead.
HTTP Request
GET /brand-products
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
brand | string | Yes | - | Exact brand name as Mercadona writes it (from /brands
). An unknown brand, or one not stocked in the requested warehouse, returns empty results with resolved_filters.brand.source = "not_found" |
warehouse | string | No | vlc1 | Hub or numeric store code from /warehouses
. Ignored when postal_code is given. On store codes, brand, ean, category_path and popularity_score may be null |
postal_code | string | No | - | Spanish 5-digit postal code, resolved to the warehouse that serves it. Takes precedence over warehouse |
category_id | integer | No | - | Only products in this category (any level, see /categories ) |
min_price | number | No | - | Lowest price_value in euros, inclusive, 0 to 10000 (e.g. 2 or 1.5). total counts only products in the range; products without a price are left out when a bound is set |
max_price | number | No | - | Highest price_value in euros, inclusive, 0 to 10000. Must be greater than or equal to min_price |
sort | enum | No | popularity | popularity (most popular first), price_asc or price_desc |
page | integer | No | 1 | 1-indexed page |
per_page | integer | No | 20 | Results per page, max 20 |
fresh | boolean | No | false | Bypass the 15-minute cache. Only affects answers with source: live; catalog_index answers come from the daily catalog snapshot and refresh once a day |
language | enum | No | es | es, en or ca. Translates product and category names. Brand names are never translated |
Response
Example for brand=Hacendado&sort=price_asc&max_price=2&per_page=2 (arrays trimmed to 2 items):
| |
Response Fields
Rows use the shared product fields, including category_path and popularity_score, plus category_rank.
| Field | Type | Description |
|---|---|---|
status | boolean | true when the request succeeded |
request_id | string | Unique request identifier |
cached_at | string | null | ISO timestamp when served from cache, null when fetched for this request |
data | object | Response payload |
data.results[] | array | Product rows for this page |
data.results[].product_id | string | Mercadona product id. Pass it verbatim: decimal ids like 81241.3 exist |
data.results[].name | string | Product name, translated with language |
data.results[].slug | string | URL slug |
data.results[].url | string | Product URL on tienda.mercadona.es |
data.results[].thumbnail | string | Image URL (imgix) |
data.results[].packaging | string | null | Packaging, e.g. "Garrafa" or "Pack-6" |
data.results[].main_feature | string | null | Highlighted feature |
data.results[].is_water | boolean | Water product flag |
data.results[].requires_age_check | boolean | Alcohol or other age-restricted product |
data.results[].category | object | Level-0 category of the product |
data.results[].category.category_id | integer | Level-0 category id |
data.results[].category.name | string | Level-0 category name |
data.results[].availability | object | Stock and delivery restrictions at the resolved warehouse |
data.results[].availability.in_stock | boolean | In stock at the resolved warehouse |
data.results[].availability.status | string | null | Restriction status |
data.results[].availability.unavailable_from | string | null | Date the product stops being available |
data.results[].availability.unavailable_weekdays | array | Weekdays it can’t be delivered |
data.results[].availability.order_limit | integer | Max units per order (e.g. 999) |
data.results[].price | string | Display price in EUR, e.g. "3.70" |
data.results[].price_value | float | Numeric price in EUR |
data.results[].previous_price | string | null | Previous display price, null if the price has not dropped |
data.results[].previous_price_value | float | null | Previous numeric price |
data.results[].is_price_drop | boolean | true when the current price is below previous_price. Computed from the previous price, not Mercadona’s flag |
data.results[].unit_price | string | Display unit price, e.g. "3.700" |
data.results[].unit_price_value | float | Numeric unit price |
data.results[].unit_price_format | string | Unit of the unit price, e.g. "L" or "kg" |
data.results[].bulk_price_value | float | Bulk price |
data.results[].size_format | string | Size unit, e.g. "l" or "kg" |
data.results[].unit_size | float | Size in size_format units |
data.results[].is_pack | boolean | Pack product |
data.results[].pack_size | float | null | Pack size |
data.results[].total_units | integer | null | Units in the pack |
data.results[].unit_name | string | null | Unit name, e.g. "briks" |
data.results[].iva_percent | integer | VAT percentage |
data.results[].approx_size | boolean | Size is approximate |
data.results[].drained_weight | float | null | Drained weight |
data.results[].currency | string | Always "EUR" |
data.results[].color_variants | array | null | Colour variants |
data.results[].warehouse | string | Warehouse that answered |
data.results[].ean | string | EAN barcode |
data.results[].brand | string | Brand name as Mercadona writes it |
data.results[].category_path | array | Category paths of the product. Each path is an array from level 0 down |
data.results[].category_path[][].category_id | integer | Category id at that level |
data.results[].category_path[][].name | string | Category name |
data.results[].category_path[][].level | integer | Category level: 0, 1 or 2 |
data.results[].popularity_score | float | null | Mercadona’s internal popularity score. null on numeric store codes |
data.results[].category_rank | integer | Position of the product by popularity inside its category |
data.total | integer | Products of the brand (within the price range, if set) |
data.page | integer | Current page |
data.per_page | integer | Results per page |
data.total_pages | integer | Total pages |
data.has_next_page | boolean | true if there is another page |
data.sort | string | Sort applied |
data.source | string | catalog_index (daily catalog snapshot) or live |
data.snapshot_date | string | Date of the catalog snapshot used |
data.resolved_filters.warehouse | object | Warehouse used for this answer |
data.resolved_filters.warehouse.input | string | null | Value you sent (postal_code or warehouse), null if none |
data.resolved_filters.warehouse.resolved | string | Warehouse code that answered |
data.resolved_filters.warehouse.source | string | postal_code, param or default |
data.resolved_filters.brand | object | How the brand value was matched |
data.resolved_filters.brand.input | string | Brand you sent |
data.resolved_filters.brand.resolved | string | Brand used for the listing |
data.resolved_filters.brand.source | string | param when the brand was found, not_found when it is unknown or not stocked in this warehouse |
data.language | string | Language used for names |
request_params | object | Query parameters you sent, echoed back as strings |
Error Responses
An unknown brand is not an error. You get HTTP 200 with status: true, an empty data.results[] and data.resolved_filters.brand.source = "not_found". This also happens when the brand exists but the requested warehouse (default vlc1) does not stock it, so check /brands
with the same warehouse or postal_code, and check the exact spelling and case.
Invalid input returns HTTP 400, and error is a plain string:
| |
| Status Code | Cause | Description |
|---|---|---|
| 200 (empty results) | Brand unknown or not stocked | resolved_filters.brand.source is not_found. Check the name and warehouse with /brands |
| 400 | Missing brand | brand is required |
| 400 | Invalid warehouse | Must be a hub code like vlc1 or a 4-digit store code |
| 400 | Invalid price range | min_price and max_price must be between 0 and 10000, and max_price must be greater than or equal to min_price |
Code Examples
| |
| |
| |
Related Endpoints
- Brands : find the exact brand name and check that the warehouse stocks it
- Product Details
: full product sheet with ingredients, allergens and photos for any
product_id - Product Search
: find a keyword inside a brand with
qandbrand - Best Sellers
: the same brand ranked by popularity, with a continuous
rank