openapi: 3.1.0
info:
  title: Chicago Value Map API
  version: p0a-2026.07
  description: >
    Tract intelligence, scored listings, and underwriting for Cook + Lake County, IL.
    Automated valuation model — NOT an appraisal. Error rates published at
    /methodology/accuracy (median ARV miss 20.1%, PPE20 50%, N=744, as-of 2026-06).
    Outputs may not be used for tenant screening or credit decisions (FCRA).
servers:
  - url: https://chicago-value-map.mohammad210.workers.dev
security: []
paths:
  /api/health:
    get:
      summary: Service + data freshness
      responses: {"200": {description: "ok, bindings, model_version, last_run, active_listings, stale_model_rows"}}
  /api/tracts/{metro}:
    get:
      summary: All tract metrics for a metro (free read:tracts tier)
      parameters: [{name: metro, in: path, required: true, schema: {type: string, enum: [chicago]}}]
      responses: {"200": {description: "vintage, count, tracts[] — see data-dictionary for fields"}}
  /api/listings/{metro}:
    get:
      summary: Active scored listings (top 200 by deal score, deduped by address)
      parameters: [{name: metro, in: path, required: true, schema: {type: string}}]
      responses: {"200": {description: "listings[] incl. deal_score (null = unscored), arv, offer, model_version"}}
  /api/underwrite:
    get:
      summary: Full underwrite at a point (live comps + risk + economics)
      parameters:
        - {name: lat, in: query, schema: {type: number}}
        - {name: lon, in: query, schema: {type: number}}
        - {name: address, in: query, schema: {type: string}}
        - {name: price, in: query, required: true, schema: {type: number}}
        - {name: units, in: query, schema: {type: integer, default: 2}}
      responses: {"200": {description: "tract, arv_source, arv_note, comp_arv{}, risk{}, underwrite{} — one valuation object, model_version stamped"}}
  /api/metrics/scorecard:
    get:
      summary: Published accuracy scorecard (the /methodology/accuracy source)
      responses: {"200": {description: "backtest v0 + live deals-graded + freshness; cached 1h"}}
  /api/mcp-tools:
    get:
      summary: MCP tool catalog (names, descriptions, schemas) — docs generator source
      responses: {"200": {description: "tools[]"}}
  /api/state:
    get: {summary: "Personal UI state (WRITE_SECRET required)", responses: {"401": {description: unauthorized}}}
    put: {summary: "Personal UI state (WRITE_SECRET required)", responses: {"401": {description: unauthorized}}}
  /api/deals:
    get: {summary: "Deal ledger (WRITE_SECRET required)", responses: {"401": {description: unauthorized}}}
    post: {summary: "Deal ledger upsert (WRITE_SECRET required)", responses: {"401": {description: unauthorized}}}
  /api/run-listings:
    get: {summary: "Trigger listings run (WRITE_SECRET required; modes: daily|sweep|rescore)", responses: {"401": {description: unauthorized}}}
  /mcp:
    post:
      summary: MCP server (streamable HTTP JSON-RPC). PUBLIC BETA — no auth, 30 calls/min/IP. OAuth 2.1 (F2) adds keys/scopes.
      responses: {"200": {description: "JSON-RPC"}, "429": {description: "rate limited"}}
