{
  "openapi": "3.0.3",
  "info": {
    "title": "AgentLayers API",
    "description": "The AgentLayers API enables you to programmatically scan websites for agent-readiness, manage AI agents, and access trust scores. Authenticate via session cookie (NextAuth) or include credentials in requests.",
    "version": "1.0.0",
    "contact": {
      "name": "AgentLayers Support",
      "url": "https://agent-layers.com/contact"
    }
  },
  "servers": [
    {
      "url": "/api",
      "description": "Current server"
    }
  ],
  "paths": {
    "/scan": {
      "post": {
        "summary": "Scan a website",
        "description": "Crawl a URL and evaluate its agent-readiness across 4 dimensions: Structured Data, LLM Readability, Technical Accessibility, and Agentic SEO. Returns detailed scores, recommendations, and optional AI analysis.",
        "tags": ["Scanning"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["url"],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "example": "https://example.com",
                    "description": "The URL to scan"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Scan completed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScanResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid URL provided"
          },
          "500": {
            "description": "Scan failed"
          }
        }
      }
    },
    "/agents": {
      "get": {
        "summary": "List agents",
        "description": "Retrieve a list of AI agents from the directory. Supports filtering by category, search term, and certification status.",
        "tags": ["Agents"],
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Filter by agent category (e.g., SALES, CONTENT, SUPPORT)"
          },
          {
            "name": "search",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Search agents by name or description"
          },
          {
            "name": "certified",
            "in": "query",
            "schema": { "type": "string", "enum": ["true", "false"] },
            "description": "Filter by certification status"
          }
        ],
        "responses": {
          "200": {
            "description": "List of agents",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": { "$ref": "#/components/schemas/Agent" }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Submit an agent",
        "description": "Register a new AI agent in the directory. The agent will receive a computed Trust Score based on the provided transparency, compliance, and performance metrics.",
        "tags": ["Agents"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Agent created successfully",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Agent" }
              }
            }
          },
          "400": {
            "description": "Validation error"
          }
        }
      }
    },
    "/badge/{slug}": {
      "get": {
        "summary": "Get agent badge",
        "description": "Returns an SVG badge image displaying the agent's Trust Score. Can be embedded in external websites.",
        "tags": ["Badges"],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "description": "The agent's URL slug"
          }
        ],
        "responses": {
          "200": {
            "description": "SVG badge image",
            "content": {
              "image/svg+xml": {
                "schema": { "type": "string" }
              }
            }
          },
          "404": {
            "description": "Agent not found"
          }
        }
      }
    },
    "/og": {
      "get": {
        "summary": "Generate OG image",
        "description": "Generates a 1200×630 Open Graph image for sharing scan results on social media.",
        "tags": ["Utilities"],
        "parameters": [
          {
            "name": "score",
            "in": "query",
            "required": true,
            "schema": { "type": "integer" },
            "description": "The overall score to display"
          },
          {
            "name": "url",
            "in": "query",
            "required": true,
            "schema": { "type": "string" },
            "description": "The scanned URL"
          }
        ],
        "responses": {
          "200": {
            "description": "PNG image",
            "content": {
              "image/png": {}
            }
          }
        }
      }
    },
    "/stripe/checkout": {
      "post": {
        "summary": "Create checkout session",
        "description": "Creates a Stripe Checkout session for upgrading to the Pro plan. Requires authentication.",
        "tags": ["Billing"],
        "security": [{ "session": [] }],
        "responses": {
          "200": {
            "description": "Checkout session URL",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string",
                      "format": "uri",
                      "description": "Stripe checkout URL"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required"
          }
        }
      }
    },
    "/mcp/scan": {
      "post": {
        "summary": "Scan an MCP server configuration",
        "description": "Analyze an MCP server configuration for security risks across 5 dimensions: Endpoint Security, Permission Scope, Data Exfiltration, Auth Strength, and Config Transparency. Supports URL, config JSON, or GitHub repository as input sources.",
        "tags": ["MCP Scanner"],
        "security": [{ "session": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["source"],
                "properties": {
                  "source": {
                    "type": "string",
                    "enum": ["URL", "CONFIG_FILE", "GITHUB"],
                    "description": "The source type for the MCP configuration"
                  },
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "MCP server URL (required when source=URL)"
                  },
                  "config": {
                    "type": "object",
                    "description": "Raw MCP config JSON (required when source=CONFIG_FILE)"
                  },
                  "owner": {
                    "type": "string",
                    "description": "GitHub repo owner (required when source=GITHUB)"
                  },
                  "repo": {
                    "type": "string",
                    "description": "GitHub repo name (required when source=GITHUB)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "MCP scan completed successfully",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/McpScanResult" }
              }
            }
          },
          "400": { "description": "Invalid input" },
          "401": { "description": "Authentication required" },
          "403": { "description": "Permission denied or quota exceeded" }
        }
      }
    },
    "/mcp/scans": {
      "get": {
        "summary": "List MCP scan history",
        "description": "Retrieve the authenticated user's MCP scan history, ordered by most recent.",
        "tags": ["MCP Scanner"],
        "security": [{ "session": [] }],
        "responses": {
          "200": {
            "description": "List of MCP scans",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "scans": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/McpScanResult" }
                    }
                  }
                }
              }
            }
          },
          "401": { "description": "Authentication required" }
        }
      }
    },
    "/mcp/scans/{id}": {
      "get": {
        "summary": "Get MCP scan details",
        "description": "Retrieve details of a specific MCP scan by ID.",
        "tags": ["MCP Scanner"],
        "security": [{ "session": [] }],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "description": "The MCP scan ID"
          }
        ],
        "responses": {
          "200": {
            "description": "MCP scan details",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/McpScanResult" }
              }
            }
          },
          "401": { "description": "Authentication required" },
          "404": { "description": "Scan not found" }
        }
      }
    },
    "/a2a/scan": {
      "post": {
        "summary": "Scan an A2A Agent Card",
        "description": "Analyze an A2A protocol implementation for security risks across 5 dimensions: Auth Protocol, Message Signing, Delegation Depth, Scope Containment, and Identity Verification. Supports Agent Card URL, JSON config, or GitHub repository.",
        "tags": ["A2A Scanner"],
        "security": [{ "session": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["source"],
                "properties": {
                  "source": {
                    "type": "string",
                    "enum": ["AGENT_CARD_URL", "CONFIG_FILE", "GITHUB"],
                    "description": "The source type for the A2A configuration"
                  },
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Agent Card URL (required when source=AGENT_CARD_URL)"
                  },
                  "config": {
                    "type": "object",
                    "description": "Raw Agent Card JSON (required when source=CONFIG_FILE)"
                  },
                  "owner": {
                    "type": "string",
                    "description": "GitHub repo owner (required when source=GITHUB)"
                  },
                  "repo": {
                    "type": "string",
                    "description": "GitHub repo name (required when source=GITHUB)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A2A scan completed successfully",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/A2aScanResult" }
              }
            }
          },
          "400": { "description": "Invalid input" },
          "401": { "description": "Authentication required" },
          "403": { "description": "Permission denied or quota exceeded" }
        }
      }
    },
    "/a2a/scans": {
      "get": {
        "summary": "List A2A scan history",
        "description": "Retrieve the authenticated user's A2A scan history, ordered by most recent.",
        "tags": ["A2A Scanner"],
        "security": [{ "session": [] }],
        "responses": {
          "200": {
            "description": "List of A2A scans",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "scans": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/A2aScanResult" }
                    }
                  }
                }
              }
            }
          },
          "401": { "description": "Authentication required" }
        }
      }
    },
    "/a2a/scans/{id}": {
      "get": {
        "summary": "Get A2A scan details",
        "description": "Retrieve details of a specific A2A scan by ID.",
        "tags": ["A2A Scanner"],
        "security": [{ "session": [] }],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "description": "The A2A scan ID"
          }
        ],
        "responses": {
          "200": {
            "description": "A2A scan details",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/A2aScanResult" }
              }
            }
          },
          "401": { "description": "Authentication required" },
          "404": { "description": "Scan not found" }
        }
      }
    },
    "/skills/scan": {
      "post": {
        "summary": "Scan an AI skill",
        "description": "Analyze an AI skill implementation for security risks across 6 dimensions: Permissions, Injection Risk, Code Transparency, Scope Creep, Supply Chain, and Community Trust. Supports GitHub repository, ClawHub registry, or direct file upload as input sources.\n\nNote: `MANIFEST_URL` is reserved for future use and currently returns 400.",
        "tags": ["Skill Scanner"],
        "security": [{ "session": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["source"],
                "properties": {
                  "source": {
                    "type": "string",
                    "enum": ["GITHUB", "CLAWHUB", "FILE_UPLOAD", "MANIFEST_URL"],
                    "description": "The source type for the skill. `GITHUB` — analyze a public or linked GitHub repo. `CLAWHUB` — fetch from the ClawHub skill registry via URL. `FILE_UPLOAD` — submit raw skill files inline. `MANIFEST_URL` — reserved, not yet supported."
                  },
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "GitHub repo URL (when source=GITHUB and owner/repo are omitted) or ClawHub skill URL (when source=CLAWHUB)"
                  },
                  "owner": {
                    "type": "string",
                    "description": "GitHub repo owner (required when source=GITHUB, alternative to url)"
                  },
                  "repo": {
                    "type": "string",
                    "description": "GitHub repo name (required when source=GITHUB, alternative to url)"
                  },
                  "files": {
                    "type": "array",
                    "description": "Skill files to analyze inline (required when source=FILE_UPLOAD)",
                    "items": {
                      "type": "object",
                      "required": ["name", "content"],
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "File name (e.g. skill.py, manifest.json)"
                        },
                        "content": {
                          "type": "string",
                          "description": "Full file content as a string"
                        }
                      }
                    }
                  }
                }
              },
              "examples": {
                "github-url": {
                  "summary": "GitHub — via URL",
                  "value": { "source": "GITHUB", "url": "https://github.com/acme/my-skill" }
                },
                "github-owner-repo": {
                  "summary": "GitHub — via owner/repo",
                  "value": { "source": "GITHUB", "owner": "acme", "repo": "my-skill" }
                },
                "clawhub": {
                  "summary": "ClawHub registry",
                  "value": { "source": "CLAWHUB", "url": "https://clawhub.ai/skills/acme/my-skill" }
                },
                "file-upload": {
                  "summary": "File upload",
                  "value": {
                    "source": "FILE_UPLOAD",
                    "files": [
                      { "name": "skill.py", "content": "def run(input): ..." },
                      { "name": "manifest.json", "content": "{\"name\": \"my-skill\", \"permissions\": []}" }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Skill scan completed successfully",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SkillScanResult" }
              }
            }
          },
          "400": { "description": "Invalid input or unsupported source type" },
          "401": { "description": "Authentication required" },
          "403": { "description": "Permission denied or plan does not include Skill Scanner" },
          "429": { "description": "Daily skill scan quota exceeded" },
          "500": { "description": "Skill scan failed" }
        }
      }
    },
    "/skills/scans": {
      "get": {
        "summary": "List Skill scan history",
        "description": "Retrieve the authenticated user's Skill scan history, ordered by most recent. The number of rows returned is capped by the user's plan quota.",
        "tags": ["Skill Scanner"],
        "security": [{ "session": [] }],
        "responses": {
          "200": {
            "description": "List of Skill scans",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "scans": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/SkillScanResult" }
                    },
                    "total": {
                      "type": "integer",
                      "description": "Total number of scans for this user"
                    },
                    "limited": {
                      "type": "boolean",
                      "description": "True when the result is truncated by the plan quota"
                    }
                  }
                }
              }
            }
          },
          "401": { "description": "Authentication required" },
          "403": { "description": "Plan does not include Skill scan history" }
        }
      }
    },
    "/skills/scans/{id}": {
      "get": {
        "summary": "Get Skill scan details",
        "description": "Retrieve the full details of a specific Skill scan by ID, including dimension breakdowns and recommendations.",
        "tags": ["Skill Scanner"],
        "security": [{ "session": [] }],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "description": "The Skill scan ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Skill scan details",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SkillScanResult" }
              }
            }
          },
          "401": { "description": "Authentication required" },
          "404": { "description": "Scan not found or does not belong to the current user" }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ScanResult": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "url": { "type": "string" },
          "domain": { "type": "string" },
          "overallScore": { "type": "integer", "minimum": 0, "maximum": 100 },
          "structuredData": { "type": "integer", "minimum": 0, "maximum": 100 },
          "llmReadability": { "type": "integer", "minimum": 0, "maximum": 100 },
          "apiReadiness": { "type": "integer", "minimum": 0, "maximum": 100, "deprecated": true, "description": "Renamed to technicalAccessibility" },
          "technicalAccessibility": { "type": "integer", "minimum": 0, "maximum": 100 },
          "agenticSeo": { "type": "integer", "minimum": 0, "maximum": 100 },
          "recommendations": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "category": { "type": "string" },
                "message": { "type": "string" },
                "priority": { "type": "string", "enum": ["high", "medium", "low"] }
              }
            }
          },
          "llmAnalysis": {
            "type": "object",
            "nullable": true,
            "properties": {
              "summary": { "type": "string" },
              "strengths": { "type": "array", "items": { "type": "string" } },
              "weaknesses": { "type": "array", "items": { "type": "string" } },
              "agentReadiness": { "type": "string" }
            }
          },
          "createdAt": { "type": "string", "format": "date-time" }
        }
      },
      "Agent": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "slug": { "type": "string" },
          "description": { "type": "string" },
          "category": {
            "type": "string",
            "enum": ["SALES", "CONTENT", "SUPPORT", "DEVELOPMENT", "ANALYTICS", "TRADING", "RESEARCH", "PRODUCTIVITY", "OTHER"]
          },
          "trustScore": { "type": "integer", "minimum": 0, "maximum": 100 },
          "transparency": { "type": "integer" },
          "compliance": { "type": "integer" },
          "performance": { "type": "integer" },
          "isCertified": { "type": "boolean" },
          "isFeatured": { "type": "boolean" },
          "integrations": { "type": "string", "description": "JSON string of integration names" },
          "createdAt": { "type": "string", "format": "date-time" }
        }
      },
      "AgentInput": {
        "type": "object",
        "required": ["name", "description", "category"],
        "properties": {
          "name": { "type": "string", "minLength": 2 },
          "description": { "type": "string", "minLength": 10 },
          "category": { "type": "string" },
          "websiteUrl": { "type": "string", "format": "uri" },
          "apiEndpoint": { "type": "string", "format": "uri" },
          "transparency": { "type": "integer", "minimum": 0, "maximum": 100 },
          "compliance": { "type": "integer", "minimum": 0, "maximum": 100 },
          "performance": { "type": "integer", "minimum": 0, "maximum": 100 },
          "integrations": { "type": "string" }
        }
      },
      "McpScanResult": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "slug": { "type": "string" },
          "source": { "type": "string", "enum": ["URL", "CONFIG_FILE", "GITHUB"] },
          "sourceUrl": { "type": "string", "nullable": true },
          "overallScore": { "type": "integer", "minimum": 0, "maximum": 100 },
          "riskLevel": { "type": "string", "enum": ["SAFE", "CAUTION", "DANGEROUS"] },
          "isCertified": { "type": "boolean" },
          "endpointSecurity": { "type": "integer", "minimum": 0, "maximum": 100 },
          "permissionScope": { "type": "integer", "minimum": 0, "maximum": 100 },
          "dataExfiltration": { "type": "integer", "minimum": 0, "maximum": 100 },
          "authStrength": { "type": "integer", "minimum": 0, "maximum": 100 },
          "configTransparency": { "type": "integer", "minimum": 0, "maximum": 100 },
          "details": { "type": "object" },
          "recommendations": { "type": "array", "items": { "type": "object" }, "nullable": true },
          "createdAt": { "type": "string", "format": "date-time" }
        }
      },
      "A2aScanResult": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "slug": { "type": "string" },
          "source": { "type": "string", "enum": ["AGENT_CARD_URL", "CONFIG_FILE", "GITHUB"] },
          "sourceUrl": { "type": "string", "nullable": true },
          "overallScore": { "type": "integer", "minimum": 0, "maximum": 100 },
          "riskLevel": { "type": "string", "enum": ["SAFE", "CAUTION", "DANGEROUS"] },
          "isCertified": { "type": "boolean" },
          "authProtocol": { "type": "integer", "minimum": 0, "maximum": 100 },
          "messageSigning": { "type": "integer", "minimum": 0, "maximum": 100 },
          "delegationDepth": { "type": "integer", "minimum": 0, "maximum": 100 },
          "scopeContainment": { "type": "integer", "minimum": 0, "maximum": 100 },
          "identityVerification": { "type": "integer", "minimum": 0, "maximum": 100 },
          "details": { "type": "object" },
          "recommendations": { "type": "array", "items": { "type": "object" }, "nullable": true },
          "createdAt": { "type": "string", "format": "date-time" }
        }
      },
      "SkillScanResult": {
        "type": "object",
        "description": "Result of a Skill Scanner analysis. The six dimension scores each range from 0–100 and are weighted to produce the overall trust score.",
        "properties": {
          "scanId": {
            "type": "string",
            "description": "Unique scan ID. Prefixed with `ephemeral-` when zero-retention is enabled."
          },
          "name": { "type": "string", "description": "Detected skill name" },
          "slug": { "type": "string", "description": "URL-safe identifier for the scan" },
          "source": {
            "type": "string",
            "enum": ["GITHUB", "CLAWHUB", "FILE_UPLOAD", "MANIFEST_URL"]
          },
          "sourceUrl": { "type": "string", "format": "uri", "nullable": true },
          "overallScore": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "description": "Weighted composite trust score"
          },
          "riskLevel": {
            "type": "string",
            "enum": ["SAFE", "CAUTION", "DANGEROUS"],
            "description": "SAFE ≥ 70, CAUTION 40–69, DANGEROUS < 40"
          },
          "isCertified": {
            "type": "boolean",
            "description": "True when the skill meets AgentLayers certification thresholds"
          },
          "dimensions": {
            "type": "object",
            "description": "Raw dimension scores (0–100 each)",
            "properties": {
              "permissions": {
                "type": "integer", "minimum": 0, "maximum": 100,
                "description": "Least-privilege analysis — does the skill request only necessary permissions?"
              },
              "injectionRisk": {
                "type": "integer", "minimum": 0, "maximum": 100,
                "description": "Prompt- and code-injection resistance"
              },
              "codeTransparency": {
                "type": "integer", "minimum": 0, "maximum": 100,
                "description": "Open source, readable, documented implementation"
              },
              "scopeCreep": {
                "type": "integer", "minimum": 0, "maximum": 100,
                "description": "Adherence to declared scope — no hidden side-effects"
              },
              "supplyChain": {
                "type": "integer", "minimum": 0, "maximum": 100,
                "description": "Dependency health, pinned versions, known CVEs"
              },
              "communityTrust": {
                "type": "integer", "minimum": 0, "maximum": 100,
                "description": "Stars, forks, recent activity, maintainer reputation"
              }
            }
          },
          "breakdowns": {
            "type": "object",
            "description": "Per-dimension evidence and sub-scores (structure varies by source type)"
          },
          "recommendations": {
            "type": "array",
            "nullable": true,
            "description": "Prioritized improvement suggestions. Availability depends on plan.",
            "items": {
              "type": "object",
              "properties": {
                "dimension": { "type": "string" },
                "message": { "type": "string" },
                "priority": { "type": "string", "enum": ["high", "medium", "low"] }
              }
            }
          },
          "persisted": {
            "type": "boolean",
            "description": "False when the user has zero-retention enabled — the scan result is not stored."
          },
          "createdAt": { "type": "string", "format": "date-time" }
        }
      }
    },
    "securitySchemes": {
      "session": {
        "type": "apiKey",
        "in": "cookie",
        "name": "next-auth.session-token",
        "description": "NextAuth session cookie. Authenticate via /auth/signin."
      }
    }
  }
}
