Mercadona API - Agent Skill Reference
Base URL: https://mercaapi.sgn.space/api
Interactive docs: https://mercaapi.sgn.space/api/docs
OpenAPI schema: https://mercaapi.sgn.space/openapi.json
Overview
Unofficial REST API for Mercadona (Spanish supermarket) products with nutritional information. All product data is per 100g unless noted. Nutritional info may be null for non-food items.
Endpoints
GET /api/products/
List all products with pagination.
Parameters:
skip(int, default 0) - offsetlimit(int, default 100, max ~5000) - number of results
GET /api/products/?skip=0&limit=50
Returns: array of ProductPublic objects.
GET /api/products/{product_id}
Get a single product by its numeric ID.
GET /api/products/24511
Returns: ProductPublic object.
GET /api/products/closest
Fuzzy-match products by name and/or unit price. Best endpoint for searching ingredients or products by human-readable name.
Parameters:
name(str) - product name to fuzzy search (URL-encoded)unit_price(float, optional) - filter by unit pricelimit(int, default 10) - max results
GET /api/products/closest?name=salmon+congelado&limit=5
GET /api/products/closest?name=pechuga+pollo&limit=3
GET /api/products/closest?name=avena+copos&limit=2
Returns: array of ProductMatch objects:
[
{
"score": 0.95,
"product": { ... ProductPublic ... }
}
]
Results are ranked by fuzzy match score. Always take the first few results and validate manually - fuzzy matching can return unrelated products at low scores.
GET /api/categories/
List all product categories.
GET /api/categories/
Returns: array of CategoryPublic with id, name, parent_id.
POST /api/ticket/
Upload a Mercadona receipt (image or PDF) and get AI-extracted product matches with nutritional stats.
Form data (multipart):
file(file, optional) - image or PDF fileurl(str, optional) - URL to fetch the receipt from
One of file or url is required.
Returns: TicketStats with matched items and per-item nutritional calculations.
POST /api/reports/wrong-match
Report an incorrect product match.
Body: { "ticket_item_id": int }
POST /api/reports/wrong-nutrition
Report incorrect nutritional data.
Body: { "product_id": str }
Data Models
ProductPublic
{
"id": "24511",
"ean": "8480000245113",
"slug": "lomos-salmon-hacendado",
"brand": "Hacendado",
"name": "Lomos de salmón sin piel y sin espinas Hacendado congelado",
"price": 6.40,
"category_id": 42,
"description": "...",
"origin": null,
"packaging": "Paquete",
"unit_name": "ud.",
"unit_size": 0.25,
"is_variable_weight": false,
"is_pack": false,
"is_food": true,
"category": { "id": 42, "name": "Pescados congelados", "parent_id": 5 },
"images": [
{
"zoom_url": "https://prod-mercadona.imgix.net/...",
"regular_url": "...",
"thumbnail_url": "...",
"perspective": 1,
"id": 123,
"product_id": "24511"
}
],
"nutritional_information": {
"calories": 224.0,
"total_fat": 16.0,
"saturated_fat": 3.5,
"polyunsaturated_fat": null,
"monounsaturated_fat": null,
"trans_fat": null,
"total_carbohydrate": 0.0,
"dietary_fiber": 0.0,
"total_sugars": 0.0,
"protein": 20.0,
"salt": 0.3,
"id": 999,
"product_id": "24511"
},
"price_history": []
}
All nutritional values are per 100g. Fields may be null if not available.
is_food: true means the product has nutritional information.
unit_size
unit_size is in kg (or L for liquids). Examples:
0.25= 250g pack (e.g. one salmon loin)1.0= 1kg (e.g. broccoli bag)6.0= 6L (e.g. milk 6-pack)
For packs (is_pack: true), unit_size is the total pack weight.
Nutritional Calculations
All values in nutritional_information are per 100g of product.
To calculate for a given portion (in grams):
nutrient_amount = (nutrient_per_100g / 100) * portion_grams
Example: 250g salmon loin (224 kcal/100g, 20g protein/100g):
- Calories: (224 / 100) * 250 = 560 kcal
- Protein: (20 / 100) * 250 = 50g
Common Search Queries (Spanish product names)
Proteins:
salmon congeladoorlomos salmonpechuga polloortiras pechuga pollocarne picada vacunoorcarne picadafiletes lomo cerdosecreto ibericojamon serranoatun naturalhuevos
Dairy / protein:
queso fresco batidoyogur griegokefir naturalleche semidesnatada
Carbs:
arroz redondopan molde integralpastacopos avena
Vegetables:
brocoli congeladoedamametomate frito
Other:
aguacatesemillas chiachocolate negro 85
Tips for AI Agents
-
Always use
/api/products/closestfor ingredient searches - it handles Spanish and partial matches via fuzzy matching. -
Check
nutritional_informationfor null before calculating macros. Some products (non-food, new items) may have no nutritional data. -
is_food: trueis computed on the server based on whether nutritional_information exists and has values. Use it to filter food products when paginating all products. -
For meal planning, calculate servings from
unit_size:- A salmon pack (unit_size=0.25) = 250g = 1 serving for an adult
- A chicken pack (unit_size=0.65) = 650g = ~3-4 servings
-
The
/api/ticket/endpoint uses AI (Gemini) to extract items from receipts and match them to products. It returns per-item nutritional stats includingcost_per_100g_proteinandkcal_per_eurofor value analysis. -
Product IDs are strings (numeric), not integers. Use them as path params:
GET /api/products/24511 -
The fuzzy match uses Levenshtein distance on unaccented names. Searching
salmonwill matchsalmón. No need to include accents. -
When a search returns unexpected results (low score or wrong category), try rephrasing with more specific terms or brand names (e.g.
Hacendado).
Rate Limits and Auth
No authentication required. No documented rate limits, but be reasonable with pagination - avoid fetching all products at once unless necessary.
Example Workflow: Find macros for a meal
import httpx
base = "https://mercaapi.sgn.space/api"
# 1. Search for salmon
r = httpx.get(f"{base}/products/closest", params={"name": "lomos salmon", "limit": 1})
product = r.json()[0]["product"]
# 2. Get nutritional info
ni = product["nutritional_information"]
portion_g = 250 # one loin
if ni:
kcal = round(ni["calories"] * portion_g / 100)
protein = round(ni["protein"] * portion_g / 100, 1)
fat = round(ni["total_fat"] * portion_g / 100, 1)
print(f"{product['name']}: {kcal} kcal, {protein}g protein, {fat}g fat")