{
  "openapi": "3.1.0",
  "info": {
    "title": "Aloha Fungi Public Agent API",
    "version": "1.0.0",
    "description": "Read-only API for AI agents and integrations. Search the live Aloha Fungi catalog, inspect a product, get goal-based recommendations and search educational content. Prices and availability must always be read live. Shopping actions that require customer confirmation are exposed separately through MCP. Major versions are encoded in the URL. Deprecated operations advertise Deprecation, Sunset and a policy link before removal.",
    "contact": {
      "name": "Aloha Fungi",
      "url": "https://alohafungi.com/developers",
      "email": "aloha@alohafungi.com"
    },
    "license": {
      "name": "Proprietary",
      "identifier": "LicenseRef-Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://alohafungi.com",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "API versioning and deprecation policy",
    "url": "https://alohafungi.com/api-policy.md"
  },
  "x-deprecation-policy": "https://alohafungi.com/api-policy.md",
  "security": [
    {},
    {
      "agentToken": []
    }
  ],
  "tags": [
    {
      "name": "Discovery",
      "description": "API and capability discovery."
    },
    {
      "name": "Catalog",
      "description": "Live product catalog and availability."
    },
    {
      "name": "Recommendations",
      "description": "Deterministic product matching by declared goal."
    },
    {
      "name": "Knowledge",
      "description": "Search Aloha Fungi educational sources."
    }
  ],
  "paths": {
    "/api/v1": {
      "get": {
        "operationId": "discoverApi",
        "summary": "Discover public agent capabilities",
        "description": "Returns stable links to the OpenAPI document, MCP server and every public API resource.",
        "tags": ["Discovery"],
        "responses": {
          "200": {
            "description": "Service discovery document.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DiscoveryResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "security": [
          {},
          {
            "agentToken": []
          }
        ]
      }
    },
    "/api/v1/products": {
      "get": {
        "operationId": "searchProducts",
        "summary": "Search the live product catalog",
        "description": "Returns at most 10 results without listing filters (kategoria/linia/forma/rodzaj/cel/sort) and at most 50 with them. Omit q or pass an empty value to skip phrase matching; to enumerate the whole catalog use listing filters (e.g. one request per kategoria) or /api/search-index. Prices are expressed in PLN and availability is live at response time.",
        "tags": ["Catalog"],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Product name, mushroom species, form or another catalog phrase.",
            "schema": {
              "type": "string",
              "maxLength": 120
            },
            "example": "reishi"
          },
          {
            "name": "kategoria",
            "in": "query",
            "required": false,
            "description": "Listing category filter, same values as /produkty (see llms.txt).",
            "schema": {
              "type": "string",
              "enum": [
                "grzyby",
                "blendy",
                "ziola",
                "zestawy",
                "kawa-kakao-matcha",
                "mystery-box",
                "wiedza"
              ]
            },
            "example": "kawa-kakao-matcha"
          },
          {
            "name": "linia",
            "in": "query",
            "required": false,
            "description": "Product line filter.",
            "schema": {
              "type": "string",
              "enum": ["longevity", "prime"]
            },
            "example": "longevity"
          },
          {
            "name": "forma",
            "in": "query",
            "required": false,
            "description": "Variant form filter.",
            "schema": {
              "type": "string",
              "enum": ["kapsulki", "krople", "proszek"]
            },
            "example": "kapsulki"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Result sort order.",
            "schema": {
              "type": "string",
              "enum": ["cena_asc", "cena_desc", "nazwa"]
            },
            "example": "cena_asc"
          },
          {
            "name": "rodzaj",
            "in": "query",
            "required": false,
            "description": "Species filter, a product handle (e.g. reishi, lions-mane).",
            "schema": {
              "type": "string"
            },
            "example": "reishi"
          },
          {
            "name": "cel",
            "in": "query",
            "required": false,
            "description": "Goal filter (\"po co?\").",
            "schema": {
              "type": "string",
              "enum": ["sen", "skupienie", "energia", "odpornosc", "spokoj", "dlugowiecznosc"]
            },
            "example": "sen"
          }
        ],
        "responses": {
          "200": {
            "description": "Matching products from the live catalog.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/UpstreamUnavailable"
          }
        },
        "security": [
          {},
          {
            "agentToken": ["catalog:read"]
          }
        ]
      }
    },
    "/api/v1/products/{handle}": {
      "get": {
        "operationId": "getProduct",
        "summary": "Get a product and its variants",
        "description": "Returns current variants, SKUs, prices, availability and available educational product content for one canonical handle.",
        "tags": ["Catalog"],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "description": "Canonical product handle returned by searchProducts.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9-]+$"
            },
            "example": "reishi"
          }
        ],
        "responses": {
          "200": {
            "description": "Product details from the live catalog.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductDetailResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/UpstreamUnavailable"
          }
        },
        "security": [
          {},
          {
            "agentToken": ["catalog:read"]
          }
        ]
      }
    },
    "/api/v1/recommendations": {
      "get": {
        "operationId": "recommendProducts",
        "summary": "Match products to a declared goal",
        "description": "Returns a deterministic catalog match for one supported goal. This is product navigation, not medical advice or diagnosis.",
        "tags": ["Recommendations"],
        "parameters": [
          {
            "name": "goal",
            "in": "query",
            "required": true,
            "description": "Customer-declared shopping goal in Polish.",
            "schema": {
              "type": "string",
              "enum": ["sen", "skupienie", "energia", "odpornosc", "spokoj", "dlugowiecznosc"]
            },
            "example": "sen"
          }
        ],
        "responses": {
          "200": {
            "description": "Products mapped to the requested goal.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecommendationResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/UpstreamUnavailable"
          }
        },
        "security": [
          {},
          {
            "agentToken": ["catalog:read"]
          }
        ]
      }
    },
    "/api/v1/knowledge": {
      "get": {
        "operationId": "searchKnowledge",
        "summary": "Search educational Aloha Fungi sources",
        "description": "Searches published blog posts, product education and mushroom guides. Every result includes its source URL.",
        "tags": ["Knowledge"],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Non-empty educational search phrase.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            },
            "example": "beta-glukany"
          }
        ],
        "responses": {
          "200": {
            "description": "Matching educational sources.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/UpstreamUnavailable"
          }
        },
        "security": [
          {},
          {
            "agentToken": ["knowledge:read"]
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "agentToken": {
        "type": "oauth2",
        "description": "Optional. Anonymous requests are accepted and are the default. If a Bearer token is sent it must be valid and carry the scope of the operation, otherwise the request is rejected with 401 or 403. There is no registration and no client secret: POST grant_type=client_credentials with a client_id naming your agent. A token narrows what you may call and makes your agent recognisable in our traffic data, which stores a one-way hash of your client_id and never the string itself; it grants no extra access and no extra quota (rate limits are per IP address either way).",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "https://alohafungi.com/api/oauth/token",
            "scopes": {
              "catalog:read": "Search products, read product cards, get goal-based recommendations.",
              "knowledge:read": "Search educational content and the TCM glossary.",
              "checkout:link": "Compose customer-confirmed ACP carts and storefront order/subscription links; the customer still pays in the storefront."
            }
          }
        }
      }
    },
    "responses": {
      "InvalidRequest": {
        "description": "The request is missing a required value or uses an unsupported value.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "The requested product handle does not exist in the current catalog.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "RateLimited": {
        "description": "The client exceeded the public fixed-window request quota.",
        "headers": {
          "Retry-After": {
            "description": "Seconds until the client should retry.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          "RateLimit-Limit": {
            "description": "Maximum requests in the current window.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          "RateLimit-Remaining": {
            "description": "Requests remaining in the current window.",
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          },
          "RateLimit-Reset": {
            "description": "Seconds until the current window resets.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "UpstreamUnavailable": {
        "description": "The live catalog is temporarily unavailable. The client should retry and must not invent price or availability.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "A Bearer token was sent but is invalid, expired or was issued for another resource. Omit the Authorization header to call anonymously.",
        "headers": {
          "WWW-Authenticate": {
            "description": "Bearer challenge with error=\"invalid_token\" and the resource_metadata URL (RFC 6750, RFC 9728).",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The token is valid but does not carry the scope this operation requires.",
        "headers": {
          "WWW-Authenticate": {
            "description": "Bearer challenge with error=\"insufficient_scope\" and the missing scope.",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    },
    "schemas": {
      "DiscoveryResponse": {
        "type": "object",
        "required": ["data"],
        "properties": {
          "data": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "ProductSummary": {
        "type": "object",
        "additionalProperties": false,
        "required": ["title", "handle", "url", "minPrice", "availability"],
        "properties": {
          "title": {
            "type": "string"
          },
          "handle": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "minPrice": {
            "type": ["number", "null"],
            "minimum": 0,
            "description": "Lowest current price in PLN. When forma/linia are set, this is the price of the matching variant, not the whole product."
          },
          "availability": {
            "type": "string",
            "description": "Current catalog availability state. When forma/linia are set, this describes only the matching variant."
          }
        }
      },
      "ProductListResponse": {
        "type": "object",
        "required": ["data"],
        "properties": {
          "data": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "$ref": "#/components/schemas/ProductSummary"
            }
          }
        }
      },
      "Variant": {
        "type": "object",
        "description": "Live product variant with its current price and stock state.",
        "additionalProperties": false,
        "required": ["variantId", "title", "forma", "linia", "sku", "price", "available"],
        "properties": {
          "variantId": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "forma": {
            "type": ["string", "null"]
          },
          "linia": {
            "type": ["string", "null"],
            "enum": ["PRIME", "LONGEVITY", null]
          },
          "sku": {
            "type": ["string", "null"]
          },
          "price": {
            "type": ["number", "null"],
            "minimum": 0,
            "description": "Current price in PLN."
          },
          "available": {
            "type": "boolean"
          }
        }
      },
      "ProductDetail": {
        "type": "object",
        "additionalProperties": false,
        "required": ["title", "handle", "url", "variants"],
        "properties": {
          "title": {
            "type": "string"
          },
          "handle": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "variants": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Variant"
            }
          },
          "content": {
            "type": "object",
            "additionalProperties": true,
            "description": "Optional educational content available for this product."
          }
        }
      },
      "ProductDetailResponse": {
        "type": "object",
        "required": ["data"],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ProductDetail"
          }
        }
      },
      "Recommendation": {
        "type": "object",
        "additionalProperties": false,
        "required": ["title", "handle", "url", "minPrice", "availability", "goals"],
        "properties": {
          "title": {
            "type": "string"
          },
          "handle": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "minPrice": {
            "type": ["number", "null"],
            "minimum": 0,
            "description": "Lowest current price in PLN."
          },
          "availability": {
            "type": "string"
          },
          "goals": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "RecommendationResponse": {
        "type": "object",
        "required": ["data"],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Recommendation"
            }
          }
        }
      },
      "KnowledgeItem": {
        "type": "object",
        "additionalProperties": true,
        "required": ["title", "description", "url", "source"],
        "properties": {
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "source": {
            "type": "string",
            "enum": ["blog", "pdp", "guide"]
          }
        }
      },
      "KnowledgeResponse": {
        "type": "object",
        "required": ["data"],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KnowledgeItem"
            }
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": ["error"],
        "properties": {
          "error": {
            "type": "object",
            "additionalProperties": false,
            "required": ["code", "message", "resolution", "docs"],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "INVALID_REQUEST",
                  "NOT_FOUND",
                  "METHOD_NOT_ALLOWED",
                  "RATE_LIMITED",
                  "UPSTREAM_UNAVAILABLE",
                  "INTERNAL_ERROR"
                ]
              },
              "message": {
                "type": "string"
              },
              "resolution": {
                "type": "string"
              },
              "docs": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}
