{
  "openapi": "3.1.0",
  "info": {
    "title": "Agentability Audit API",
    "version": "v0",
    "summary": "Score how usable any public web page is for AI agents.",
    "description": "Scores any public web page on the 8-principle Agent Factors Engineering (AFE) rubric (0-100). No authentication is required for any read surface; the email field on an audit is used only to enforce a 3-audit lifetime limit per address. On error, every response returns a structured object stating what failed and the next action.",
    "contact": { "name": "The Agentability Project", "email": "hello@agentability.io", "url": "https://agentability.io" },
    "license": { "name": "The Agentability Project — not a registered company" }
  },
  "servers": [ { "url": "https://agentability.io", "description": "Production" } ],
  "paths": {
    "/api/public-audit": {
      "post": {
        "operationId": "runAudit",
        "summary": "Run an agentability audit on a URL",
        "description": "Fetches and renders the target page, runs 12 deterministic and 17 LLM checks, stores the result, and returns the composite score plus a link to the full report. Takes about 10 seconds.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/AuditRequest" },
              "example": { "url": "https://stripe.com/pricing", "email": "you@example.com" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Audit complete.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuditResult" } } }
          },
          "400": {
            "description": "Missing or invalid field. The error states which field and what to send.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "example": { "success": false, "error": "url is required" } } }
          },
          "429": {
            "description": "Rate limit reached (3 audits per email, lifetime). Contact hello@agentability.io for more.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" }, "example": { "success": false, "error": "3 free audits used" } } }
          }
        }
      }
    },
    "/api/agentable-report": {
      "get": {
        "operationId": "getReport",
        "summary": "Fetch a full audit report by id",
        "description": "Returns the composite score, per-principle scores, every check with its result and fix, and the prioritised findings list for a stored audit.",
        "parameters": [
          { "name": "id", "in": "query", "required": true, "description": "The audit_id returned by runAudit.", "schema": { "type": "string", "format": "uuid" } }
        ],
        "responses": {
          "200": {
            "description": "Full report payload.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Report" } } }
          },
          "404": {
            "description": "No audit exists for that id.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AuditRequest": {
        "type": "object",
        "required": ["url", "email"],
        "properties": {
          "url": { "type": "string", "format": "uri", "description": "Full public URL including scheme, e.g. https://stripe.com/pricing" },
          "email": { "type": "string", "format": "email", "description": "Used only to enforce the 3-audit lifetime limit per address" },
          "demo_token": { "type": "string", "description": "Optional token to bypass the rate limit" }
        }
      },
      "AuditResult": {
        "type": "object",
        "properties": {
          "success": { "type": "boolean" },
          "audit_id": { "type": "string", "format": "uuid" },
          "score": { "type": "number", "minimum": 0, "maximum": 100 },
          "principle_scores": { "type": "object", "description": "Score (0-1) for each of the 8 AFE principles", "additionalProperties": { "type": "number" } },
          "report_url": { "type": "string", "format": "uri" }
        }
      },
      "Report": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "url": { "type": "string" },
          "finalUrl": { "type": "string" },
          "compositeScore": { "type": "number" },
          "verdict": { "type": "string" },
          "rubricVersion": { "type": "string" },
          "principleScores": { "type": "object", "additionalProperties": { "type": "number" } },
          "principles": { "type": "array", "items": { "type": "object" } },
          "findings": { "type": "array", "items": { "$ref": "#/components/schemas/Finding" } }
        }
      },
      "Finding": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "principle": { "type": "string" },
          "severity": { "type": "string", "enum": ["high", "medium", "opportunity", "low"] },
          "what": { "type": "string" },
          "fix": { "type": "string" }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "success": { "type": "boolean" },
          "error": { "type": "string", "description": "Human- and machine-readable reason that states what failed and the next action to take" }
        }
      }
    }
  }
}
