{
  "openapi": "3.1.0",
  "info": {
    "title": "Anzena Public API",
    "version": "1.0.0",
    "summary": "Read-only catalogue, NLWeb-style ask, MCP tools, shipping quotes and soft leads for humans and AI agents.",
    "description": "Public JSON API for Anzena. Prefer this contract over scraping HTML. Discovery: https://www.anzena.fr/agents.json , https://www.anzena.fr/.well-known/mcp.json , https://www.anzena.fr/fr/agents/ . Ask: GET|POST /ask . MCP: GET /mcp (manifest) + POST /mcp (JSON-RPC).",
    "contact": {
      "name": "Anzena",
      "email": "contact@anzena.fr",
      "url": "https://www.anzena.fr/fr/"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://api.anzena.fr/api/v1",
      "description": "Production"
    },
    {
      "url": "https://api.anzena.nc-factory.com/api/v1",
      "description": "Staging"
    }
  ],
  "tags": [
    { "name": "Catalog", "description": "Universes, collections, products, colors" },
    { "name": "Search", "description": "Filtered product search for agents and clients" },
    { "name": "Ask", "description": "NLWeb-style natural language ask (retrieval-grounded)" },
    { "name": "MCP", "description": "Model Context Protocol JSON-RPC tools (read-only)" },
    { "name": "Checkout", "description": "Shipping quotes (no payment)" },
    { "name": "Leads", "description": "Contact / Factory / newsletter soft leads" }
  ],
  "paths": {
    "/universes": {
      "get": {
        "tags": ["Catalog"],
        "summary": "List published universes",
        "operationId": "listUniverses",
        "parameters": [{ "$ref": "#/components/parameters/LocaleQuery" }],
        "responses": {
          "200": {
            "description": "Universe list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["data"],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/Universe" }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/universes/{slug}": {
      "get": {
        "tags": ["Catalog"],
        "summary": "Universe detail with collections",
        "operationId": "getUniverse",
        "parameters": [
          { "$ref": "#/components/parameters/SlugPath" },
          { "$ref": "#/components/parameters/LocaleQuery" }
        ],
        "responses": {
          "200": { "description": "Universe" },
          "404": { "description": "Not found" }
        }
      }
    },
    "/collections": {
      "get": {
        "tags": ["Catalog"],
        "summary": "List published collections",
        "operationId": "listCollections",
        "parameters": [{ "$ref": "#/components/parameters/LocaleQuery" }],
        "responses": {
          "200": { "description": "Collection list" }
        }
      }
    },
    "/collections/{slug}": {
      "get": {
        "tags": ["Catalog"],
        "summary": "Collection detail with products",
        "operationId": "getCollection",
        "parameters": [
          { "$ref": "#/components/parameters/SlugPath" },
          { "$ref": "#/components/parameters/LocaleQuery" }
        ],
        "responses": {
          "200": { "description": "Collection" },
          "404": { "description": "Not found" }
        }
      }
    },
    "/products": {
      "get": {
        "tags": ["Catalog"],
        "summary": "List published products",
        "operationId": "listProducts",
        "parameters": [{ "$ref": "#/components/parameters/LocaleQuery" }],
        "responses": {
          "200": {
            "description": "Product list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["data"],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/ProductSummary" }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/products/{slug}": {
      "get": {
        "tags": ["Catalog"],
        "summary": "Product detail by locale slug",
        "operationId": "getProduct",
        "parameters": [
          { "$ref": "#/components/parameters/SlugPath" },
          { "$ref": "#/components/parameters/LocaleQuery" }
        ],
        "responses": {
          "200": {
            "description": "Product detail",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["data"],
                  "properties": {
                    "data": { "$ref": "#/components/schemas/ProductDetail" }
                  }
                }
              }
            }
          },
          "404": { "description": "Not found" }
        }
      }
    },
    "/search": {
      "get": {
        "tags": ["Search"],
        "summary": "Search published products",
        "description": "Full-text-ish match on handle, format_key, type, grading_type and localized name/slug/summary. Optional filters: universe handle, collection handle, format_key, type.",
        "operationId": "searchProducts",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Search query (optional if other filters are set)"
          },
          { "$ref": "#/components/parameters/LocaleQuery" },
          {
            "name": "universe",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Universe handle (e.g. tcg)"
          },
          {
            "name": "collection",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Collection handle (e.g. pokemon)"
          },
          {
            "name": "format_key",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Product format_key (psa, pca, ccc, instax-mini, …). Alias: format"
          },
          {
            "name": "type",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Product type (bumper, accessory, …)"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 20 }
          }
        ],
        "responses": {
          "200": {
            "description": "Search results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["data", "meta"],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/ProductSummary" }
                    },
                    "meta": { "$ref": "#/components/schemas/SearchMeta" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/ask": {
      "get": {
        "tags": ["Ask"],
        "summary": "Natural-language ask (query string)",
        "operationId": "askGet",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "schema": { "type": "string", "maxLength": 500 }
          },
          {
            "name": "mode",
            "in": "query",
            "schema": { "type": "string", "enum": ["list", "summarize", "generate"], "default": "list" }
          },
          { "$ref": "#/components/parameters/LocaleQuery" }
        ],
        "responses": {
          "200": { "description": "Grounded answer + Schema.org ItemList" },
          "401": { "description": "API key required" },
          "422": { "description": "Validation error" },
          "429": { "description": "Rate limited" }
        }
      },
      "post": {
        "tags": ["Ask"],
        "summary": "Natural-language ask (JSON body)",
        "operationId": "askPost",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["query"],
                "properties": {
                  "query": { "type": "string" },
                  "mode": { "type": "string", "enum": ["list", "summarize", "generate"] },
                  "locale": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Grounded answer + Schema.org ItemList" },
          "401": { "description": "API key required" },
          "429": { "description": "Rate limited" }
        }
      }
    },
    "/mcp": {
      "get": {
        "tags": ["MCP"],
        "summary": "MCP server manifest + tool list",
        "operationId": "mcpManifest",
        "responses": {
          "200": { "description": "Manifest" },
          "401": { "description": "API key required" }
        }
      },
      "post": {
        "tags": ["MCP"],
        "summary": "MCP JSON-RPC (tools/list, tools/call, initialize) or shorthand {tool, arguments}",
        "operationId": "mcpRpc",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "required": ["method"],
                    "properties": {
                      "jsonrpc": { "type": "string", "enum": ["2.0"] },
                      "id": {},
                      "method": {
                        "type": "string",
                        "enum": ["initialize", "ping", "tools/list", "tools/call", "list_tools", "call_tool"]
                      },
                      "params": { "type": "object" }
                    }
                  },
                  {
                    "type": "object",
                    "required": ["tool"],
                    "properties": {
                      "tool": {
                        "type": "string",
                        "enum": ["ask", "search_products", "get_product", "list_guides", "grader_compat"]
                      },
                      "arguments": { "type": "object" }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": { "description": "JSON-RPC result or shorthand data" },
          "400": { "description": "JSON-RPC error" },
          "401": { "description": "API key required" },
          "429": { "description": "Rate limited" }
        }
      }
    },
    "/bumper-colors": {
      "get": {
        "tags": ["Catalog"],
        "summary": "Active bumper color palette",
        "operationId": "listBumperColors",
        "responses": {
          "200": { "description": "Color list" }
        }
      }
    },
    "/checkout/shipping-quotes": {
      "post": {
        "tags": ["Checkout"],
        "summary": "Quote shipping options for a cart",
        "operationId": "shippingQuotes",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ShippingQuotesRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Quoted options",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["data"],
                  "properties": {
                    "data": { "$ref": "#/components/schemas/ShippingQuotesResponse" }
                  }
                }
              }
            }
          },
          "422": { "description": "Validation error" },
          "429": { "description": "Rate limited" }
        }
      }
    },
    "/leads": {
      "post": {
        "tags": ["Leads"],
        "summary": "Submit a soft lead",
        "description": "Honeypot field `website` must be empty. Throttled.",
        "operationId": "createLead",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/LeadRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Idempotent / already recorded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": { "$ref": "#/components/schemas/LeadResponse" }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": { "$ref": "#/components/schemas/LeadResponse" }
                  }
                }
              }
            }
          },
          "422": { "description": "Validation error" },
          "429": { "description": "Rate limited" }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "LocaleQuery": {
        "name": "locale",
        "in": "query",
        "schema": {
          "type": "string",
          "enum": ["fr", "en", "it", "es", "de", "nl", "pt", "pl"],
          "default": "fr"
        }
      },
      "SlugPath": {
        "name": "slug",
        "in": "path",
        "required": true,
        "schema": { "type": "string" }
      }
    },
    "schemas": {
      "Universe": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "handle": { "type": "string" },
          "name": { "type": ["string", "null"] },
          "slug": { "type": ["string", "null"] },
          "summary": { "type": ["string", "null"] }
        }
      },
      "ProductSummary": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "handle": { "type": "string" },
          "type": { "type": "string" },
          "grading_type": { "type": ["string", "null"] },
          "format_key": { "type": ["string", "null"] },
          "name": { "type": ["string", "null"] },
          "slug": { "type": ["string", "null"] },
          "summary": { "type": ["string", "null"] },
          "price_from_cents": { "type": ["integer", "null"] },
          "image_url": { "type": ["string", "null"] },
          "variants": { "type": "array", "items": { "type": "object" } }
        }
      },
      "ProductDetail": {
        "allOf": [
          { "$ref": "#/components/schemas/ProductSummary" },
          {
            "type": "object",
            "properties": {
              "description": { "type": ["string", "null"] },
              "benefits": {},
              "faq": {},
              "compatibilities": {},
              "dimensions": {},
              "materials": {},
              "bumper_assets": { "type": "array", "items": { "type": "object" } }
            }
          }
        ]
      },
      "SearchMeta": {
        "type": "object",
        "properties": {
          "q": { "type": ["string", "null"] },
          "universe": { "type": ["string", "null"] },
          "collection": { "type": ["string", "null"] },
          "format_key": { "type": ["string", "null"] },
          "type": { "type": ["string", "null"] },
          "limit": { "type": "integer" },
          "count": { "type": "integer" }
        }
      },
      "ShippingQuotesRequest": {
        "type": "object",
        "required": ["shipping_address", "items"],
        "properties": {
          "shipping_address": {
            "type": "object",
            "required": ["country_code", "postal_code"],
            "properties": {
              "country_code": { "type": "string", "minLength": 2, "maxLength": 2 },
              "postal_code": { "type": "string" },
              "city": { "type": "string" }
            }
          },
          "items": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "required": ["product_handle", "quantity"],
              "properties": {
                "product_handle": { "type": "string" },
                "product_id": { "type": "integer" },
                "variant_id": { "type": "integer" },
                "quantity": { "type": "integer", "minimum": 1 },
                "unit_price_cents": { "type": "integer" },
                "title": { "type": "string" },
                "color_key": { "type": "string" },
                "back_type": { "type": "string" }
              }
            }
          }
        }
      },
      "ShippingQuotesResponse": {
        "type": "object",
        "properties": {
          "weight_kg": { "type": "number" },
          "free_shipping": { "type": "boolean" },
          "free_shipping_all": { "type": "boolean" },
          "metropolitan_france": { "type": "boolean" },
          "free_shipping_option_key": { "type": "string" },
          "free_shipping_credit_cents": { "type": "integer" },
          "options": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": { "type": "string" },
                "carrier": { "type": "string" },
                "mode": { "type": "string" },
                "name": { "type": "string" },
                "cost_cents": { "type": "integer" },
                "price_cents": { "type": "integer" },
                "list_price_cents": { "type": "integer" },
                "discount_percent": { "type": "integer" },
                "is_free": { "type": "boolean" },
                "speed": { "type": "string", "enum": ["standard", "fast"] },
                "eta_min_days": { "type": "integer" },
                "eta_max_days": { "type": "integer" },
                "currency": { "type": "string" }
              }
            }
          }
        }
      },
      "LeadRequest": {
        "type": "object",
        "required": ["type", "email"],
        "properties": {
          "type": {
            "type": "string",
            "enum": ["contact", "factory", "pro", "newsletter", "event", "abandon_cart"]
          },
          "email": { "type": "string", "format": "email" },
          "first_name": { "type": "string" },
          "last_name": { "type": "string" },
          "phone": { "type": "string" },
          "company": { "type": "string" },
          "locale": { "type": "string" },
          "project_type": { "type": "string" },
          "quantity": { "type": "integer" },
          "message": { "type": "string" },
          "source": { "type": "string" },
          "meta": { "type": "object" },
          "website": {
            "type": "string",
            "maxLength": 0,
            "description": "Honeypot — must be empty"
          },
          "hp_ts": { "type": "integer" }
        }
      },
      "LeadResponse": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "status": {
            "type": "string",
            "enum": ["created", "already_subscribed", "already_recorded"]
          }
        }
      }
    }
  }
}
