{
  "openapi": "3.1.0",
  "info": {
    "title": "Lantern Public API",
    "description": "Unauthenticated public endpoints for the Lantern AI Visibility platform. All other endpoints require OAuth 2.1 authentication via the MCP server at https://agent.lantern.is/agent/mcp.",
    "version": "1",
    "contact": {
      "name": "Lantern",
      "url": "https://lantern.is"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://lantern.is",
      "description": "Production"
    }
  ],
  "paths": {
    "/api/analyze": {
      "post": {
        "operationId": "analyzeUrl",
        "summary": "Analyze a website's AI readiness",
        "description": "Runs a multi-page AI readiness analysis on the given URL and returns a scored report. Results are cached per domain for 24 hours. Unauthenticated; no token required.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["url"],
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "The website URL to analyze (max 2048 characters).",
                    "example": "https://example.com"
                  },
                  "forceRefresh": {
                    "type": "boolean",
                    "description": "Force a fresh analysis even if a cached result exists for today. Requires authentication for paid plans.",
                    "default": false
                  },
                  "source": {
                    "type": "string",
                    "description": "Optional tracking label for the analysis request origin."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Analysis result (may be a cached result from today).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "domain": {
                      "type": "string",
                      "description": "Normalized domain name of the analyzed site."
                    },
                    "cached": {
                      "type": "boolean",
                      "description": "True if the result was served from cache."
                    },
                    "analyzedAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Timestamp when the analysis was completed."
                    },
                    "hasHistoricalData": {
                      "type": "boolean",
                      "description": "True if prior analyses exist for this domain."
                    },
                    "analysis": {
                      "type": "object",
                      "description": "The AI readiness analysis payload."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (missing URL, malformed URL, or URL too long).",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "403": {
            "description": "URL blocked by SSRF protection (private/internal IP ranges).",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "413": {
            "description": "Request body exceeds the 10 KB limit.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "500": {
            "description": "Internal server error.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "getAnalysisById",
        "summary": "Retrieve an analysis report by ID",
        "description": "Returns a previously completed analysis report by its UUID. Unauthenticated; report IDs are UUIDs so enumeration is not practical.",
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The report UUID returned by POST /api/analyze."
          }
        ],
        "responses": {
          "200": {
            "description": "The analysis report.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "reportId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "domain": { "type": "string" },
                    "overallScore": { "type": "number" },
                    "grade": { "type": "string" }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid report ID.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "404": {
            "description": "Report not found.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "500": {
            "description": "Internal server error.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "healthCheck",
        "summary": "Health check",
        "description": "Returns 200 when the service is healthy. The response body is a JSON object; its exact shape depends on which origin serves the request: the legacy origin returns a shallow liveness result (`{ \"ok\": true }`), while the primary origin performs a deep dependency check and returns `{ \"status\", \"checks\", \"version\", \"ts\" }`, responding 503 if a required dependency check fails. Treat any 2xx as healthy and any 503 as unhealthy rather than depending on a fixed field set.",
        "responses": {
          "200": {
            "description": "Service is healthy.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "properties": {
                    "ok": { "type": "boolean", "example": true, "description": "Present on the legacy origin's shallow liveness result." },
                    "status": { "type": "string", "example": "ok", "description": "Present on the primary origin's deep health check." }
                  }
                }
              }
            }
          },
          "503": {
            "description": "One or more required dependency checks failed (deep health check on the primary origin only).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "properties": {
                    "status": { "type": "string", "example": "error" }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message."
          }
        },
        "required": ["error"]
      }
    }
  }
}
