{
  "openapi": "3.1.0",
  "info": {
    "title": "BishopTech Public API",
    "version": "1.0.0",
    "description": "The documented public BishopTech REST surface for capability discovery, service health, published content, user-approved contact requests, and website readiness scans. Admin, cron, webhook, analytics, and authenticated application routes are excluded.",
    "contact": {
      "name": "BishopTech",
      "url": "https://www.bishoptech.dev/contact",
      "email": "matt@bishoptech.dev"
    }
  },
  "servers": [
    {
      "url": "https://www.bishoptech.dev",
      "description": "BishopTech production API"
    }
  ],
  "externalDocs": {
    "description": "BishopTech API and agent resources",
    "url": "https://www.bishoptech.dev/api"
  },
  "paths": {
    "/api/capabilities": {
      "get": {
        "operationId": "getPublicCapabilities",
        "summary": "Discover public capabilities",
        "description": "Returns the public operations, authentication policy, and side effects that an agent should understand before calling BishopTech.",
        "responses": {
          "200": {
            "description": "Public capability catalog",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CapabilitiesResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/aio-api": {
      "get": {
        "operationId": "getServiceHealth",
        "summary": "Read service health",
        "description": "Returns a lightweight BishopTech service health response. This endpoint has no side effect and does not require authentication.",
        "responses": {
          "200": {
            "description": "Service health response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceHealthResponse"
                }
              }
            }
          },
          "500": {
            "description": "Service health could not be generated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/blog/posts": {
      "get": {
        "operationId": "listPublishedBlogPosts",
        "summary": "List published blog posts",
        "description": "Returns published posts from the configured BishopTech content stores, normalized to a stable response shape.",
        "responses": {
          "200": {
            "description": "Published posts",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BlogPostsResponse"
                }
              }
            }
          },
          "500": {
            "description": "Published content could not be loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/blog/posts/{slug}": {
      "get": {
        "operationId": "getPublishedBlogPost",
        "summary": "Get one published blog post",
        "description": "Returns a single published post by its stable slug.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Slug"
          }
        ],
        "responses": {
          "200": {
            "description": "Published post",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BlogPostResponse"
                }
              }
            }
          },
          "400": {
            "description": "The slug is missing or invalid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "No published post matched the slug",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "The post could not be loaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/contact": {
      "post": {
        "operationId": "submitContactRequest",
        "summary": "Submit a contact or consultation request",
        "description": "Creates a lead and may send an email notification. This is a side-effecting operation; an agent must have explicit user intent before calling it.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The message was sent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactResponse"
                }
              }
            }
          },
          "202": {
            "description": "The lead was saved and will be followed up even though notification delivery is pending",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactResponse"
                }
              }
            }
          },
          "400": {
            "description": "The request body is not valid JSON",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be delivered or saved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/readiness-check/scan": {
      "post": {
        "operationId": "runWebsiteReadinessScan",
        "summary": "Run a website readiness scan",
        "description": "Crawls a submitted website, evaluates public readiness signals, and stores a report. This can use external crawling and AI services; call only after the user explicitly requests an audit.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReadinessScanRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Readiness scan completed and stored",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadinessScanResponse"
                }
              }
            }
          },
          "400": {
            "description": "Required scan fields are missing or the body is invalid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "The scan or persistence operation failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "Slug": {
        "name": "slug",
        "in": "path",
        "required": true,
        "description": "The published post slug.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "pattern": "^[a-z0-9][a-z0-9-]*$"
        }
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "required": ["success", "error", "code", "resolution"],
        "properties": {
          "success": {
            "type": "boolean",
            "const": false
          },
          "error": {
            "type": "string",
            "description": "Human-readable error message."
          },
          "code": {
            "type": "string",
            "description": "Stable machine-readable error code."
          },
          "resolution": {
            "type": "string",
            "description": "Next action an agent or developer can take."
          }
        },
        "additionalProperties": true
      },
      "Capability": {
        "type": "object",
        "required": ["id", "name", "method", "path", "description", "sideEffect"],
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "method": { "type": "string", "enum": ["GET", "POST"] },
          "path": { "type": "string" },
          "description": { "type": "string" },
          "sideEffect": { "type": "string" }
        }
      },
      "CapabilitiesResponse": {
        "type": "object",
        "required": ["name", "description", "contract", "documentation", "authentication", "capabilities", "callingRule"],
        "properties": {
          "name": { "type": "string", "const": "BishopTech" },
          "description": { "type": "string" },
          "contract": { "type": "string", "format": "uri" },
          "documentation": { "type": "string", "format": "uri" },
          "agentInstructions": { "type": "string", "format": "uri" },
          "authentication": {
            "type": "object",
            "required": ["required", "note"],
            "properties": {
              "required": { "type": "boolean", "const": false },
              "note": { "type": "string" }
            }
          },
          "capabilities": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/Capability" }
          },
          "callingRule": { "type": "string" }
        }
      },
      "ServiceHealthResponse": {
        "type": "object",
        "required": ["success", "timestamp", "data", "health"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "timestamp": { "type": "string", "format": "date-time" },
          "data": {
            "type": "object",
            "required": ["status", "service", "version", "domain", "endpoints", "features", "lastChecked"],
            "properties": {
              "status": { "type": "string" },
              "service": { "type": "string" },
              "version": { "type": "string" },
              "domain": { "type": "string" },
              "endpoints": { "type": "object", "additionalProperties": { "type": "string" } },
              "features": { "type": "array", "items": { "type": "string" } },
              "lastChecked": { "type": "string", "format": "date-time" }
            }
          },
          "health": {
            "type": "object",
            "required": ["status"],
            "properties": {
              "status": { "type": "string" },
              "uptime": { "type": "number" },
              "version": { "type": "string" }
            },
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      },
      "BlogPost": {
        "type": "object",
        "required": ["slug"],
        "properties": {
          "slug": { "type": "string" },
          "title": { "type": "string" },
          "description": { "type": ["string", "null"] },
          "mainImage": { "type": ["string", "null"], "format": "uri" },
          "publishedAt": { "type": ["string", "null"], "format": "date-time" },
          "updatedAt": { "type": ["string", "null"], "format": "date-time" }
        },
        "additionalProperties": true
      },
      "BlogPostsResponse": {
        "type": "object",
        "required": ["success", "posts", "count"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "posts": { "type": "array", "items": { "$ref": "#/components/schemas/BlogPost" } },
          "count": { "type": "integer", "minimum": 0 }
        }
      },
      "BlogPostResponse": {
        "type": "object",
        "required": ["success", "post"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "post": { "$ref": "#/components/schemas/BlogPost" }
        }
      },
      "ContactRequest": {
        "type": "object",
        "required": ["name", "email", "message"],
        "properties": {
          "name": { "type": "string", "minLength": 1, "description": "Name of the person asking to be contacted." },
          "email": { "type": "string", "format": "email" },
          "message": { "type": "string", "minLength": 1, "description": "What the user wants BishopTech to help build or fix." },
          "company": { "type": "string" },
          "phone": { "type": "string" },
          "projectType": { "type": "string" },
          "launchTimeline": { "type": "string" },
          "hostingPreference": { "type": "string" },
          "leadType": { "type": "string" },
          "source": { "type": "string" },
          "attribution": { "type": "object", "additionalProperties": true }
        },
        "additionalProperties": true
      },
      "ContactResponse": {
        "type": "object",
        "required": ["success", "message"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "message": { "type": "string" }
        }
      },
      "ReadinessScanRequest": {
        "type": "object",
        "required": ["website_url", "contact_email"],
        "properties": {
          "website_url": { "type": "string", "format": "uri", "description": "Website to scan. HTTPS is recommended." },
          "contact_email": { "type": "string", "format": "email" },
          "contact_name": { "type": "string" },
          "contact_phone": { "type": "string" },
          "company_name": { "type": "string" }
        },
        "additionalProperties": false
      },
      "ReadinessScanResponse": {
        "type": "object",
        "required": ["success", "id", "result"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "id": { "type": "string" },
          "result": {
            "type": "object",
            "required": ["overall_score", "readiness_level", "schema_status", "has_llm_txt", "ai_crawlers_allowed"],
            "properties": {
              "overall_score": { "type": "number", "minimum": 0, "maximum": 100 },
              "readiness_level": { "type": "string" },
              "schema_status": { "type": "string" },
              "has_llm_txt": { "type": "boolean" },
              "ai_crawlers_allowed": { "type": "boolean" },
              "page_speed_score": { "type": "number" },
              "critical_errors": { "type": "array", "items": { "type": "string" } },
              "warnings": { "type": "array", "items": { "type": "string" } },
              "optimization_opportunities": { "type": "array", "items": { "type": "string" } }
            },
            "additionalProperties": true
          }
        }
      }
    }
  }
}
