Versioned JSON contract for structured subject, comparable-grid, and valuation data. Plumb maps it deterministically to UAD 3.6 MISMO XML, PDF, and an Appendix H-1 report that states exactly how many rules were evaluated.
This spec describes the JSON shape a comp importer sends to Plumb Bob to produce XSD-validated UAD 3.6 MISMO XML plus an Appendix H-1 compliance report. It is the contract between data-IN (your importer — TrueTracts, DataMaster, or any equivalent MLS/comp export) and UAD-XML-OUT (Plumb's UAD 3.6 builder and published-rule engine).
Plumb's conversational capture flow is SFR-first today. This ingest format is the structured path for comp importers who already hold the facts in rows and want Plumb to emit the XML and compliance report without re-typing. The format is exercised end-to-end by 13 fixture archetypes in the Plumb repo: SFR, condo, 2–4 unit, new-construction, ADU, basement/waterfront, HOA, and refinance.
GSE_UAD_3.6.0_v1.3 schema.
One JSON object, three required blocks: subject, comparables, and
valuation. Optional blocks cover site, structure, amenities, defects, and
2–4 unit / income-approach data. The public ingest contract is
schemas/plumb_ingest_v1.schema.json, dumped from
src/plumb/importer/models.py::PlumbIngestV1. Validate your payload
against it. The field names below are ingest keys; docs/plumb_ingest_v1.md
carries the field-to-UAD-UID mapping. The internal
subject_property/comparable/appraisal.schema.json files describe the
emitted model your payload maps onto, which is a separate downstream layer.
{
"subject_address": "4218 E Mountain View Dr, Mesa, AZ 85215",
"geocode": {
"matched_address": "...",
"latitude": 33.47,
"longitude": -111.71,
"state_code": "AZ",
"county_name": "Maricopa",
"county_geoid": "04013",
"census_tract": "04013421102"
},
"appraiser_profile": {
"first_name": "...",
"last_name": "...",
"license_number": "...",
"license_state": "AZ",
"license_type": "Certified Residential",
"company_name": "...",
"email": "...",
"phone": "...",
"designations": []
},
"lender_client": {
"lender_name": "...",
"lender_city": "...",
"lender_state": "AZ",
"lender_postal_code": "85003",
"loan_purpose": "Purchase"
},
"characteristics": {
"bedroom_count": 3,
"full_bathroom_count": 2,
"half_bathroom_count": 0,
"gla_square_feet": 2485,
"year_built": 1998,
"overall_condition": "C4",
"overall_quality": "Q4",
"market_boundaries": "North: ...; South: ..."
},
"physical_structure": {
"heating_system_type": "ForcedAir",
"heating_fuel_type": "NaturalGas",
"cooling_system_type": "Central",
"foundation_type": "Slab",
"roof_material_type": "AsphaltShingle",
"exterior_wall_predominant": "Stucco",
"stories_above_grade": 1,
"level_glas": []
},
"amenities": {
"pool_present": false,
"garage_type": "Attached",
"garage_spaces": 2
},
"defects": [],
"comparables": [
{
"ordinal": 1,
"address_line": "...",
"city": "...",
"state_code": "AZ",
"postal_code": "85215",
"sale_price": 642000,
"sale_date": "2026-04-01",
"gla_square_feet": 2400,
"bedroom_count": 3,
"full_bathroom_count": 2,
"half_bathroom_count": 0,
"overall_condition": "C4",
"overall_quality": "Q4",
"heating_type": "ForcedAir"
}
],
"valuation": {
"appraised_value": 632000,
"effective_date": "2026-05-25",
"reconciliation_summary": "...",
"valuation_conditional_conclusion_type": "AsIs",
"exposure_time_low_range_days": 21,
"exposure_time_high_range_days": 60
}
}
| Field | Type | Notes |
|---|---|---|
subject_address | string | One-line street, city, state, ZIP |
geocode | object | Census geocode; Plumb uses state and postal code for the market rate profile |
appraiser_profile | object | Name, license, company, contact, designations |
lender_client | object | Lender name/address and loan_purpose (Purchase/Refinance) |
characteristics | object | Beds, baths, GLA, year built, condition (C1–C6), quality (Q1–Q6), market boundaries |
physical_structure | object | Heating, cooling, foundation, roof, exterior wall, stories |
amenities | object | Pool, garage type/spaces |
defects | array | Each item: description, location, type, category, severity, affects_value, requires_repair |
One entry per comparable. ordinal is 1-indexed and sets grid order.
| Field | Type | Notes |
|---|---|---|
ordinal | int | 1-indexed grid position |
address_line, city, state_code, postal_code | string | Comparable address |
sale_price | int | Closed sale price |
sale_date | string (ISO) | Closed sale date |
gla_square_feet | int | Above-grade finished area |
bedroom_count, full_bathroom_count, half_bathroom_count | int | |
overall_condition, overall_quality | string | C1–C6, Q1–Q6 |
heating_type | string | Optional; omitted stays omitted (honest gaps) |
valuation_use_type | string | Optional: SalesComparable (default), GrossRentMultiplierComparable, RentalComparable, PropertyAnalyzedNotUsed |
| Field | Type | Notes |
|---|---|---|
appraised_value | int | Final reconciled opinion |
effective_date | string (ISO) | Appraisal effective date |
reconciliation_summary | string | Appraiser narrative (max 5000 chars) |
valuation_conditional_conclusion_type | string | AsIs / SubjectToCompletionPerPlans / SubjectToInspection / SubjectToRepair |
exposure_time_low_range_days, exposure_time_high_range_days | int | Marketing/exposure range |
income_approach | object (optional) | 2–4 unit only: gross_rent_multiplier_factor_number, value_indicated_by_income_approach_amount, income_analysis_comment_description |
For 2–4 unit properties, add units (per-unit rent schedule) and
rental_summary (aggregate monthly rents) under characteristics:
"units": [
{
"bedroom_count": 2,
"full_bathroom_count": 1,
"floor_identifier": "1",
"unit_occupancy_type": "Tenant",
"unit_rented_indicator": true,
"unit_monthly_actual_rent_amount": 2200,
"unit_monthly_market_rent_amount": 2300
}
],
"rental_summary": {
"total_monthly_actual_rent_amount": 4600,
"total_monthly_market_rent_amount": 7200
}
Plumb emits one PROPERTY_UNIT per unit, each with its own
UNIT_RENT_SCHEDULE, a RENTAL_INFORMATION_SUMMARY on the
PROPERTY, and an INCOME_APPROACH block under
VALUATION_REPORT with the GRM. IncomeApproachIndicator and
RentScheduleIndicator turn on automatically when the income-approach and
rent-schedule data are present.
The authoritative ingest contract is:
schemas/plumb_ingest_v1.schema.json — the public JSON Schema you validate against (frozen, schema_version "1.0", unknown keys rejected)src/plumb/importer/models.py::PlumbIngestV1 — the Pydantic source it is dumped fromdocs/plumb_ingest_v1.md — the field-to-UAD-UID mapping
The internal schemas/{subject_property,comparable,appraisal}.schema.json
files describe the emitted model your payload maps onto, a separate downstream layer.
If a key is not listed in this spec, it is not yet supported on the ingest path. The
fixture corpus under tests/integration/fixtures/ shows every supported
archetype end-to-end and doubles as a regression gate against the GSEs' own SF1–SF5
passing samples.
Spec questions: hello@plumbvaluation.com. Importer integrations (TrueTracts, DataMaster, or any equivalent) are welcome.