{
  "openapi": "3.1.0",
  "info": {
    "title": "Univers Aquaponie public storefront API",
    "version": "2026-10-08",
    "summary": "Read-only JSON endpoints for the Univers Aquaponie catalog (aquaponics and hydroponics equipment).",
    "description": "Public, unauthenticated, read-only endpoints served by the Shopify storefront of univers-aquaponie.com. Use them to search the catalog and read product, variant, price and availability data. Prices are in EUR, VAT included. Prefix any path with a locale (/en, /de, /nl, /cs, /ru, /it, /pt, /pl, /es, /sv, /da) to get translated titles and descriptions. To create carts and checkouts, use the Universal Commerce Protocol MCP endpoint documented under /api/ucp/mcp; payment always requires explicit buyer approval. Human-readable guide: https://www.univers-aquaponie.com/pages/developers. Agent guide: https://www.univers-aquaponie.com/llms.txt.",
    "contact": {
      "name": "Univers Aquaponie",
      "url": "https://www.univers-aquaponie.com/pages/contact"
    },
    "termsOfService": "https://www.univers-aquaponie.com/policies/terms-of-service"
  },
  "externalDocs": {
    "description": "Developer and agent guide",
    "url": "https://www.univers-aquaponie.com/pages/developers"
  },
  "servers": [
    {
      "url": "https://www.univers-aquaponie.com",
      "description": "Production storefront (French default locale)"
    }
  ],
  "security": [],
  "tags": [
    {
      "name": "Catalog",
      "description": "Products and collections"
    },
    {
      "name": "Search",
      "description": "Predictive search"
    },
    {
      "name": "Agent commerce",
      "description": "Universal Commerce Protocol (UCP) over MCP"
    },
    {
      "name": "Discovery",
      "description": "Machine-readable discovery files"
    }
  ],
  "paths": {
    "/products.json": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "operationId": "listProducts",
        "summary": "List all published products",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 250,
              "default": 30
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of products",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductList"
                }
              }
            }
          }
        }
      }
    },
    "/products/{handle}.json": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "operationId": "getProduct",
        "summary": "Get one product with all its variants and prices",
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "URL handle, identical in every language. Example: aliment-truite-aquaponie"
          }
        ],
        "responses": {
          "200": {
            "description": "The product",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "product": {
                      "$ref": "#/components/schemas/Product"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No product with this handle (empty JSON body). Search with /search/suggest.json to find the right handle."
          }
        }
      }
    },
    "/products/{handle}.js": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "operationId": "getProductAjax",
        "summary": "Get one product in the Ajax API format (prices in cents, live availability per variant)",
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "URL handle, identical in every language. Example: aliment-truite-aquaponie"
          }
        ],
        "responses": {
          "200": {
            "description": "The product",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "404": {
            "description": "No product with this handle."
          }
        }
      }
    },
    "/collections/{handle}/products.json": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "operationId": "listCollectionProducts",
        "summary": "List the products of a collection",
        "description": "Main collections: kits-aquaponie, serres-aquaponie, aquariums-aquaponie, pompes, bulleurs-oxygenation, filtration-bacteries, supports-de-culture, substrats, engrais-complements-mineraux, semences-germination, aliments-pour-bassins, aliments-pour-aquarium, univers-formation, offres-du-moment, all.",
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Collection handle. Example: pompes"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 250,
              "default": 30
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of products (empty list for an unknown collection)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductList"
                }
              }
            }
          }
        }
      }
    },
    "/search/suggest.json": {
      "get": {
        "tags": [
          "Search"
        ],
        "operationId": "searchSuggest",
        "summary": "Predictive search across products, collections, pages and articles",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Search terms, in the language of the locale prefix. Example: pompe"
          },
          {
            "name": "resources[type]",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "product,collection,page,article"
            },
            "description": "Comma separated list among product, collection, page, article, query"
          },
          {
            "name": "resources[limit]",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 10,
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Suggestions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "resources": {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "object",
                          "additionalProperties": {
                            "type": "array",
                            "items": {
                              "type": "object"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Missing or invalid parameter, for example an empty q. Fix the parameter named in description and retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorefrontError"
                }
              }
            }
          }
        }
      }
    },
    "/api/ucp/mcp": {
      "post": {
        "tags": [
          "Agent commerce"
        ],
        "operationId": "ucpMcp",
        "summary": "Universal Commerce Protocol MCP endpoint (JSON-RPC 2.0)",
        "description": "Call tools/list first. Tools include search_catalog, lookup_catalog, get_product, create_cart, update_cart, get_cart, create_checkout, update_checkout, complete_checkout, cancel_checkout and get_order. complete_checkout requires explicit buyer approval. Rate limited per IP: back off on HTTP 429. Discovery document: /.well-known/ucp.",
        "externalDocs": {
          "url": "https://ucp.dev"
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonRpcRequest"
              },
              "example": {
                "jsonrpc": "2.0",
                "id": 1,
                "method": "tools/list"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC result or JSON-RPC error object",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/JsonRpcResult"
                    },
                    {
                      "$ref": "#/components/schemas/JsonRpcError"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry later with exponential backoff."
          }
        }
      }
    },
    "/.well-known/ucp": {
      "get": {
        "tags": [
          "Discovery"
        ],
        "operationId": "getUcpProfile",
        "summary": "UCP merchant profile (versions, services, capabilities, payment handlers)",
        "responses": {
          "200": {
            "description": "UCP profile",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "tags": [
          "Discovery"
        ],
        "operationId": "getLlmsTxt",
        "summary": "Agent guide: when to use this store and how to call it",
        "responses": {
          "200": {
            "description": "Markdown",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/agents.md": {
      "get": {
        "tags": [
          "Discovery"
        ],
        "operationId": "getAgentsMd",
        "summary": "Shopify managed agent instructions",
        "responses": {
          "200": {
            "description": "Markdown",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "StorefrontError": {
        "type": "object",
        "required": [
          "status",
          "message"
        ],
        "properties": {
          "status": {
            "type": "integer",
            "examples": [
              422
            ]
          },
          "message": {
            "type": "string",
            "examples": [
              "Invalid parameter error"
            ]
          },
          "description": {
            "type": "string",
            "description": "Which parameter is wrong and why; use it to fix the request.",
            "examples": [
              "param is missing or the value is empty: q"
            ]
          }
        }
      },
      "ProductList": {
        "type": "object",
        "properties": {
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Product"
            }
          }
        }
      },
      "Product": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "handle": {
            "type": "string"
          },
          "body_html": {
            "type": "string",
            "description": "Description in HTML"
          },
          "vendor": {
            "type": "string"
          },
          "product_type": {
            "type": "string"
          },
          "tags": {
            "type": [
              "string",
              "array"
            ]
          },
          "variants": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Variant"
            }
          },
          "images": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "src": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "options": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "additionalProperties": true
      },
      "Variant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "sku": {
            "type": [
              "string",
              "null"
            ]
          },
          "price": {
            "type": "string",
            "description": "Price in EUR, VAT included, as a decimal string. Example: 114.90"
          },
          "compare_at_price": {
            "type": [
              "string",
              "null"
            ]
          },
          "available": {
            "type": "boolean"
          },
          "grams": {
            "type": "integer"
          }
        },
        "additionalProperties": true
      },
      "JsonRpcRequest": {
        "type": "object",
        "required": [
          "jsonrpc",
          "method"
        ],
        "properties": {
          "jsonrpc": {
            "const": "2.0"
          },
          "id": {
            "type": [
              "integer",
              "string"
            ]
          },
          "method": {
            "type": "string",
            "examples": [
              "tools/list",
              "tools/call"
            ]
          },
          "params": {
            "type": "object"
          }
        }
      },
      "JsonRpcResult": {
        "type": "object",
        "required": [
          "jsonrpc",
          "result"
        ],
        "properties": {
          "jsonrpc": {
            "const": "2.0"
          },
          "id": {},
          "result": {}
        }
      },
      "JsonRpcError": {
        "type": "object",
        "required": [
          "jsonrpc",
          "error"
        ],
        "properties": {
          "jsonrpc": {
            "const": "2.0"
          },
          "id": {},
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "integer",
                "examples": [
                  -32601
                ]
              },
              "message": {
                "type": "string",
                "examples": [
                  "Method not found"
                ]
              },
              "data": {}
            }
          }
        }
      }
    }
  }
}
