{
  "openapi": "3.1.1",
  "info": {
    "title": "Meridian public read-only API",
    "version": "1.0.0",
    "description": "Anonymous, read-only access to Meridian's approved public service catalogue. This API does not provide private writes, generated samples, or authentication. The related MCP endpoint uses Streamable HTTP at /mcp; see the human documentation for client setup."
  },
  "servers": [
    { "url": "https://seekmeridian.com", "description": "Meridian public website and API" }
  ],
  "externalDocs": {
    "description": "Human agent documentation and MCP setup",
    "url": "https://seekmeridian.com/docs"
  },
  "security": [],
  "paths": {
    "/api": {
      "get": {
        "operationId": "getPublicApiIndex",
        "summary": "Discover Meridian's public API",
        "description": "Returns stable links for the human documentation, OpenAPI document, read-only catalogue, and Streamable HTTP MCP endpoint.",
        "security": [],
        "responses": {
          "200": {
            "description": "Public API links.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiIndex" } } }
          },
          "405": { "$ref": "#/components/responses/MethodNotAllowed" }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "getPublicApiHealth",
        "summary": "Check this website API process",
        "description": "Reports the health and role of this HTTP service. It does not probe or claim the health of the catalogue or MCP upstreams.",
        "security": [],
        "responses": {
          "200": {
            "description": "This process is handling requests.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HealthResponse" } } }
          },
          "405": { "$ref": "#/components/responses/MethodNotAllowed" }
        }
      }
    },
    "/api/v1/catalogue": {
      "get": {
        "operationId": "getApprovedCatalogue",
        "summary": "Read approved Meridian catalogue information",
        "description": "Proxies the existing approved-only catalogue. `service` is an exact service ID lookup. `question` is an exact approved FAQ question or FAQ ID lookup; it is not general search. Each filter is limited to 200 characters. The upstream response is capped at 1 MiB and the request deadline is five seconds.",
        "security": [],
        "parameters": [
          { "$ref": "#/components/parameters/ServiceFilter" },
          { "$ref": "#/components/parameters/QuestionFilter" }
        ],
        "responses": {
          "200": {
            "description": "Approved catalogue response; pending entries and unapproved commercial terms are excluded by the source catalogue.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CatalogueResponse" } } }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "405": { "$ref": "#/components/responses/MethodNotAllowed" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "502": { "$ref": "#/components/responses/BadGateway" },
          "504": { "$ref": "#/components/responses/GatewayTimeout" }
        }
      }
    },
    "/v1/catalogue": {
      "get": {
        "operationId": "getApprovedCatalogueLegacyAlias",
        "summary": "Read approved catalogue information through the established alias",
        "description": "Compatibility alias for `/api/v1/catalogue`. It accepts the same exact `service` and `question` filters and returns the same approved-only response.",
        "security": [],
        "parameters": [
          { "$ref": "#/components/parameters/ServiceFilter" },
          { "$ref": "#/components/parameters/QuestionFilter" }
        ],
        "responses": {
          "200": {
            "description": "Approved catalogue response.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CatalogueResponse" } } }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "405": { "$ref": "#/components/responses/MethodNotAllowed" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "502": { "$ref": "#/components/responses/BadGateway" },
          "504": { "$ref": "#/components/responses/GatewayTimeout" }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "ServiceFilter": {
        "name": "service",
        "in": "query",
        "required": false,
        "description": "Exact approved `service_id`. Values are trimmed by the catalogue. Duplicate parameters and values longer than 200 characters return 400.",
        "schema": { "type": "string", "maxLength": 200 }
      },
      "QuestionFilter": {
        "name": "question",
        "in": "query",
        "required": false,
        "description": "Exact approved FAQ question or FAQ ID. This does not perform semantic search. Duplicate parameters and values longer than 200 characters return 400.",
        "schema": { "type": "string", "maxLength": 200 }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "A query parameter is unsupported, repeated, malformed, or exceeds its documented limit.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } }
      },
      "MethodNotAllowed": {
        "description": "The route supports GET only. The response includes `Allow: GET`.",
        "headers": { "Allow": { "schema": { "type": "string", "const": "GET" } } },
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } }
      },
      "RateLimited": {
        "description": "The existing catalogue declined the request due to its shared rate limit. `Retry-After` is forwarded when valid.",
        "headers": { "Retry-After": { "schema": { "type": "string" }, "description": "Retry guidance supplied by the existing catalogue." } },
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } }
      },
      "BadGateway": {
        "description": "The catalogue returned an invalid, oversized, or unavailable response.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } }
      },
      "GatewayTimeout": {
        "description": "The catalogue did not respond before the five-second deadline.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiError" } } }
      }
    },
    "schemas": {
      "ApiIndex": {
        "type": "object",
        "required": ["service", "read_only", "docs", "openapi", "catalogue", "health", "mcp"],
        "properties": {
          "service": { "const": "Meridian public read-only catalogue API" },
          "read_only": { "const": true },
          "docs": { "type": "string", "format": "uri" },
          "openapi": { "type": "string", "format": "uri" },
          "catalogue": { "type": "string", "format": "uri" },
          "health": { "type": "string", "format": "uri" },
          "mcp": { "type": "string", "format": "uri" }
        },
        "additionalProperties": false
      },
      "HealthResponse": {
        "type": "object",
        "required": ["ok", "role", "docs"],
        "properties": {
          "ok": { "const": true },
          "role": { "const": "public-read-only-agent-readiness" },
          "docs": { "type": "string", "format": "uri" }
        },
        "additionalProperties": false
      },
      "ApiError": {
        "type": "object",
        "required": ["error", "docs"],
        "properties": {
          "error": {
            "type": "object",
            "required": ["code", "message", "hint"],
            "properties": {
              "code": { "type": "string", "minLength": 1 },
              "message": { "type": "string", "minLength": 1 },
              "hint": { "type": "string", "minLength": 1 }
            },
            "additionalProperties": false
          },
          "docs": { "const": "https://seekmeridian.com/docs" }
        },
        "additionalProperties": false
      },
      "NextStep": {
        "type": "object",
        "required": ["label", "url"],
        "properties": {
          "label": { "type": "string" },
          "url": { "type": "string", "format": "uri", "pattern": "^https://(www\\.)?seekmeridian\\.com/" }
        },
        "additionalProperties": false
      },
      "CatalogueEntry": {
        "type": "object",
        "required": ["service_id", "title", "summary", "audience", "inclusions", "exclusions", "price", "currency", "billing_interval", "effective_from", "approved_at", "approval_status", "source_url", "source_provenance"],
        "properties": {
          "service_id": { "type": "string" },
          "title": { "type": "string" },
          "summary": { "type": "string" },
          "audience": { "type": "array", "items": { "type": "string" } },
          "inclusions": { "type": "array", "items": { "type": "string" } },
          "exclusions": { "type": "array", "items": { "type": "string" } },
          "price": { "type": ["number", "null"], "minimum": 0 },
          "currency": { "type": ["string", "null"] },
          "billing_interval": { "type": ["string", "null"] },
          "effective_from": { "type": "string", "format": "date" },
          "approved_at": { "type": ["string", "null"], "format": "date-time" },
          "approval_status": { "const": "approved" },
          "source_url": { "type": "string", "format": "uri" },
          "source_provenance": { "type": "string" }
        },
        "additionalProperties": false
      },
      "CatalogueFaq": {
        "type": "object",
        "required": ["faq_id", "question", "answer", "approval_status", "approved_at", "source_url", "source_provenance"],
        "properties": {
          "faq_id": { "type": "string" },
          "question": { "type": "string" },
          "answer": { "type": "string" },
          "approval_status": { "const": "approved" },
          "approved_at": { "type": ["string", "null"], "format": "date-time" },
          "source_url": { "type": "string", "format": "uri" },
          "source_provenance": { "type": "string" }
        },
        "additionalProperties": false
      },
      "CatalogueResponse": {
        "type": "object",
        "required": ["catalogue_version", "matches", "faqs", "known", "answer_status", "next_step"],
        "properties": {
          "catalogue_version": { "type": "string" },
          "matches": { "type": "array", "items": { "$ref": "#/components/schemas/CatalogueEntry" } },
          "faqs": { "type": "array", "items": { "$ref": "#/components/schemas/CatalogueFaq" } },
          "related_context": {
            "type": ["object", "null"],
            "properties": {
              "entries": { "type": "array", "items": { "$ref": "#/components/schemas/CatalogueEntry" } },
              "faqs": { "type": "array", "items": { "$ref": "#/components/schemas/CatalogueFaq" } }
            },
            "additionalProperties": false
          },
          "known": { "type": "boolean" },
          "answer_status": { "enum": ["approved_information", "unknown_or_unapproved"] },
          "message": { "type": "string" },
          "next_step": { "$ref": "#/components/schemas/NextStep" }
        },
        "additionalProperties": false
      }
    }
  }
}
