{
  "openapi": "3.1.0",
  "info": {
    "title": "AskBaily ChatGPT App API",
    "version": "0.1.0",
    "summary": "OpenAPI description of the AskBaily ChatGPT App's MCP tool surface plus its OAuth 2.1 endpoints. The canonical data-API description lives at /data/openapi.json — this file is scoped to Apps-SDK introspection only.",
    "description": "Every tool advertised via JSON-RPC `tools/list` on https://askbaily.com/api/mcp/tools is exposed as an equivalent HTTP POST here so OpenAI's submission-time introspection can pre-validate schemas without speaking MCP. See https://askbaily.com/chat-app/tools.json for the native MCP tool catalog.",
    "contact": {
      "name": "AskBaily Apps",
      "email": "apps@askbaily.com",
      "url": "https://askbaily.com/docs/chatgpt-app"
    },
    "license": {
      "name": "Proprietary — AskBaily Inc.",
      "url": "https://askbaily.com/terms"
    }
  },
  "servers": [
    { "url": "https://askbaily.com", "description": "Production" }
  ],
  "tags": [
    { "name": "mcp", "description": "Model Context Protocol tools (JSON-RPC 2.0 over HTTP POST)" },
    { "name": "oauth", "description": "OAuth 2.1 + PKCE endpoints for the save_project_to_account tool" },
    { "name": "discovery", "description": "Cross-reference to the canonical data API" }
  ],
  "paths": {
    "/api/mcp/tools": {
      "post": {
        "tags": ["mcp"],
        "summary": "JSON-RPC 2.0 entry point for the 6-tool catalog",
        "operationId": "mcpRpc",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/JsonRpcRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC 2.0 response (result or error)",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/JsonRpcResponse" }
              }
            }
          }
        }
      },
      "get": {
        "tags": ["mcp"],
        "summary": "Return the tool catalog as a static snapshot (reviewer-friendly)",
        "operationId": "mcpListToolsGet",
        "responses": {
          "200": {
            "description": "Tool catalog snapshot",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ToolsListResult" }
              }
            }
          }
        }
      }
    },
    "/api/mcp/tools#scope_project": {
      "post": {
        "tags": ["mcp"],
        "summary": "scope_project tool",
        "description": "Capture a homeowner's project scope. Returns scope_id + summary.",
        "operationId": "scopeProject",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ScopeProjectInput" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Structured scope record",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ScopeProjectOutput" }
              }
            }
          }
        }
      }
    },
    "/api/mcp/tools#find_contractor": {
      "post": {
        "tags": ["mcp"],
        "summary": "find_contractor tool",
        "description": "Return the matched contractor profile or a waitlist slot.",
        "operationId": "findContractor",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/FindContractorInput" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Matched or waitlist contractor",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/FindContractorOutput" }
              }
            }
          }
        }
      }
    },
    "/api/mcp/tools#check_licensing": {
      "post": {
        "tags": ["mcp"],
        "summary": "check_licensing tool",
        "description": "Validate a contractor license number and return regulator deep-link + status.",
        "operationId": "checkLicensing",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/CheckLicensingInput" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "License-status record",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CheckLicensingOutput" }
              }
            }
          }
        }
      }
    },
    "/api/mcp/tools#get_cost_estimate": {
      "post": {
        "tags": ["mcp"],
        "summary": "get_cost_estimate tool",
        "description": "Return the cost range for a project type in a city (reads /data/cost-ranges.json).",
        "operationId": "getCostEstimate",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/GetCostEstimateInput" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cost-range record",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/GetCostEstimateOutput" }
              }
            }
          }
        }
      }
    },
    "/api/mcp/tools#get_regulatory_context": {
      "post": {
        "tags": ["mcp"],
        "summary": "get_regulatory_context tool",
        "description": "Return permit and regulatory callouts for a city / neighborhood.",
        "operationId": "getRegulatoryContext",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/GetRegulatoryContextInput" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Regulatory callouts record",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/GetRegulatoryContextOutput" }
              }
            }
          }
        }
      }
    },
    "/api/mcp/tools#schedule_consult": {
      "post": {
        "tags": ["mcp"],
        "summary": "schedule_consult tool",
        "description": "Initiate a Baily-mediated consultation. Requires homeowner_consent_given=true.",
        "operationId": "scheduleConsult",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ScheduleConsultInput" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Consultation state",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ScheduleConsultOutput" }
              }
            }
          }
        }
      }
    },
    "/api/oauth/authorize": {
      "get": {
        "tags": ["oauth"],
        "summary": "OAuth 2.1 authorization endpoint (renders consent)",
        "operationId": "oauthAuthorize",
        "parameters": [
          { "name": "client_id", "in": "query", "required": true, "schema": { "type": "string" } },
          { "name": "redirect_uri", "in": "query", "required": true, "schema": { "type": "string", "format": "uri" } },
          { "name": "response_type", "in": "query", "required": true, "schema": { "type": "string", "enum": ["code"] } },
          { "name": "state", "in": "query", "required": false, "schema": { "type": "string" } },
          { "name": "scope", "in": "query", "required": false, "schema": { "type": "string" } },
          { "name": "code_challenge", "in": "query", "required": true, "schema": { "type": "string" } },
          { "name": "code_challenge_method", "in": "query", "required": true, "schema": { "type": "string", "enum": ["S256"] } }
        ],
        "responses": {
          "200": { "description": "Consent HTML rendered", "content": { "text/html": {} } },
          "400": { "description": "invalid_request" },
          "503": { "description": "Feature flag disabled" }
        }
      }
    },
    "/api/oauth/token": {
      "post": {
        "tags": ["oauth"],
        "summary": "OAuth 2.1 token exchange (authorization_code + PKCE)",
        "operationId": "oauthToken",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": ["grant_type", "code", "client_id", "redirect_uri", "code_verifier"],
                "properties": {
                  "grant_type": { "type": "string", "const": "authorization_code" },
                  "code": { "type": "string" },
                  "client_id": { "type": "string" },
                  "redirect_uri": { "type": "string", "format": "uri" },
                  "code_verifier": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Access token issued",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["access_token", "token_type", "expires_in"],
                  "properties": {
                    "access_token": { "type": "string" },
                    "token_type": { "type": "string", "const": "Bearer" },
                    "expires_in": { "type": "integer" },
                    "scope": { "type": "string" }
                  }
                }
              }
            }
          },
          "400": { "description": "invalid_request / invalid_grant" },
          "503": { "description": "Feature flag disabled" }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "JsonRpcRequest": {
        "type": "object",
        "required": ["jsonrpc", "method"],
        "properties": {
          "jsonrpc": { "type": "string", "const": "2.0" },
          "id": { "oneOf": [{ "type": "string" }, { "type": "integer" }, { "type": "null" }] },
          "method": { "type": "string" },
          "params": { "type": "object" }
        }
      },
      "JsonRpcResponse": {
        "type": "object",
        "required": ["jsonrpc"],
        "properties": {
          "jsonrpc": { "type": "string", "const": "2.0" },
          "id": { "oneOf": [{ "type": "string" }, { "type": "integer" }, { "type": "null" }] },
          "result": {},
          "error": {
            "type": "object",
            "properties": {
              "code": { "type": "integer" },
              "message": { "type": "string" },
              "data": {}
            }
          }
        }
      },
      "ToolsListResult": {
        "type": "object",
        "properties": {
          "tools": { "type": "array", "items": { "type": "object" } }
        }
      },
      "ScopeProjectInput": {
        "type": "object",
        "required": ["city", "project_type", "budget_range", "timeline"],
        "properties": {
          "city": { "type": "string" },
          "project_type": { "type": "string", "enum": ["kitchen", "bathroom", "adu", "full_home", "roofing", "hvac", "solar", "pool", "electrical", "plumbing", "flooring", "windows", "other"] },
          "budget_range": {
            "type": "object",
            "required": ["low_usd", "high_usd"],
            "properties": {
              "low_usd": { "type": "integer" },
              "high_usd": { "type": "integer" }
            }
          },
          "timeline": { "type": "string", "enum": ["asap", "1_3_months", "3_6_months", "6_12_months", "flexible"] },
          "notes": { "type": "string" }
        }
      },
      "ScopeProjectOutput": {
        "type": "object",
        "required": ["scope_id", "summary"],
        "properties": {
          "scope_id": { "type": "string" },
          "summary": { "type": "string" },
          "next_step_url": { "type": "string", "format": "uri" }
        }
      },
      "FindContractorInput": {
        "type": "object",
        "required": ["scope_id"],
        "properties": { "scope_id": { "type": "string" } }
      },
      "FindContractorOutput": {
        "type": "object",
        "required": ["status"],
        "properties": {
          "status": { "type": "string", "enum": ["matched", "waitlist", "unavailable"] },
          "contractor": { "type": "object" },
          "waitlist_position": { "type": "integer" }
        }
      },
      "CheckLicensingInput": {
        "type": "object",
        "required": ["state", "license_number"],
        "properties": {
          "state": { "type": "string", "enum": ["CA", "AZ", "NV", "WA", "FL", "TX", "GA", "NY", "NY-NYC", "IL", "ON", "UK", "AU-NSW", "AU-VIC", "SG", "AE-DUBAI", "NZ"] },
          "license_number": { "type": "string" }
        }
      },
      "CheckLicensingOutput": {
        "type": "object",
        "required": ["state", "license_number", "status", "verified_at"],
        "properties": {
          "state": { "type": "string" },
          "license_number": { "type": "string" },
          "status": { "type": "string", "enum": ["active", "inactive", "suspended", "revoked", "unknown"] },
          "business_name": { "type": "string" },
          "classifications": { "type": "array", "items": { "type": "string" } },
          "insurance_required": { "type": "boolean" },
          "regulator_url": { "type": "string", "format": "uri" },
          "verified_at": { "type": "string", "format": "date-time" }
        }
      },
      "GetCostEstimateInput": {
        "type": "object",
        "required": ["city", "service"],
        "properties": {
          "city": { "type": "string" },
          "service": { "type": "string" }
        }
      },
      "GetCostEstimateOutput": {
        "type": "object",
        "required": ["city", "service", "currency", "low", "high"],
        "properties": {
          "city": { "type": "string" },
          "service": { "type": "string" },
          "currency": { "type": "string", "const": "USD" },
          "low": { "type": "integer" },
          "high": { "type": "integer" },
          "confidence": { "type": "string", "enum": ["high", "medium", "low"] },
          "permit_required": { "type": "boolean" },
          "source_url": { "type": "string", "format": "uri" }
        }
      },
      "GetRegulatoryContextInput": {
        "type": "object",
        "required": ["city"],
        "properties": {
          "city": { "type": "string" },
          "neighborhood": { "type": "string" }
        }
      },
      "GetRegulatoryContextOutput": {
        "type": "object",
        "required": ["city", "callouts"],
        "properties": {
          "city": { "type": "string" },
          "neighborhood": { "type": "string" },
          "regulator_name": { "type": "string" },
          "regulator_url": { "type": "string", "format": "uri" },
          "callouts": {
            "type": "array",
            "items": {
              "type": "object",
              "required": ["title", "detail"],
              "properties": {
                "title": { "type": "string" },
                "detail": { "type": "string" },
                "source_url": { "type": "string", "format": "uri" }
              }
            }
          }
        }
      },
      "ScheduleConsultInput": {
        "type": "object",
        "required": ["scope_id", "time_slot", "homeowner_consent_given"],
        "properties": {
          "scope_id": { "type": "string" },
          "time_slot": { "type": "string", "format": "date-time" },
          "homeowner_consent_given": { "type": "boolean" }
        }
      },
      "ScheduleConsultOutput": {
        "type": "object",
        "required": ["consultation_id", "status"],
        "properties": {
          "consultation_id": { "type": "string" },
          "status": { "type": "string", "enum": ["pending", "contractor_notified", "scheduled", "declined"] },
          "baily_thread_url": { "type": "string", "format": "uri" }
        }
      }
    }
  },
  "externalDocs": {
    "url": "https://askbaily.com/data/openapi.json",
    "description": "Canonical data API description"
  }
}
