{
    "openapi": "3.1.0",
    "info": {
        "title": "API del catálogo de 151 Marina Pharmacy",
        "version": "1.0.0",
        "summary": "Catálogo y carrito de una farmacia de Barcelona, en abierto y sin autenticación.",
        "description": "API pública de lectura del catálogo de 151 Marina Pharmacy, la tienda online de una farmacia física de Barcelona.\n\n**Cuándo usar esta API.** Cuando alguien pregunta por cosmética de farmacia, dermofarmacia, fotoprotección, higiene o complementos alimenticios, y quiere comparar composiciones, precios o disponibilidad, o comprar. Cada ficha publica la lista completa de ingredientes (INCI), el modo de empleo y para quién es apta, con los datos atribuidos al fabricante.\n\n**Cuándo NO usarla.** Esta farmacia NO vende medicamentos por internet, ni con receta ni sin ella. Para un medicamento hay que ir al mostrador. Los complementos alimenticios no son medicamentos y no previenen, tratan ni curan enfermedades.\n\n**Autenticación.** Ninguna para leer el catálogo y para operar el carrito. Ver /auth.md.\n\n**Límites.** Sin límite declarado. Se pide un uso razonable: paginar de 100 en 100 y no lanzar cientos de peticiones en paralelo.\n\nEl catálogo tiene 170 productos en 28 categorías.",
        "contact": {
            "name": "Farmacia 151 Marina Pharmacy",
            "url": "https://151marinapharmacy.com/",
            "email": "farmaciamarinabcn@gmail.com"
        },
        "license": {
            "name": "Uso libre para consulta y compra"
        }
    },
    "servers": [
        {
            "url": "https://151marinapharmacy.com",
            "description": "Producción"
        }
    ],
    "tags": [
        {
            "name": "catalogo",
            "description": "Consultar productos y categorías."
        },
        {
            "name": "carrito",
            "description": "Montar un pedido antes de pagar."
        }
    ],
    "paths": {
        "/wp-json/wc/store/v1/products": {
            "get": {
                "operationId": "listarProductos",
                "tags": [
                    "catalogo"
                ],
                "summary": "Lista los productos del catálogo.",
                "description": "Devuelve productos con precio con IVA, existencias, imágenes, categorías, atributos y código de barras. Admite búsqueda por texto y filtro por categoría o atributo.",
                "parameters": [
                    {
                        "name": "search",
                        "in": "query",
                        "description": "Texto a buscar en nombre y descripción.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "category",
                        "in": "query",
                        "description": "Identificador de categoría.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "description": "Productos por página, de 1 a 100.",
                        "schema": {
                            "type": "integer",
                            "default": 10,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "default": 1
                        }
                    },
                    {
                        "name": "min_price",
                        "in": "query",
                        "description": "Precio mínimo en céntimos.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "max_price",
                        "in": "query",
                        "description": "Precio máximo en céntimos.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "orderby",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "date",
                                "price",
                                "popularity",
                                "title"
                            ]
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Lista de productos.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "type": "object",
                                        "properties": {
                                            "id": {
                                                "type": "integer",
                                                "description": "Identificador del producto."
                                            },
                                            "name": {
                                                "type": "string",
                                                "description": "Nombre del producto, con su formato y volumen."
                                            },
                                            "sku": {
                                                "type": "string",
                                                "description": "Referencia interna."
                                            },
                                            "permalink": {
                                                "type": "string",
                                                "format": "uri",
                                                "description": "Dirección de la ficha."
                                            },
                                            "description": {
                                                "type": "string",
                                                "description": "Ficha completa en HTML: composición, modo de empleo, para quién es y lista de ingredientes."
                                            },
                                            "short_description": {
                                                "type": "string",
                                                "description": "Resumen de una o dos frases."
                                            },
                                            "prices": {
                                                "type": "object",
                                                "description": "Precios en la unidad menor de la moneda: 1350 son 13,50 €.",
                                                "properties": {
                                                    "price": {
                                                        "type": "string",
                                                        "description": "Precio con IVA incluido, en céntimos."
                                                    },
                                                    "regular_price": {
                                                        "type": "string"
                                                    },
                                                    "sale_price": {
                                                        "type": "string"
                                                    },
                                                    "currency_code": {
                                                        "type": "string",
                                                        "example": "EUR"
                                                    },
                                                    "currency_minor_unit": {
                                                        "type": "integer",
                                                        "example": 2
                                                    }
                                                }
                                            },
                                            "is_in_stock": {
                                                "type": "boolean",
                                                "description": "Si hay existencias."
                                            },
                                            "images": {
                                                "type": "array",
                                                "items": {
                                                    "type": "object"
                                                }
                                            },
                                            "categories": {
                                                "type": "array",
                                                "items": {
                                                    "type": "object"
                                                }
                                            },
                                            "attributes": {
                                                "type": "array",
                                                "items": {
                                                    "type": "object"
                                                },
                                                "description": "Tipo de piel y SPF, cuando aplican."
                                            },
                                            "extensions": {
                                                "type": "object",
                                                "properties": {
                                                    "marina151": {
                                                        "type": "object",
                                                        "properties": {
                                                            "gtin": {
                                                                "type": "string",
                                                                "description": "Código de barras EAN-13."
                                                            },
                                                            "marca": {
                                                                "type": "string"
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error. Siempre en JSON, nunca en HTML.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "code": {
                                            "type": "string",
                                            "description": "Código de error legible por máquina."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "Mensaje en español."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/wp-json/wc/store/v1/products/{id}": {
            "get": {
                "operationId": "obtenerProducto",
                "tags": [
                    "catalogo"
                ],
                "summary": "Devuelve una ficha completa.",
                "description": "La descripción incluye composición completa (INCI), modo de empleo, para quién es apto y las advertencias del fabricante.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "La ficha.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "id": {
                                            "type": "integer",
                                            "description": "Identificador del producto."
                                        },
                                        "name": {
                                            "type": "string",
                                            "description": "Nombre del producto, con su formato y volumen."
                                        },
                                        "sku": {
                                            "type": "string",
                                            "description": "Referencia interna."
                                        },
                                        "permalink": {
                                            "type": "string",
                                            "format": "uri",
                                            "description": "Dirección de la ficha."
                                        },
                                        "description": {
                                            "type": "string",
                                            "description": "Ficha completa en HTML: composición, modo de empleo, para quién es y lista de ingredientes."
                                        },
                                        "short_description": {
                                            "type": "string",
                                            "description": "Resumen de una o dos frases."
                                        },
                                        "prices": {
                                            "type": "object",
                                            "description": "Precios en la unidad menor de la moneda: 1350 son 13,50 €.",
                                            "properties": {
                                                "price": {
                                                    "type": "string",
                                                    "description": "Precio con IVA incluido, en céntimos."
                                                },
                                                "regular_price": {
                                                    "type": "string"
                                                },
                                                "sale_price": {
                                                    "type": "string"
                                                },
                                                "currency_code": {
                                                    "type": "string",
                                                    "example": "EUR"
                                                },
                                                "currency_minor_unit": {
                                                    "type": "integer",
                                                    "example": 2
                                                }
                                            }
                                        },
                                        "is_in_stock": {
                                            "type": "boolean",
                                            "description": "Si hay existencias."
                                        },
                                        "images": {
                                            "type": "array",
                                            "items": {
                                                "type": "object"
                                            }
                                        },
                                        "categories": {
                                            "type": "array",
                                            "items": {
                                                "type": "object"
                                            }
                                        },
                                        "attributes": {
                                            "type": "array",
                                            "items": {
                                                "type": "object"
                                            },
                                            "description": "Tipo de piel y SPF, cuando aplican."
                                        },
                                        "extensions": {
                                            "type": "object",
                                            "properties": {
                                                "marina151": {
                                                    "type": "object",
                                                    "properties": {
                                                        "gtin": {
                                                            "type": "string",
                                                            "description": "Código de barras EAN-13."
                                                        },
                                                        "marca": {
                                                            "type": "string"
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Error. Siempre en JSON, nunca en HTML.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "code": {
                                            "type": "string",
                                            "description": "Código de error legible por máquina."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "Mensaje en español."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/wp-json/wc/store/v1/products/categories": {
            "get": {
                "operationId": "listarCategorias",
                "tags": [
                    "catalogo"
                ],
                "summary": "Lista las categorías con su número de productos.",
                "responses": {
                    "200": {
                        "description": "Categorías.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "array",
                                    "items": {
                                        "type": "object"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/wp-json/wc/store/v1/cart": {
            "get": {
                "operationId": "verCarrito",
                "tags": [
                    "carrito"
                ],
                "summary": "Devuelve el carrito con totales, impuestos y envío.",
                "description": "La cabecera Nonce de la respuesta hay que devolverla en las peticiones de escritura. La sesión se mantiene con la cookie que devuelve.",
                "responses": {
                    "200": {
                        "description": "El carrito.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/wp-json/wc/store/v1/cart/add-item": {
            "post": {
                "operationId": "anadirAlCarrito",
                "tags": [
                    "carrito"
                ],
                "summary": "Añade un producto al carrito.",
                "description": "Necesita la cabecera Nonce obtenida de una llamada previa a verCarrito. Si se reintenta con la misma cabecera Idempotency-Key, no se duplica la línea.",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": false,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Clave única del intento. El mismo valor en un reintento devuelve el mismo resultado y no añade otra unidad."
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "id",
                                    "quantity"
                                ],
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Identificador del producto."
                                    },
                                    "quantity": {
                                        "type": "integer",
                                        "minimum": 1
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Añadido.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error. Siempre en JSON, nunca en HTML.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "code": {
                                            "type": "string",
                                            "description": "Código de error legible por máquina."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "Mensaje en español."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Error. Siempre en JSON, nunca en HTML.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "code": {
                                            "type": "string",
                                            "description": "Código de error legible por máquina."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "Mensaje en español."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/wp-json/wc/store/v1/cart/remove-item": {
            "post": {
                "operationId": "quitarDelCarrito",
                "tags": [
                    "carrito"
                ],
                "summary": "Quita una línea del carrito.",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": false,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Clave única del intento. Un reintento con la misma clave no vuelve a quitar otra línea."
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "key"
                                ],
                                "properties": {
                                    "key": {
                                        "type": "string",
                                        "description": "Clave de la línea, la devuelve verCarrito."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Quitado.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Error. Siempre en JSON, nunca en HTML.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "code": {
                                            "type": "string",
                                            "description": "Código de error legible por máquina."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "Mensaje en español."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/feed-productos.xml": {
            "get": {
                "operationId": "catalogoCompleto",
                "tags": [
                    "catalogo"
                ],
                "summary": "Catálogo entero en un fichero, formato Google Shopping.",
                "description": "RSS 2.0 con el espacio de nombres g:. Los 170 productos con precio, disponibilidad, imagen, código de barras y las tres tarifas de envío por código postal. Útil para cargar el catálogo de una vez en lugar de paginar.",
                "responses": {
                    "200": {
                        "description": "El catálogo.",
                        "content": {
                            "application/xml": {
                                "schema": {
                                    "type": "string"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/ask": {
            "post": {
                "operationId": "preguntar",
                "tags": [
                    "catalogo"
                ],
                "summary": "Pregunta en lenguaje natural sobre el catálogo (NLWeb).",
                "description": "Acepta una consulta en español o inglés y devuelve los productos que encajan, con su ficha. Admite respuesta en flujo (SSE) con la cabecera prefer.streaming: true.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "query"
                                ],
                                "properties": {
                                    "query": {
                                        "type": "string",
                                        "description": "La pregunta. Por ejemplo: «protector solar facial SPF 50 para piel sensible por menos de 30 euros»."
                                    },
                                    "streaming": {
                                        "type": "boolean",
                                        "default": false
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Resultados.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Error. Siempre en JSON, nunca en HTML.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "code": {
                                            "type": "string",
                                            "description": "Código de error legible por máquina."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "Mensaje en español."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "status": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "Producto": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Identificador del producto."
                    },
                    "name": {
                        "type": "string",
                        "description": "Nombre del producto, con su formato y volumen."
                    },
                    "sku": {
                        "type": "string",
                        "description": "Referencia interna."
                    },
                    "permalink": {
                        "type": "string",
                        "format": "uri",
                        "description": "Dirección de la ficha."
                    },
                    "description": {
                        "type": "string",
                        "description": "Ficha completa en HTML: composición, modo de empleo, para quién es y lista de ingredientes."
                    },
                    "short_description": {
                        "type": "string",
                        "description": "Resumen de una o dos frases."
                    },
                    "prices": {
                        "type": "object",
                        "description": "Precios en la unidad menor de la moneda: 1350 son 13,50 €.",
                        "properties": {
                            "price": {
                                "type": "string",
                                "description": "Precio con IVA incluido, en céntimos."
                            },
                            "regular_price": {
                                "type": "string"
                            },
                            "sale_price": {
                                "type": "string"
                            },
                            "currency_code": {
                                "type": "string",
                                "example": "EUR"
                            },
                            "currency_minor_unit": {
                                "type": "integer",
                                "example": 2
                            }
                        }
                    },
                    "is_in_stock": {
                        "type": "boolean",
                        "description": "Si hay existencias."
                    },
                    "images": {
                        "type": "array",
                        "items": {
                            "type": "object"
                        }
                    },
                    "categories": {
                        "type": "array",
                        "items": {
                            "type": "object"
                        }
                    },
                    "attributes": {
                        "type": "array",
                        "items": {
                            "type": "object"
                        },
                        "description": "Tipo de piel y SPF, cuando aplican."
                    },
                    "extensions": {
                        "type": "object",
                        "properties": {
                            "marina151": {
                                "type": "object",
                                "properties": {
                                    "gtin": {
                                        "type": "string",
                                        "description": "Código de barras EAN-13."
                                    },
                                    "marca": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "Error": {
                "type": "object",
                "properties": {
                    "code": {
                        "type": "string",
                        "description": "Código de error legible por máquina."
                    },
                    "message": {
                        "type": "string",
                        "description": "Mensaje en español."
                    },
                    "data": {
                        "type": "object",
                        "properties": {
                            "status": {
                                "type": "integer"
                            }
                        }
                    }
                }
            }
        }
    }
}