Returns the complete product sheet for one Mercadona product, looked up by product_id or by EAN barcode. On top of the standard product row (price, unit price, previous price, availability, brand, category path) you get ingredients and allergens as HTML and plain text, origin, suppliers, legal name, storage and usage instructions, alcohol content and every product photo. Prices and stock are for the warehouse that serves the postal code you pass, and the product must be stocked there.
HTTP Request
GET /product-details
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
product_id | string | One of | - | Mercadona product id, passed verbatim. Decimal ids like 81241.3 exist (81241 is a different, unknown id). Pass exactly one of product_id or ean |
ean | string | One of | - | EAN-13 barcode. Counter items carry internal 2105… codes. The response is the same as for product_id |
postal_code | string | No | - | Spanish 5-digit postal code. Resolved to the warehouse that serves that address and takes precedence over warehouse |
warehouse | string | No | vlc1 | Hub or 4-digit store code from /warehouses
. The product must be stocked there. Ignored when postal_code is given |
language | string | No | es | es, en or ca. Only name and category names are translated. Description, ingredients, allergens and the other texts stay in Spanish |
fresh | boolean | No | false | Bypass the product cache (1 hour, 20 minutes when availability is restricted) and fetch live data |
Numeric store codes are served live: popularity_score is null, and brand, ean or category_path may be null.
Response
Request: GET /product-details?product_id=10381&postal_code=08001
| |
Response Fields
| Field | Type | Description |
|---|---|---|
status | boolean | true when the product was found |
request_id | string | Unique request identifier |
cached_at | string | null | ISO timestamp when the answer came from cache, null when fetched for this request |
data | object | The product |
data.product_id | string | Mercadona product id. Pass it verbatim: decimal ids like 81241.3 exist |
data.name | string | Product name, translated with language |
data.slug | string | URL slug of the product page |
data.url | string | Product URL on tienda.mercadona.es |
data.thumbnail | string | Product image URL (300x300) |
data.packaging | string | null | Packaging label, e.g. "Pack-6" or "Brik" |
data.main_feature | string | null | Highlighted feature, when Mercadona sets one |
data.is_water | boolean | Water product flag |
data.requires_age_check | boolean | Alcohol or other age-restricted product |
data.category | object | Level-0 category of the product |
data.category.category_id | integer | Level-0 category id |
data.category.name | string | Level-0 category name, translated with language |
data.availability | object | Availability at the resolved warehouse |
data.availability.in_stock | boolean | In stock at the resolved warehouse |
data.availability.status | string | null | Restriction status, null when unrestricted |
data.availability.unavailable_from | string | null | Date the product stops being available |
data.availability.unavailable_weekdays | array | Weekdays the product can’t be delivered |
data.availability.order_limit | integer | Maximum units per order, e.g. 999 |
data.price | string | Display price in euros, e.g. "4.98" |
data.price_value | float | Numeric price in euros |
data.previous_price | string | null | Previous display price, null when there is none |
data.previous_price_value | float | null | Previous numeric price |
data.is_price_drop | boolean | true when the current price is below the previous price (computed by the API, not a Mercadona flag) |
data.unit_price | string | Display unit price, e.g. "0.830" |
data.unit_price_value | float | Numeric unit price |
data.unit_price_format | string | Unit the unit price refers to, e.g. "L" or "kg" |
data.bulk_price_value | float | Bulk price |
data.size_format | string | Size unit, e.g. "l" |
data.unit_size | float | Size expressed in size_format units |
data.is_pack | boolean | Product is sold as a pack |
data.pack_size | float | null | Size of each unit in the pack |
data.total_units | integer | null | Number of units in the pack |
data.unit_name | string | null | Name of each unit, e.g. "briks" |
data.iva_percent | integer | VAT percentage |
data.approx_size | boolean | Size is approximate |
data.drained_weight | float | null | Drained weight, for canned or preserved products |
data.currency | string | Always "EUR" |
data.color_variants | array | null | Colour variants, null when the product has none |
data.warehouse | string | Warehouse that answered for this row |
data.ean | string | EAN-13 barcode |
data.brand | string | Brand name as Mercadona writes it |
data.category_path | array | Category paths of the product. Each path is an array of objects from level 0 down |
data.category_path[][].category_id | integer | Category id |
data.category_path[][].name | string | Category name, translated with language |
data.category_path[][].level | integer | Category level: 0, 1 or 2 |
data.popularity_score | float | null | Mercadona’s internal popularity score. null on numeric store codes |
data.is_new | boolean | Flagged as new by Mercadona |
data.origin | string | Origin, e.g. "España" |
data.photos[] | array | All product photos |
data.photos[].zoom | string | Image URL, 3600x3600 |
data.photos[].regular | string | Image URL, 600x600 |
data.photos[].thumbnail | string | Image URL, 300x300 |
data.photos[].perspective | integer | Perspective number of the photo |
data.ingredients | string | Ingredients as HTML. <strong> marks allergens |
data.ingredients_text | string | Ingredients as plain text |
data.allergens | string | Allergen statement as HTML |
data.allergens_text | string | Allergen statement as plain text |
data.legal_name | string | Legal denomination of the product |
data.description | string | Product description |
data.suppliers[] | array of strings | Supplier names |
data.storage_instructions | string | null | Storage instructions |
data.usage_instructions | string | null | Usage instructions |
data.mandatory_mentions | string | null | Mandatory label mentions, e.g. "100% granjas nacionales" |
data.danger_mentions | string | null | Hazard text |
data.alcohol_by_volume | string | null | Alcohol by volume, display value |
data.alcohol_by_volume_value | float | null | Alcohol by volume, numeric |
data.counter_info | string | null | Information for counter (fresh) items |
data.production_variant | string | null | Production variant |
data.is_prepared_by_mercadona | boolean | Ready meal prepared by Mercadona |
data.is_bulk | boolean | Sold loose |
data.is_variable_weight | boolean | Price depends on the weight served |
data.snapshot_date | string | Date of the catalog snapshot, YYYY-MM-DD |
data.resolved_filters | object | What your filters resolved to |
data.resolved_filters.warehouse | object | Warehouse resolution |
data.resolved_filters.warehouse.input | string | null | The postal_code or warehouse you sent |
data.resolved_filters.warehouse.resolved | string | Warehouse that answered, e.g. bcn1 |
data.resolved_filters.warehouse.source | string | postal_code, param or default |
data.resolved_filters.ean | object | Only when looked up by ean: {input, resolved, source}, where resolved is the matching product_id and source is "index" |
data.language | string | Language used |
request_params | object | Query parameters you sent, echoed back as strings |
Error Responses
When the product can’t be found, the API returns HTTP 200 with status: false, data: null and an error object. Unknown barcode:
| |
The message mentions /mercadona/search. That is an internal path: the public endpoint is /search
.
Invalid input returns HTTP 400 with error as a plain string. Passing both product_id and ean, or neither:
| |
| Status Code | Cause | Description |
|---|---|---|
200, error.code: ean_not_found | Unknown barcode | No product with that EAN in the catalog. It may be a counter item or not sold online. Search by name instead |
200, error.code: not_found_in_warehouse | Not stocked | The product exists but isn’t stocked in the resolved warehouse. Try another postal code |
200, error.code: not_found | Unknown product id | No product with that product_id. Check decimal ids are passed verbatim |
| 400 | Both or neither of product_id / ean | Pass exactly one of them |
| 400 | Invalid warehouse | Must be a hub code (3 letters + 1 digit) or a 4-digit store code |
Check status before reading data: not-found answers are HTTP 200.
Code Examples
| |
| |
| |
Related Endpoints
- Product Search : find product ids and barcodes by keyword
- Related Products : products Mercadona suggests alongside this one
- Brand Products : every product of the same brand
- Resolve Warehouse : check which warehouse a postal code maps to