{
  "openapi": "3.1.0",
  "info": {
    "title": "Building Better Software API",
    "version": "1.0.0",
    "description": "A free public API for a WordPress maintenance company offering self-serve agent registration and a Model Context Protocol server.",
    "contact": {
      "email": "blake@blakehowe.com"
    }
  },
  "servers": [
    {
      "url": "https://buildingbettersoftware.io"
    }
  ],
  "externalDocs": {
    "url": "https://docs.buildingbettersoftware.io"
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": { "type": "string" },
              "message": { "type": "string" },
              "hint": { "type": "string" },
              "docs_url": { "type": "string" }
            }
          }
        }
      },
      "JsonRpcRequest": {
        "type": "object",
        "required": ["jsonrpc", "id", "method"],
        "properties": {
          "jsonrpc": { "type": "string", "const": "2.0" },
          "id": { "type": ["string", "integer", "null"] },
          "method": { "type": "string" },
          "params": { "type": "object" }
        }
      },
      "JsonRpcResponse": {
        "type": "object",
        "required": ["jsonrpc", "id"],
        "properties": {
          "jsonrpc": { "type": "string", "const": "2.0" },
          "id": { "type": ["string", "integer", "null"] },
          "result": { "type": "object" },
          "error": {
            "type": "object",
            "properties": {
              "code": { "type": "integer" },
              "message": { "type": "string" }
            }
          }
        }
      },
      "TokenResponse": {
        "type": "object",
        "properties": {
          "access_token": { "type": "string" },
          "token_type": { "type": "string" },
          "expires_in": { "type": "integer" }
        }
      },
      "ClientCredentials": {
        "type": "object",
        "properties": {
          "client_id": { "type": "string" },
          "client_secret": { "type": "string" }
        }
      },
      "SearchResult": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "title": { "type": "string" },
          "url": { "type": "string" },
          "type": { "type": "string" }
        }
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer"
      },
      "oauthClientCredentials": {
        "type": "oauth2",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "https://buildingbettersoftware.io/oauth/token",
            "scopes": {
              "contact:write": "Allow contact form submissions"
            }
          }
        }
      }
    }
  },
  "paths": {
    "/mcp": {
      "post": {
        "operationId": "mcpJsonRpc",
        "summary": "MCP Streamable-HTTP Endpoint",
        "description": "Processes JSON-RPC 2.0 requests for initialize, tools/list, and tools/call methods including list_services, get_page_content, search_content, and contact_request which is rate limited to five calls per hour per IP.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/JsonRpcRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful JSON-RPC response.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/JsonRpcResponse" }
              }
            }
          },
          "400": {
            "description": "Invalid request format.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "401": {
            "description": "Missing or invalid bearer token.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        },
        "security": [
          { "bearerAuth": [] }
        ]
      }
    },
    "/oauth/token": {
      "post": {
        "operationId": "oauthToken",
        "summary": "Obtain OAuth Token",
        "description": "Exchanges client credentials for an access token via form-encoded submission.",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": ["grant_type", "client_id", "client_secret"],
                "properties": {
                  "grant_type": { "type": "string", "const": "client_credentials" },
                  "client_id": { "type": "string" },
                  "client_secret": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token issued successfully.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/TokenResponse" }
              }
            }
          },
          "400": {
            "description": "Malformed request or missing parameters.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "401": {
            "description": "Invalid client credentials.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    },
    "/agent/register": {
      "post": {
        "operationId": "agentRegister",
        "summary": "Register New Agent",
        "description": "Creates a new anonymous agent for self-serve access without requiring authentication.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["client_name"],
                "properties": {
                  "client_name": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Agent registered successfully.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ClientCredentials" }
              }
            }
          },
          "400": {
            "description": "Invalid registration payload.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    },
    "/agent/claim": {
      "post": {
        "operationId": "agentClaim",
        "summary": "Claim Agent Ownership",
        "description": "Associates an existing client ID with your authenticated account.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["client_id"],
                "properties": {
                  "client_id": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Agent claimed successfully.",
            "content": {
              "application/json": {
                "schema": { "type": "object" }
              }
            }
          },
          "400": {
            "description": "Invalid claim payload.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        },
        "security": [
          { "bearerAuth": [] }
        ]
      }
    },
    "/wp-json/wp/v2/search": {
      "get": {
        "operationId": "searchContent",
        "summary": "Search Content",
        "description": "Returns matching posts and pages based on a query string with optional pagination.",
        "parameters": [
          {
            "name": "search",
            "in": "query",
            "required": true,
            "schema": { "type": "string" }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": { "type": "integer", "minimum": 1, "maximum": 100 }
          }
        ],
        "responses": {
          "200": {
            "description": "Search results retrieved successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": { "$ref": "#/components/schemas/SearchResult" }
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid search parameter.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    },
    "/wp-json/wp/v2/posts": {
      "get": {
        "operationId": "listPosts",
        "summary": "List Posts",
        "description": "Retrieves a paginated list of published blog posts with optional search filtering.",
        "parameters": [
          {
            "name": "per_page",
            "in": "query",
            "schema": { "type": "integer", "minimum": 1, "maximum": 100 }
          },
          {
            "name": "page",
            "in": "query",
            "schema": { "type": "integer", "minimum": 1 }
          },
          {
            "name": "search",
            "in": "query",
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Posts retrieved successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": { "type": "integer" },
                      "date": { "type": "string", "format": "date-time" },
                      "link": { "type": "string", "format": "uri" },
                      "title": { "type": "string" },
                      "excerpt": { "type": "string" }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/wp-json/wp/v2/pages": {
      "get": {
        "operationId": "listPages",
        "summary": "List Pages",
        "description": "Retrieves a paginated list of published site pages with optional search filtering.",
        "parameters": [
          {
            "name": "per_page",
            "in": "query",
            "schema": { "type": "integer", "minimum": 1, "maximum": 100 }
          },
          {
            "name": "page",
            "in": "query",
            "schema": { "type": "integer", "minimum": 1 }
          },
          {
            "name": "search",
            "in": "query",
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Pages retrieved successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": { "type": "integer" },
                      "date": { "type": "string", "format": "date-time" },
                      "link": { "type": "string", "format": "uri" },
                      "title": { "type": "string" },
                      "excerpt": { "type": "string" }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "operationId": "getLlmsTxt",
        "summary": "Retrieve LLMs.txt",
        "description": "Serves the machine-readable documentation file for direct LLM consumption.",
        "responses": {
          "200": {
            "description": "LLMs.txt content served successfully.",
            "content": {
              "text/plain": {
                "schema": { "type": "string" }
              }
            }
          }
        }
      }
    },
    "/.well-known/agents.json": {
      "get": {
        "operationId": "getAgentDiscovery",
        "summary": "Agent Discovery Metadata",
        "description": "Provides standardized discovery information for AI agent integration.",
        "responses": {
          "200": {
            "description": "Discovery metadata retrieved successfully.",
            "content": {
              "application/json": {
                "schema": { "type": "object" }
              }
            }
          }
        }
      }
    }
  }
}