{
  "openapi": "3.1.0",
  "info": {
    "title": "Aback Skills",
    "version": "1.0.0",
    "description": "A free, verified marketplace of agent skills. The public API reads the approved catalogue with no key and no quota. The MCP server installs a skill into a project and needs an API key.",
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://abackskills.com",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "catalogue",
      "description": "The public, approved skill catalogue."
    },
    {
      "name": "mcp",
      "description": "The MCP server that installs skills into projects."
    }
  ],
  "paths": {
    "/api/skills": {
      "get": {
        "tags": ["catalogue"],
        "summary": "List the approved skills",
        "description": "Reads the public catalogue. No key, no quota, and the response is edge cached for sixty seconds.",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": false,
            "schema": { "type": "string" },
            "description": "Every whitespace-separated token must match the name, the description or the tags."
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": { "type": "string" },
            "description": "Restrict the listing to one catalogue category."
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": { "type": "integer", "minimum": 1 }
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": false,
            "schema": { "type": "integer", "minimum": 1 }
          },
          {
            "name": "sortBy",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["created_at_desc", "created_at_asc", "risk_score_desc"]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The matching skills and a pagination block.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SkillListResponse" }
              }
            }
          },
          "400": {
            "description": "The request failed validation."
          }
        }
      }
    },
    "/api/skills/{slug}": {
      "get": {
        "tags": ["catalogue"],
        "summary": "Read one approved skill",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "The skill, its risk signals and its version history.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SkillDetailResponse" }
              }
            }
          },
          "404": {
            "description": "No approved skill matches the slug."
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "tags": ["mcp"],
        "summary": "The Model Context Protocol endpoint",
        "description": "Speaks JSON-RPC 2.0 over Streamable HTTP. The server is stateless. Authenticate with `Authorization: Bearer abk_live_<key>`, or pass the key as an `api_key` query parameter.",
        "security": [{ "bearerAuth": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["jsonrpc", "method"],
                "properties": {
                  "jsonrpc": { "type": "string", "const": "2.0" },
                  "id": { "type": ["string", "number"] },
                  "method": {
                    "type": "string",
                    "examples": ["tools/list", "tools/call", "resources/read"]
                  },
                  "params": { "type": "object" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A JSON-RPC response.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/JsonRpcResponse" }
              }
            }
          },
          "401": {
            "description": "The API key is missing, unknown, revoked or expired."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "An MCP API key. Create one at https://abackskills.com/dashboard/mcp."
      }
    },
    "schemas": {
      "RiskSummary": {
        "type": "object",
        "required": ["hasExternalLinks", "hasScripts", "hasCommands", "riskScore"],
        "properties": {
          "hasExternalLinks": { "type": "boolean" },
          "hasScripts": { "type": "boolean" },
          "hasCommands": { "type": "boolean" },
          "riskScore": { "type": "integer", "minimum": 0, "maximum": 100 }
        }
      },
      "SkillSummary": {
        "type": "object",
        "required": ["id", "slug", "name", "version", "risks"],
        "properties": {
          "id": { "type": "string" },
          "slug": { "type": "string" },
          "name": { "type": "string" },
          "version": { "type": "string" },
          "description": { "type": "string" },
          "category": { "type": "string" },
          "tags": { "type": "array", "items": { "type": "string" } },
          "author": { "type": ["string", "null"] },
          "installCount": { "type": "integer" },
          "risks": { "$ref": "#/components/schemas/RiskSummary" }
        }
      },
      "SkillListResponse": {
        "type": "object",
        "required": ["status", "data"],
        "properties": {
          "status": { "type": "string", "const": "success" },
          "data": {
            "type": "object",
            "required": ["skills", "pagination"],
            "properties": {
              "skills": {
                "type": "array",
                "items": { "$ref": "#/components/schemas/SkillSummary" }
              },
              "pagination": {
                "type": "object",
                "required": ["page", "pageSize", "totalCount", "totalPages"],
                "properties": {
                  "page": { "type": "integer" },
                  "pageSize": { "type": "integer" },
                  "totalCount": { "type": "integer" },
                  "totalPages": { "type": "integer" },
                  "hasNextPage": { "type": "boolean" },
                  "hasPreviousPage": { "type": "boolean" }
                }
              }
            }
          }
        }
      },
      "SkillDetailResponse": {
        "type": "object",
        "required": ["status", "data"],
        "properties": {
          "status": { "type": "string", "const": "success" },
          "data": {
            "type": "object",
            "required": ["skill"],
            "properties": {
              "skill": {
                "type": "object",
                "required": ["slug", "name", "version", "description", "riskPanel"],
                "properties": {
                  "slug": { "type": "string" },
                  "name": { "type": "string" },
                  "version": { "type": "string" },
                  "description": { "type": "string" },
                  "category": { "type": "string" },
                  "tags": { "type": "array", "items": { "type": "string" } },
                  "author": { "type": ["string", "null"] },
                  "installCount": { "type": "integer" },
                  "contentHash": { "type": "string" },
                  "riskPanel": { "$ref": "#/components/schemas/RiskSummary" }
                }
              }
            }
          }
        }
      },
      "JsonRpcResponse": {
        "type": "object",
        "required": ["jsonrpc", "id"],
        "properties": {
          "jsonrpc": { "type": "string", "const": "2.0" },
          "id": { "type": ["string", "number", "null"] },
          "result": { "type": "object" },
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": {
              "code": { "type": "integer" },
              "message": { "type": "string" },
              "data": { "type": "object" }
            }
          }
        }
      }
    }
  }
}
