openapi: 3.1.0
info:
  title: HavenCostGuide Public Cost-Estimate API
  description: |
    Free, public, deterministic U.S. home-renovation cost estimates by project,
    state, size, and quality tier. Powers the [HavenCostGuide](https://havencostguide.com)
    calculator UI, the 550 state-landing pages, and the [/answers/](https://havencostguide.com/answers)
    AI-friendly index — all return identical numbers because all surfaces use this same arithmetic.

    Built for:
    - AI agents (LangChain / MCP tools / ChatGPT Custom GPTs)
    - Journalists and researchers
    - Affiliate / aggregator sites
    - Mobile apps and Chrome extensions

    No authentication. No rate limit beyond a global fair-use cap.
    Stable, versioned at `/api/v1/`. Published under CC-BY 4.0 — please cite
    HavenCostGuide with a backlink when republishing.
  version: "1.0.0"
  contact:
    name: HavenCostGuide
    url: https://havencostguide.com/contact
    email: api@havencostguide.com
  license:
    name: CC-BY 4.0
    url: https://creativecommons.org/licenses/by/4.0/
servers:
  - url: https://havencostguide.com
    description: Production
paths:
  /api/v1/cost-estimate:
    get:
      operationId: getCostEstimate
      summary: Get a state-adjusted renovation cost estimate
      description: |
        Returns a deterministic USD low-high range for the requested renovation
        project given U.S. state, size, quality tier, and (optionally) scope.

        The arithmetic is `baseRange × stateMultiplier × qualityMultiplier × 1.10`
        (10% contingency). The same formula powers the calculator UI, all 550
        state landings, the /answers hub, and the public dataset — so AI
        agents quoting this endpoint will always match the website.

        Example: a mid-range, medium-size kitchen remodel in California returns
        `{"low": 50050, "high": 92950}` — exactly matching the
        `/kitchen-remodel-cost-california` state-landing page.
      parameters:
        - name: project
          in: query
          required: true
          description: Project type. Use /api/v1/projects to discover valid values.
          schema:
            type: string
            enum: [kitchen, bathroom, flooring, roofing, solar, windows, deck, basement, fence, pool, painting]
        - name: state
          in: query
          required: true
          description: 2-letter U.S. state code (e.g., CA, TX, NY).
          schema:
            type: string
            pattern: "^[A-Za-z]{2}$"
        - name: size
          in: query
          required: false
          description: Project size tier. Defaults to 'medium'.
          schema:
            type: string
            enum: [small, medium, large]
            default: medium
        - name: quality
          in: query
          required: false
          description: Quality / materials tier. Defaults to 'mid'.
          schema:
            type: string
            enum: [budget, mid, high]
            default: mid
        - name: scope
          in: query
          required: false
          description: |
            Project scope (e.g., 'full', 'asphalt', 'composite'). Defaults to
            the primary scope of the project type. Use /api/v1/projects to
            discover valid scopes per project.
          schema:
            type: string
      responses:
        "200":
          description: Successful cost estimate
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CostEstimate"
              examples:
                kitchen_california:
                  summary: Mid-range medium kitchen in California
                  value:
                    project: kitchen
                    project_name: Kitchen Remodel
                    state: CA
                    scope: full
                    size: medium
                    quality: mid
                    range: { low: 50050, high: 92950, currency: USD }
                    state_cost_index: 1.40
                    includes: "labor (50%), materials (35%), permits (5%), and 10% contingency"
                    methodology: "https://havencostguide.com/methodology"
                    dataset: "https://havencostguide.com/dataset/2026-renovation-cost-index"
                    license: "CC-BY 4.0"
                    attribution: "HavenCostGuide (2026), 2026 U.S. Renovation Cost Index"
                    api_version: v1
        "400":
          description: Invalid project, state, scope, size, or quality
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ApiError"
  /api/v1/projects:
    get:
      operationId: listProjects
      summary: List all supported renovation project types and their scopes
      description: |
        Discovery endpoint for AI agents. Returns the full taxonomy of project
        types, their valid scopes, sizes, and quality tiers — call this first
        before /cost-estimate to know the parameter space.
      responses:
        "200":
          description: List of projects
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProjectList"
  /api/v1/states:
    get:
      operationId: listStates
      summary: List all 50 U.S. states with their renovation-cost-index multipliers
      description: |
        Returns every U.S. state's cost-index multiplier versus the national
        base (1.0). Values >1.0 mean the state runs above the U.S. average
        (e.g., CA=1.40, HI=1.55); <1.0 means below (e.g., MS=0.85, IA=0.85).
      responses:
        "200":
          description: List of states
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StateList"
components:
  schemas:
    CostEstimate:
      type: object
      properties:
        project:
          type: string
          description: Project type ID
        project_name:
          type: string
          description: Human-readable project name
        state:
          type: string
          description: 2-letter U.S. state code
        scope:
          type: string
        size:
          type: string
          enum: [small, medium, large]
        quality:
          type: string
          enum: [budget, mid, high]
        range:
          type: object
          properties:
            low:
              type: integer
              description: Lower end of the estimate, USD
            high:
              type: integer
              description: Upper end of the estimate, USD
            currency:
              type: string
              example: USD
        state_cost_index:
          type: number
          description: Cost-index multiplier vs U.S. national base (1.0)
        includes:
          type: string
          description: What the range covers (labor split, contingency, etc.)
        methodology:
          type: string
          format: uri
          description: Link to the full methodology page
        dataset:
          type: string
          format: uri
          description: Link to the public dataset (CC-BY 4.0)
        license:
          type: string
          example: CC-BY 4.0
        attribution:
          type: string
          description: Required attribution string when citing
        api_version:
          type: string
          example: v1
    ProjectList:
      type: object
      properties:
        api_version:
          type: string
        projects:
          type: array
          items:
            type: object
            properties:
              id: { type: string }
              name: { type: string }
              scopes: { type: array, items: { type: string } }
              sizes: { type: array, items: { type: string } }
              quality_tiers: { type: array, items: { type: string } }
        license: { type: string }
        dataset: { type: string, format: uri }
    StateList:
      type: object
      properties:
        api_version: { type: string }
        states:
          type: array
          items:
            type: object
            properties:
              code: { type: string, description: "2-letter state code" }
              cost_index: { type: number, description: "Multiplier vs national base 1.0" }
        national_base: { type: number, example: 1.0 }
        methodology: { type: string, format: uri }
    ApiError:
      type: object
      properties:
        detail: { type: string }
