{
  "openapi": "3.1.0",
  "info": {
    "title": "AgentReady Public API",
    "version": "1.3.0",
    "description": "Public, best-effort website readiness scans and saved report history. New integrations use versioned paths. AgentReady announces a retiring version at least 180 days ahead and returns Deprecation and Sunset headers during that window. Public scans and reports read public web content and expose no private account data; they currently require no authentication."
  },
  "servers": [{ "url": "https://www.agentready.me" }],
  "tags": [
    { "name": "Scans", "description": "Evidence-backed agent-readiness analysis for public URLs." },
    { "name": "Commerce", "description": "Public availability information for AgentReady checkout." }
  ],
  "paths": {
    "/api/v1/scan": {
      "post": {
        "operationId": "scanPublicUrl",
        "tags": ["Scans"],
        "summary": "Scan a public URL for AI-agent readiness",
        "description": "Normalizes and validates a public HTTP URL, runs the Tier 1 readiness scan, and returns scores, evidence, recommendations, and a Fix Pack v2 execution contract. Enhanced scans require a signed-in user.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/PublicScanRequest" },
              "examples": { "standard": { "value": { "url": "example.com", "includePlaywright": true } } }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Readiness score, phase findings, prioritized recommendations, and Fix Pack.",
            "headers": {
              "RateLimit-Limit": { "description": "Maximum anonymous scans in the active window.", "schema": { "type": "integer" } },
              "RateLimit-Remaining": { "description": "Anonymous scans remaining in the active window.", "schema": { "type": "integer" } },
              "RateLimit-Reset": { "description": "Seconds until the active window resets.", "schema": { "type": "integer" } }
            },
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScanResult" } } }
          },
          "400": {
            "description": "The request is missing a URL or the target is not a valid public HTTP URL.",
            "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/ProblemDetails" } } }
          },
          "401": {
            "description": "The requested enhanced scan requires a signed-in account.",
            "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/ProblemDetails" } } }
          },
          "429": {
            "description": "The anonymous public-scan limit has been reached.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": { "type": "integer", "minimum": 1 }
              },
              "RateLimit-Limit": { "description": "Maximum anonymous scans in the active window.", "schema": { "type": "integer" } },
              "RateLimit-Remaining": { "description": "Anonymous scans remaining in the active window.", "schema": { "type": "integer" } },
              "RateLimit-Reset": { "description": "Seconds until the active window resets.", "schema": { "type": "integer" } }
            },
            "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/ProblemDetails" } } }
          },
          "500": {
            "description": "The scan could not be completed.",
            "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/ProblemDetails" } } }
          }
        }
      }
    },
    "/api/scan": {
      "post": {
        "operationId": "scanPublicUrlCompatibilityAlias",
        "tags": ["Scans"],
        "summary": "Compatibility alias for the v1 public scan",
        "description": "Backward-compatible alias of POST /api/v1/scan. It returns X-API-Version: 1 and a successor-version Link header. New integrations should use the versioned path.",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PublicScanRequest" } } }
        },
        "responses": {
          "200": { "description": "Same typed response as /api/v1/scan.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScanResult" } } } },
          "400": { "description": "Invalid request.", "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/ProblemDetails" } } } },
          "401": { "description": "Enhanced scan authentication required.", "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/ProblemDetails" } } } },
          "429": { "description": "Anonymous scan limit reached.", "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/ProblemDetails" } } } },
          "500": { "description": "Scan failed.", "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/ProblemDetails" } } } }
        }
      }
    },
    "/api/checkout": {
      "get": {
        "operationId": "getCheckoutAvailability",
        "tags": ["Commerce"],
        "summary": "Check paid-plan checkout availability",
        "description": "Returns a non-secret health view of Stripe account, webhook, and paid-plan configuration. It does not create a checkout session.",
        "responses": {
          "200": {
            "description": "Checkout is available.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CheckoutAvailability" } } }
          },
          "503": {
            "description": "Checkout is not fully configured or temporarily unavailable. The response uses the same typed availability shape with checkoutAvailable set to false.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CheckoutAvailability" } } }
          }
        }
      }
    },
    "/api/v1/report": {
      "get": {
        "operationId": "getPublicReport",
        "tags": ["Scans"],
        "summary": "Retrieve the latest or historical public scan report",
        "description": "Returns an explicitly published, unlisted report by opaque id. Set history=true to receive up to 12 snapshots newest first. Links expire after 30 days.",
        "parameters": [
          { "name": "id", "in": "query", "required": true, "description": "Opaque report id returned after a scan with publishReport=true.", "schema": { "type": "string", "minLength": 8, "maxLength": 128 } },
          { "name": "history", "in": "query", "required": false, "description": "Return the complete saved history.", "schema": { "type": "boolean", "default": false } }
        ],
        "responses": {
          "200": { "description": "Latest public report or report history.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PublicReportResponse" } } } },
          "400": { "description": "Invalid or missing opaque report id.", "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/ProblemDetails" } } } },
          "404": { "description": "No active public report exists for this id.", "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/ProblemDetails" } } } },
          "503": { "description": "Public report storage is unavailable.", "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/ProblemDetails" } } } }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "PublicScanRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["url"],
        "properties": {
          "url": { "type": "string", "description": "Public hostname or HTTP(S) URL.", "examples": ["example.com"] },
          "includePlaywright": { "type": "boolean", "default": true, "description": "Run browser-backed checks when available." },
          "enhanced": { "type": "boolean", "default": false, "description": "Run signed-in enhanced agent tasks." },
          "publishReport": { "type": "boolean", "default": false, "description": "Explicitly create an unlisted report link that expires after 30 days." }
        }
      },
      "Finding": {
        "type": "object",
        "required": ["type", "message"],
        "properties": {
          "type": { "type": "string", "enum": ["success", "warning", "error"] },
          "message": { "type": "string" },
          "details": { "type": "string" }
        }
      },
      "Recommendation": {
        "type": "object",
        "required": ["priority", "title", "description", "actionable"],
        "properties": {
          "key": { "type": "string" },
          "priority": { "type": "string", "enum": ["high", "medium", "low"] },
          "title": { "type": "string" },
          "description": { "type": "string" },
          "actionable": { "type": "string" },
          "scoreImpact": { "type": "number" }
        }
      },
      "ScanPhase": {
        "type": "object",
        "required": ["phaseName", "score", "maxScore", "findings", "recommendations"],
        "properties": {
          "phaseName": { "type": "string" },
          "score": { "type": "number" },
          "maxScore": { "type": "number" },
          "findings": { "type": "array", "items": { "$ref": "#/components/schemas/Finding" } },
          "recommendations": { "type": "array", "items": { "$ref": "#/components/schemas/Recommendation" } }
        }
      },
      "FixEvidence": {
        "type": "object",
        "required": ["source", "observedAt", "message"],
        "properties": {
          "source": { "type": "string", "enum": ["live_scan", "repository_scan", "user_input"] },
          "observedAt": { "type": "string", "format": "date-time" },
          "message": { "type": "string" },
          "url": { "type": "string", "format": "uri" },
          "details": { "type": "string" }
        }
      },
      "FixItem": {
        "type": "object",
        "required": ["id", "phase", "severity", "title", "why", "fix", "evidence", "applicability", "humanReviewRequired", "acceptance", "acceptanceAssertions", "liveAssertions"],
        "properties": {
          "id": { "type": "string" },
          "checkId": { "type": "string", "description": "Stable scanner-owned check identifier when available." },
          "phase": { "type": "string" },
          "severity": { "type": "string", "enum": ["critical", "high", "medium", "low"] },
          "title": { "type": "string" },
          "why": { "type": "string" },
          "fix": { "type": "string" },
          "evidence": { "type": "array", "items": { "$ref": "#/components/schemas/FixEvidence" } },
          "applicability": { "type": "string", "enum": ["required", "conditional", "not_applicable"] },
          "dependencies": { "type": "array", "items": { "type": "string" } },
          "implementation": { "type": "object", "additionalProperties": true },
          "humanReviewRequired": { "type": "boolean" },
          "reviewReasons": { "type": "array", "items": { "type": "string" } },
          "acceptance": { "type": "string" },
          "acceptanceAssertions": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "liveAssertions": { "type": "array", "items": { "type": "string" } },
          "scoreImpact": { "type": "number" }
        }
      },
      "FixPack": {
        "type": "object",
        "required": ["version", "scannerVersion", "methodologyVersion", "url", "scannedAt", "score", "maxScore", "targetResolution", "fixes", "verify"],
        "properties": {
          "version": { "type": "integer", "const": 2 },
          "scannerVersion": { "type": "string" },
          "methodologyVersion": { "type": "string", "const": "2026-08-23-v2" },
          "url": { "type": "string", "format": "uri" },
          "scannedAt": { "type": "string", "format": "date-time" },
          "score": { "type": "number" },
          "maxScore": { "type": "number" },
          "targetResolution": { "type": "string", "const": "candidate_until_repository_connected" },
          "fixes": { "type": "array", "items": { "$ref": "#/components/schemas/FixItem" } },
          "verify": { "type": "object", "additionalProperties": true }
        }
      },
      "ScanResult": {
        "type": "object",
        "required": ["url", "score", "maxScore", "phases", "scannedAt"],
        "properties": {
          "url": { "type": "string", "format": "uri" },
          "score": { "type": "number", "minimum": 0, "maximum": 100 },
          "maxScore": { "type": "number", "const": 100 },
          "scannedAt": { "type": "string", "format": "date-time" },
          "executiveSummary": { "type": "string" },
          "topPriorities": { "type": "array", "items": { "type": "string" } },
          "phases": { "type": "array", "items": { "$ref": "#/components/schemas/ScanPhase" } },
          "metadata": {
            "type": "object",
            "properties": {
              "fixPack": { "$ref": "#/components/schemas/FixPack" },
              "readiness": { "$ref": "#/components/schemas/ReadinessPreview" },
              "capabilities": { "type": "object", "additionalProperties": { "$ref": "#/components/schemas/CapabilityResult" } }
            },
            "additionalProperties": true
          }
        }
      },
      "ReadinessCheck": {
        "type": "object",
        "required": ["id", "title", "tier", "surface", "status", "weight", "evidence"],
        "properties": {
          "id": { "type": "string" },
          "title": { "type": "string" },
          "tier": { "type": "string", "enum": ["essential", "recommended", "bonus"] },
          "surface": { "type": "string", "enum": ["web", "api", "auth", "mcp", "commerce", "repository"] },
          "status": { "type": "string", "enum": ["pass", "partial", "fail", "not_applicable", "unobservable"] },
          "weight": { "type": "number" },
          "credit": { "type": "number", "minimum": 0, "maximum": 1 },
          "applicabilityReason": { "type": "string" },
          "evidence": { "type": "array", "items": {} }
        }
      },
      "ReadinessPreview": {
        "type": "object",
        "required": ["model", "methodologyVersion", "score", "coverage", "checks", "legacyScore"],
        "properties": {
          "model": { "type": "string", "const": "applicability-aware-v2" },
          "methodologyVersion": { "type": "string" },
          "score": { "type": "number", "minimum": 0, "maximum": 100 },
          "coverage": { "type": "number", "minimum": 0, "maximum": 100 },
          "checks": { "type": "array", "items": { "$ref": "#/components/schemas/ReadinessCheck" } },
          "legacyScore": { "type": "number", "minimum": 0, "maximum": 100 },
          "note": { "type": "string" }
        },
        "additionalProperties": true
      },
      "PublicReportSnapshot": {
        "type": "object",
        "required": ["id", "url", "score", "maxScore", "scannedAt"],
        "properties": {
          "id": { "type": "string" },
          "url": { "type": "string", "format": "uri" },
          "score": { "type": "number", "minimum": 0, "maximum": 100 },
          "maxScore": { "type": "number" },
          "scannedAt": { "type": "string", "format": "date-time" },
          "result": { "$ref": "#/components/schemas/ScanResult" }
        }
      },
      "PublicReportSnapshotPayload": {
        "allOf": [
          { "$ref": "#/components/schemas/ScanResult" },
          {
            "type": "object",
            "required": ["snapshot", "publicReportUrl"],
            "properties": {
              "id": { "type": "string" },
              "publicReportUrl": { "type": "string", "format": "uri" },
              "snapshot": { "$ref": "#/components/schemas/PublicReportSnapshot" }
            }
          }
        ]
      },
      "PublicReportSummary": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "createdAt": { "type": "string", "format": "date-time" },
          "updatedAt": { "type": "string", "format": "date-time" },
          "expiresAt": { "type": "string", "format": "date-time" }
        }
      },
      "PublicReportHistoryResponse": {
        "type": "object",
        "required": ["url", "latest", "history", "snapshots", "report"],
        "properties": {
          "url": { "type": "string", "format": "uri" },
          "latest": { "$ref": "#/components/schemas/PublicReportSnapshotPayload" },
          "history": { "type": "array", "maxItems": 12, "items": { "$ref": "#/components/schemas/PublicReportSnapshotPayload" } },
          "snapshots": { "type": "array", "maxItems": 12, "items": { "$ref": "#/components/schemas/PublicReportSnapshotPayload" } },
          "report": { "$ref": "#/components/schemas/PublicReportSummary" }
        }
      },
      "PublicReportResponse": {
        "oneOf": [
          { "$ref": "#/components/schemas/PublicReportSnapshotPayload" },
          { "$ref": "#/components/schemas/PublicReportHistoryResponse" }
        ]
      },
      "CapabilityResult": {
        "type": "object",
        "required": ["state", "scored", "evidence"],
        "properties": {
          "state": { "type": "string", "enum": ["observed", "advertised", "suspected", "absent"] },
          "scored": { "type": "boolean" },
          "evidence": { "type": "array", "items": { "type": "string" } }
        }
      },
      "CheckoutPlanAvailability": {
        "type": "object",
        "required": ["available", "amount", "currency", "interval"],
        "properties": {
          "available": { "type": "boolean" },
          "amount": { "type": "integer", "description": "Price in the currency's minor unit." },
          "currency": { "type": "string", "examples": ["usd"] },
          "interval": { "type": ["string", "null"], "examples": ["month"] }
        }
      },
      "CheckoutAvailability": {
        "type": "object",
        "required": ["checkoutAvailable", "mode", "accountReady", "webhookReady", "plans", "checkedAt"],
        "properties": {
          "checkoutAvailable": { "type": "boolean" },
          "mode": { "type": "string", "enum": ["live", "test", "unknown"] },
          "accountReady": { "type": "boolean" },
          "webhookReady": { "type": "boolean" },
          "plans": {
            "type": "object",
            "required": ["pro", "pro_plus", "enterprise"],
            "properties": {
              "pro": { "$ref": "#/components/schemas/CheckoutPlanAvailability" },
              "pro_plus": { "$ref": "#/components/schemas/CheckoutPlanAvailability" },
              "enterprise": { "$ref": "#/components/schemas/CheckoutPlanAvailability" }
            }
          },
          "checkedAt": { "type": "string", "format": "date-time" },
          "error": { "type": "string" }
        }
      },
      "ProblemDetails": {
        "type": "object",
        "description": "RFC 9457 Problem Details with stable AgentReady extensions.",
        "required": ["type", "title", "status", "detail", "code", "error"],
        "properties": {
          "type": { "type": "string", "format": "uri", "description": "Stable machine-readable problem type." },
          "title": { "type": "string" },
          "status": { "type": "integer", "minimum": 400, "maximum": 599 },
          "detail": { "type": "string" },
          "code": { "type": "string", "description": "Stable AgentReady error code." },
          "error": { "type": "string", "description": "Backward-compatible alias of detail." }
        }
      }
    }
  }
}
