{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/tektolo-com/json-schema/tektolo-com-quick-estimate-request-schema.json",
  "title": "QuickEstimateRequest",
  "description": "Flat, primitive-only input: the easiest way to get an estimate.",
  "x-generated": "2026-10-30",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/tektolo-com-openapi.json#/components/schemas/QuickEstimateRequest",
  "properties": {
    "client_refs": {
      "anyOf": [
        {
          "additionalProperties": {
            "type": "string"
          },
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "title": "Client Refs",
      "description": "Your own reference ids (e.g. unit_id, job_id). Echoed back, never used."
    },
    "zip": {
      "type": "string",
      "pattern": "^\\d{5}$",
      "title": "Zip",
      "description": "The user's 5-digit US ZIP code. If it is missing or not exactly 5 digits, ask the user; never guess, pad or correct it."
    },
    "bedrooms": {
      "type": "integer",
      "maximum": 12.0,
      "minimum": 0.0,
      "title": "Bedrooms",
      "description": "0 for a studio."
    },
    "bathrooms": {
      "anyOf": [
        {
          "type": "number",
          "multipleOf": 0.5,
          "maximum": 12.0,
          "minimum": 0.0
        },
        {
          "type": "string",
          "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
        }
      ],
      "title": "Bathrooms",
      "description": "Half baths count as 0.5."
    },
    "issues": {
      "items": {
        "type": "string"
      },
      "type": "array",
      "maxItems": 100,
      "title": "Issues",
      "description": "What was found in plain English, e.g. ['stained carpet in both bedrooms', 'nail holes everywhere', 'oven is filthy']. Read like pasted notes: an entry may hold several conditions ('carpet stained, nail holes'; one finding each); a room before or after the condition sets the location ('Bedroom 2 carpet torn', 'mold in bathroom'); a written count sets the quantity ('3 blinds broken'); an entry saying there is no work ('no mold', 'leak fixed by tenant') is reported as not billed. All the issues together may hold up to 12,000 characters; send longer notes in more than one request."
    },
    "unit_type": {
      "$ref": "#/$defs/UnitType",
      "description": "Single-family homes and townhomes get house-sized defaults (floor area, locks).",
      "default": "apartment"
    },
    "sq_ft": {
      "anyOf": [
        {
          "type": "integer",
          "maximum": 20000.0,
          "minimum": 150.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Sq Ft",
      "description": "Interior sq ft."
    },
    "year_built": {
      "anyOf": [
        {
          "type": "integer",
          "maximum": 2100.0,
          "minimum": 1700.0
        },
        {
          "type": "null"
        }
      ],
      "title": "Year Built",
      "description": "Drives lead-paint (pre-1978) handling."
    },
    "carpet": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "title": "Carpet",
      "description": "Is there wall-to-wall carpet?"
    },
    "pets": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "title": "Pets",
      "description": "Did pets live in the unit? true adds an optional flea treatment."
    },
    "walk_date": {
      "anyOf": [
        {
          "type": "string",
          "format": "date"
        },
        {
          "type": "null"
        }
      ],
      "title": "Walk Date",
      "description": "The walk-through date; dated or aged items are judged against it. Omit if unknown."
    },
    "profile": {
      "$ref": "#/$defs/Profile",
      "description": "minimum (rent-ready basics) | standard | premium (higher finish).",
      "default": "standard"
    },
    "price_tier": {
      "$ref": "#/$defs/PriceTier",
      "description": "bulk_contract (portfolio contract prices) | pm_vendor (default: a property manager buying turns from local vendors) | retail_one_off (an owner hiring one contractor).",
      "default": "pm_vendor"
    },
    "detail": {
      "type": "string",
      "enum": [
        "summary",
        "full"
      ],
      "title": "Detail",
      "description": "summary (default, small) or full (every line).",
      "default": "summary"
    },
    "retain": {
      "type": "boolean",
      "title": "Retain",
      "description": "Optional (contract 0.5.1). false: keep none of this request's text, so the AI reader's answer for the issues is not stored either. By default the text is kept with contact details and access codes removed, to improve matching; the estimate is the same either way.",
      "default": true
    }
  },
  "additionalProperties": false,
  "type": "object",
  "required": [
    "zip",
    "bedrooms",
    "bathrooms"
  ],
  "$defs": {
    "PriceTier": {
      "type": "string",
      "enum": [
        "bulk_contract",
        "pm_vendor",
        "retail_one_off"
      ],
      "title": "PriceTier",
      "description": "Purchasing channel. Library prices are pm_vendor (a PM buying turns from a local vendor)."
    },
    "Profile": {
      "type": "string",
      "enum": [
        "minimum",
        "standard",
        "premium"
      ],
      "title": "Profile"
    },
    "UnitType": {
      "type": "string",
      "enum": [
        "apartment",
        "single_family",
        "townhome",
        "condo",
        "duplex",
        "manufactured"
      ],
      "title": "UnitType"
    }
  }
}