openapi: 3.0.3
info:
  title: Rent Limits API
  version: "2.0.0"
  description: |
    Answers to the rent and income questions landlords, tax-credit owners and housing analysts ask about a US ZIP
    code - each answer with the official figures it rests on, their effective dates and their sources.

    - What can this existing tax-credit unit legally charge, given when it was placed in service?  `/v1/taxcredit?placed_in_service=` (PRO+)
    - How far does the local voucher payment standard sit from the federal benchmark?  `/v1/local` (ULTRA+)
    - Is rent being left on the table when a voucher holder rents a tax-credit unit?  `/v1/market` (ULTRA+)
    - How many income-qualified, cost-burdened renter households are there for each tax-credit rent?  `/v1/market` (ULTRA+)
    - Which of this ZIP's income areas holds most of its residences?  `income_area_by_residences` (PRO+)

    Contains HUD data; values marked `computed_by: "this service"` are computed by this service from published
    government figures, which are shown unmodified as evidence. **This product uses the HUD User Data API but is not
    endorsed or certified by HUD User.** Not legal or financial advice.
servers:
  - url: https://rent-limits-api.p.rapidapi.com
paths:
  /v1/federal:
    get:
      summary: Fair Market Rents and Small Area FMRs for a ZIP (all plans)
      operationId: federal
      parameters:
        - $ref: "#/components/parameters/zip"
        - $ref: "#/components/parameters/bedrooms4"
      responses:
        "200": {description: FMR and SAFMR rows for every HUD rent area the ZIP lies in, FY2027 and FY2026, content: {application/json: {schema: {$ref: "#/components/schemas/Federal"}}}}
        "400": {$ref: "#/components/responses/BadRequest"}
        "403": {$ref: "#/components/responses/PlanTooLow"}
        "404": {$ref: "#/components/responses/NotFound"}
        "503": {$ref: "#/components/responses/Unavailable"}
  /v1/incomelimits:
    get:
      summary: HUD Section 8 income limits (30/50/80%, 1-8 persons) for each county or town the ZIP touches (PRO and above)
      operationId: incomelimits
      parameters:
        - $ref: "#/components/parameters/zip"
        - $ref: "#/components/parameters/fips"
      responses:
        "200": {description: Candidates with income limits, content: {application/json: {schema: {$ref: "#/components/schemas/Candidates"}}}}
        "400": {$ref: "#/components/responses/BadRequest"}
        "403": {$ref: "#/components/responses/PlanTooLow"}
        "404": {$ref: "#/components/responses/NotFound"}
        "503": {$ref: "#/components/responses/Unavailable"}
  /v1/taxcredit:
    get:
      summary: Tax-credit (LIHTC / MTSP) limits - for new projects, and for an existing project by its placed-in-service date (PRO and above)
      description: |
        Without `placed_in_service`: HUD's current MTSP limits for projects placed in service on or after the current
        effective date (v1 behaviour, unchanged).
        With `placed_in_service=YYYY-MM-DD`: each candidate also carries `applicable_limits` - the held-harmless
        limits for that placed-in-service window (IRC §142(d)(2)(E): the running maximum of HUD's MTSP limits from
        the window's year to now, each household size separately), with the window, the years considered, the
        controlling year per household size and HUD's limits for every year as evidence. `placed_in_service=all`
        returns one answer per window (the chart state agencies publish).
        A "not served" answer (before 2009, before the first window this service holds, a redefined HUD area, or a
        withheld feature) is still HTTP 200 and still counts as one call against your plan quota.
      operationId: taxcredit
      parameters:
        - $ref: "#/components/parameters/zip"
        - $ref: "#/components/parameters/bedrooms5"
        - $ref: "#/components/parameters/fips"
        - $ref: "#/components/parameters/placed_in_service"
      responses:
        "200": {description: Candidates with MTSP limits and (when asked) applicable_limits, content: {application/json: {schema: {$ref: "#/components/schemas/TaxCredit"}}}}
        "400": {$ref: "#/components/responses/BadRequest"}
        "403": {$ref: "#/components/responses/PlanTooLow"}
        "404": {$ref: "#/components/responses/NotFound"}
        "503": {$ref: "#/components/responses/Unavailable"}
  /v1/local:
    get:
      summary: Local housing-agency payment standards, how far each sits from the federal benchmark, and a utility-allowance reference (ULTRA and above)
      operationId: local
      parameters:
        - $ref: "#/components/parameters/zip"
        - $ref: "#/components/parameters/bedrooms5"
      responses:
        "200": {description: Agencies covering the ZIP; each schedule carries payment_standard_vs_federal, content: {application/json: {schema: {$ref: "#/components/schemas/Local"}}}}
        "400": {$ref: "#/components/responses/BadRequest"}
        "403": {$ref: "#/components/responses/PlanTooLow"}
        "404": {$ref: "#/components/responses/NotFound"}
        "503": {$ref: "#/components/responses/Unavailable"}
  /v1/market:
    get:
      summary: Voucher rent headroom in tax-credit units and renter demand by tax-credit rent (ULTRA and MEGA)
      description: |
        `voucher_rent_headroom` (24 CFR 982.507(c)): the rent to owner of a voucher household in a tax-credit unit may
        reach the lesser of a reasonable rent and the payment standard. This service measures
        `achievable_gross_rent = min(Census ACS median gross rent aged by BLS CPI, payment standard + the agency's
        utility allowance)` and `voucher_rent_above_taxcredit_max` = the amount above the tax-credit maximum gross
        rent, or `null` when there is none. Never negative. An area-level measurement, not an approved rent.
        `renter_demand_by_taxcredit_rent`: HUD CHAS 2018-2022 renter households at <=30/<=50/<=80% HAMFI (banded and
        cumulative) and cost-burdened counts, beside the tax-credit maximum gross rent of the matching tier.
      operationId: market
      parameters:
        - $ref: "#/components/parameters/zip"
        - $ref: "#/components/parameters/bedrooms5"
        - $ref: "#/components/parameters/placed_in_service_date"
        - {name: tier, in: query, required: false, description: "Tax-credit tier for voucher_rent_headroom: 20, 30, 40, 50, 60, 70, 80 or all (default 60)", schema: {type: string, enum: ["20", "30", "40", "50", "60", "70", "80", "all"], default: "60"}}
      responses:
        "200": {description: Computed answers with their evidence, content: {application/json: {schema: {$ref: "#/components/schemas/Market"}}}}
        "400": {$ref: "#/components/responses/BadRequest"}
        "403": {$ref: "#/components/responses/PlanTooLow"}
        "404": {$ref: "#/components/responses/NotFound"}
        "503": {$ref: "#/components/responses/Unavailable"}
  /v1/coverage:
    get:
      summary: Data vintages, layer status (including placed_in_service), crosswalk and market vintages, coverage counts (all plans)
      operationId: coverage
      responses:
        "200": {description: Coverage summary, content: {application/json: {schema: {type: object}}}}
components:
  parameters:
    zip: {name: zip, in: query, required: true, description: "5-digit ZIP (ZIP+4 accepted; leading zeros required, e.g. 00604)", schema: {type: string, pattern: "^[0-9]{5}(-?[0-9]{4})?$", example: "06604"}}
    bedrooms4: {name: bedrooms, in: query, required: false, description: "0 (studio) to 4; omit for all sizes", schema: {type: integer, minimum: 0, maximum: 4}}
    bedrooms5: {name: bedrooms, in: query, required: false, description: "0 (studio) to 5; omit for all sizes", schema: {type: integer, minimum: 0, maximum: 5}}
    fips: {name: fips, in: query, required: false, description: "10-digit code of one candidate (from a previous response) to select a single county or town", schema: {type: string, pattern: "^[0-9]{10}$"}}
    placed_in_service: {name: placed_in_service, in: query, required: false, description: "ISO date (YYYY-MM-DD, on or after 1987-01-01) or 'all'. With the 8609 line 8b multiple-building election use the first building's date; acquisition/rehab uses the acquisition date.", schema: {type: string, pattern: "^([0-9]{4}-[0-9]{2}-[0-9]{2}|all)$", example: "2020-06-01"}}
    placed_in_service_date: {name: placed_in_service, in: query, required: false, description: "ISO date: compare against that project's held-harmless tax-credit maximum instead of the current one", schema: {type: string, pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"}}
  responses:
    BadRequest: {description: "Invalid zip, bedrooms, fips, tier or placed_in_service (malformed, year only, impossible date, or before 1987-01-01)"}
    PlanTooLow: {description: Your plan does not include this endpoint}
    NotFound: {description: ZIP not in HUD or Census files, or fips is not a candidate for the ZIP}
    Unavailable: {description: Daily capacity reached (Retry-After set) or a layer not yet available}
  schemas:
    Source:
      type: object
      description: |
        Provenance of a layer. source_url = the official file, or HUD's public dataset page when the data came from
        HUD's API; source_sha256 = the SHA-256 of that HUD file, or of this service's dated snapshot of HUD's API
        answer. retrieved_via says which ("file", "HUD User API", "BLS download").
      properties:
        vintage: {type: string, example: FY2027}
        effective_date: {type: string, format: date}
        source_url: {type: string}
        source_sha256: {type: string}
        retrieved_via: {type: string, enum: [file, HUD User API, BLS download]}
        retrieved_utc: {type: string}
    Federal:
      type: object
      properties:
        zip: {type: string}
        fair_market_rents: {type: array, items: {allOf: [{$ref: "#/components/schemas/Source"}, {type: object, properties: {hud_area_code: {type: string}, hud_area_name: {type: string}, rents: {type: object, additionalProperties: {type: integer}}}}]}}
        small_area_fmrs: {type: array, items: {type: object}}
        notes: {type: array, items: {type: string}}
        disclaimer: {type: string}
    IncomeAreaByResidences:
      type: object
      description: Which listed income area holds most of the ZIP's residential addresses (HUD-USPS crosswalk, ratios unmodified).
      properties:
        most_residences_in: {type: string, nullable: true, description: 10-digit fips of a listed candidate}
        most_residences_in_reason: {type: string}
        status: {type: string, enum: [zip_in_crosswalk, zip_absent_from_crosswalk]}
        crosswalk_areas_not_listed: {type: array, items: {type: object, properties: {geoid: {type: string}, residential_ratio: {type: number}}}}
        computed_by: {type: string, example: this service}
        note: {type: string}
        vintage: {type: string, example: 2026 Q2}
    Candidate:
      type: object
      properties:
        fips: {type: string}
        name: {type: string}
        land_share: {type: number, nullable: true}
        crosswalk: {type: object, properties: {status: {type: string, enum: [in_crosswalk, zip_present_no_addresses_here, candidate_not_in_crosswalk_for_this_zip, zip_absent_from_crosswalk]}, residential_ratio: {type: number, nullable: true}, total_ratio: {type: number, nullable: true}}}
    ApplicableLimits:
      type: object
      properties:
        available: {type: boolean}
        reason: {type: string}
        pis_date: {type: string}
        pis_window: {type: string, example: "FY2019 (2019-04-24 – 2020-03-31)"}
        years_considered: {type: array, items: {type: string}}
        controlling_year_by_household_size: {type: object}
        income_limits: {type: object}
        max_gross_rents: {type: object}
        grace_alternative: {type: object}
        grace_rule: {type: string}
        provisional: {type: boolean}
        not_modelled: {type: array, items: {type: string}}
        computed_by: {type: string, example: this service}
        method: {type: string}
        evidence: {type: object, description: "HUD MTSP 50%/60% limits for every fiscal year considered, unmodified, with their source"}
    TaxCredit:
      type: object
      properties:
        zip: {type: string}
        income_area_by_residences: {$ref: "#/components/schemas/IncomeAreaByResidences"}
        candidates: {type: array, items: {allOf: [{$ref: "#/components/schemas/Candidate"}, {type: object, properties: {standard: {type: object}, applicable_limits: {$ref: "#/components/schemas/ApplicableLimits"}}}]}}
        disclaimer: {type: string}
    Candidates:
      type: object
      properties:
        zip: {type: string}
        income_area_by_residences: {$ref: "#/components/schemas/IncomeAreaByResidences"}
        candidates: {type: array, items: {$ref: "#/components/schemas/Candidate"}}
        disclaimer: {type: string}
    Local:
      type: object
      properties:
        zip: {type: string}
        agencies: {type: array, items: {type: object, properties: {pha_code: {type: string}, schedules: {type: array, items: {type: object, properties: {payment_standard: {type: object}, payment_standard_vs_federal: {type: object, properties: {comparisons: {type: array, items: {type: object, properties: {hud_area_code: {type: string}, fy: {type: string}, vs_fmr: {type: object}, vs_safmr: {type: object, nullable: true}}}}, fy_basis: {type: string}, computed_by: {type: string}}}}}}}}}
        disclaimer: {type: string}
    Market:
      type: object
      properties:
        zip: {type: string}
        tier: {type: string}
        voucher_rent_headroom:
          type: object
          properties:
            available: {type: boolean}
            reason: {type: string}
            computed_by: {type: string}
            rule: {type: string}
            lines: {type: array, items: {type: object, description: "One line per agency tenant-based schedule; by_bedrooms -> achievable_gross_rent, lower_bound, market_evidence, by_candidate -> tiers -> {taxcredit_max_gross_rent, voucher_rent_above_taxcredit_max (null when none), text}"}}
            inputs: {type: object}
        renter_demand_by_taxcredit_rent:
          type: array
          items: {type: object, description: "Per income area: CHAS area, tiers 30/50/80 with taxcredit_max_gross_rents, banded and cumulative renter households and cost-burdened counts; tier 60 not derivable"}
        disclaimer: {type: string}
externalDocs:
  description: Rent Limits documentation
  url: https://glazeddata.com/rent-limits/api/
x-hud-notice: "This product uses the HUD User Data API but is not endorsed or certified by HUD User."
