CDFI Fund NMTC Low-Income Community Screener - IRA 48(e) Bonus avatar

CDFI Fund NMTC Low-Income Community Screener - IRA 48(e) Bonus

Pricing

from $3.30 / 1,000 results

Go to Apify Store
CDFI Fund NMTC Low-Income Community Screener - IRA 48(e) Bonus

CDFI Fund NMTC Low-Income Community Screener - IRA 48(e) Bonus

Coordinate lookup for the IRA 48(e) low-income clean-energy bonus. Batch lat/lon against the DOE/NREL 48(e) Category 1 layer (IRC 45D(e) NMTC low-income communities). Returns a tract GEOID, Category 1 bonus flag, adder, Census tract coverage and a HUD QCT flag. MCP-ready.

Pricing

from $3.30 / 1,000 results

Rating

0.0

(0)

Developer

Kyle Maloney

Kyle Maloney

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

8 days ago

Last modified

Share

CDFI NMTC Low-Income Community Screener - IRA 48(e) Bonus Credit

Batch-screen coordinates against the federal map of New Markets Tax Credit low-income communities (IRC 45D(e)) - the Category 1 pathway to the Inflation Reduction Act's +10 percentage-point ITC adder under IRC 48(e) / 48E(h). One clean row per site, with the tract GEOID, the Category 1 flag, an explicit coverage determination, and two context flags: HUD LIHTC Qualified Census Tract, and federal Indian reservation (Category 2 context).

Keyless. Four services, queried live on every run:

SourceLayerRoleLive count (2026-09-19)
DOE/NREL 48(e) Category 1Category_1_Eligibility_from_20240901_through_2028_2decides eligibility35,423
Census TIGERweb tracts (2020)Census Tractsmakes a negative honest85,528
Census TIGERweb AIANNHAFederal American Indian Reservationscontext312
HUD LIHTC QCTQUALIFIED_CENSUS_TRACTS_2025context15,727

What changed in v2.0 (2026-09-19) - the upstream was decommissioned

Through v1.1 this Actor read the U.S. Treasury CDFI Fund CIMS ArcGIS service. CDFI retired it. This was measured, not inferred:

HostDNSResult
cimsprodprep.cdfifund.gov164.95.164.53connection refused
cimsprod.cdfifund.gov164.95.164.52connection refused
cims.cdfifund.gov164.95.164.54connect timeout
www.cdfifund.govAkamaiHTTP 200

DNS resolves for all three; nothing is listening on 443. CDFI's own /cims page now links exclusively to a Salesforce app, which exposes no keyless data endpoint: the Salesforce REST data API returns HTTP 401, /services/apexrest/ returns 404, and the guest UI channel returns permission denied as an empty success - a query for the standard Contact object comes back state:"SUCCESS" with result: []. Building a tax screen on that would manufacture confident false negatives.

The replacement has better provenance than what it replaces

v2.0 reads the DOE/NREL Low-Income Communities Bonus Credit Program's own Category 1 eligibility layer - the agency that administers the IRC 48(e) allocation, publishing the determination it allocates against. v1.1 read CDFI's NMTC map and inferred 48(e) Category 1 from it; v2.0 reads the 48(e) answer directly.

It reproduces this Actor's own recorded canary exactly: South Bronx NY resolves to tract 36005007900 on both the dead CIMS layer and the new one.

The hard part: "zero features" no longer means "not eligible"

The new layer holds only qualifying tracts - NMTCQualif has exactly one distinct value live, "Yes". So a zero-feature answer is ambiguous between three very different things: not qualified, outside US census-tract coverage, and the query silently broke. That last one is not hypothetical - the missing-inSR false clear that bit v1.0 on CIMS exists on the new layer too (South Bronx returns 1 feature with inSR=4326 and 0 without, HTTP 200 either way).

So v2.0 adds an independent Census coverage layer whose only job is to answer "is this point inside a US census tract, and which one". A negative is published only when coverage affirmatively places the point in a tract and the eligibility layer answered and returned zero. Every other case is null with a stated basis in bonus_eligibility_basis - never false.

The two sources also cross-check each other's GEOID. If they disagree about which tract a point is in, the row is null, not a guess.

What v2.0 cannot answer, and says so

CIMS published 15 per-tract attributes; the new layer publishes 6. The per-tract ACS measures have no keyless replacement - poverty rate, percent of area median family income, unemployment rate and ratio, metro designation, the high-migration flag, poverty population, and the per-test qualified booleans. Those fields are retained (nothing was removed or renamed) and are null on every row, with tract_attributes_status and tract_attributes_note stating why. Null means not checked - never zero, never false.

CDFI's surviving CDFI_Investment_Areas_ACS_2016_2020.xlsb was evaluated as a substitute and deliberately rejected: recomputing IRC 45D(e) from it agrees with the authoritative determination only 93.79% of the time, because the CDFI Investment Area test uses different income benchmarks. It is a different legal test, and publishing its flags as NMTC qualifiers would be a confident wrong answer on a tax position.

The price, tiers and categories are unchanged.


Who this is for

  • Solar, storage and community-solar developers pre-screening a site pipeline for the 48(e) Category 1 low-income-community adder before committing to an application.
  • Tax equity investors and their counsel sanity-checking a sponsor's eligibility claim, with the tract GEOID, the deciding source and the coverage determination on the record - and an explicit null wherever the answer could not be established.
  • CDFIs and NMTC allocatees checking whether a project sits in a qualifying tract. (Note: v2.0 reports whether a tract qualifies, not the underlying poverty/income measures - see "What v2.0 cannot answer" above.)
  • Site-selection and EPC teams layering the bonus onto the rest of the constraint picture.
  • AI agents doing site due diligence - see the MCP note below.

Example input

{
"assets": [
{ "lat": 40.815, "lon": -73.904, "label": "South Bronx, NY (low-income community, also a LIHTC QCT)" },
{ "lat": 35.6811, "lon": -109.0509, "label": "Window Rock, AZ (low-income community on the Navajo Nation)" },
{ "lat": 34.073, "lon": -118.4, "label": "Beverly Hills, CA (genuine clear - not a low-income community)" }
],
"checkQct": true,
"checkTribal": true,
"maxAssets": 500
}

That is the prefilled input. Measured live on build 2.0.2 (run FgxdpMxxP6MApM7PC, 5.6 s, 3 rows) it returns:

labelLIC48(e) Cat 1basiscoveragetractQCTreservation
South Bronx, NYtruetruenmtc_low_income_community_category_1in_census_tract36005007900true-
Window Rock, AZtruetruenmtc_low_income_community_category_1in_census_tract04001945001falseNavajo Nation Reservation
Beverly Hills, CAfalsefalseverified_not_a_low_income_communityin_census_tract06037700801false-

Note the third row. Beverly Hills is a verified negative: the eligibility layer answered and returned nothing, and the Census coverage layer independently placed the point inside tract 06037700801. Contrast a point in the open Pacific, measured on the same build (run SnbcwtipFj5H01onj):

labelLIC48(e) Cat 1basiscoverage
Open Pacific (30, -140)nullnullout_of_us_census_tract_coverage_not_screenedoutside_census_tracts

Both returned zero features from the eligibility layer. Only one of them is a negative. Through v1.1 they would have been indistinguishable, and both would have read false.

Input fields

FieldTypeRequiredDescription
assetsarrayyesPoints to screen. Each item: lat, lon (WGS84 decimal degrees), optional label. One billable row per asset.
checkQctbooleannoDefault true. Also flag the HUD LIHTC Qualified Census Tract as context. Set false to skip; the row then reports qct_status: "skipped_by_input".
checkTribalbooleannoDefault true. Also flag a federal Indian reservation as IRC 48(e) Category 2 context. Set false to skip.
maxAssetsintegernoSafety cap on how many assets are screened. Default 500, max 5,000.

Omitting assets returns HTTP 400 at run creation - the run never starts and nothing is billed.


Output fields

One row per screened asset. Every one of the 63 declared fields is listed here (this table is generated from the Actor's own dataset schema, so it cannot drift from it).

null on a flag always means the backing source did not answer, or could not establish the answer, never the answer is no.

FieldTypeDescription
asset_labelstring | nullYour name for the screened asset, echoed from the input.
asset_latnumber | nullLatitude of the screened point (WGS84).
asset_lonnumber | nullLongitude of the screened point (WGS84).
in_nmtc_low_income_communityboolean | nullWhether the point falls inside a census tract that the DOE/NREL 48(e) Category 1 layer maps as an IRC 45D(e) low-income community. FALSE ONLY when the eligibility layer answered, returned nothing, AND the Census coverage layer affirmatively placed the point inside a US census tract - i.e. a verified negative. NULL whenever that could not be established: eligibility source down, coverage source down, point outside US census-tract coverage, the two sources disagreeing on the tract, or an invalid coordinate. Read coverage_determination and bonus_eligibility_basis to tell those apart.
tract_geoidstring | null11-digit census tract GEOID (state FIPS + county FIPS + tract). On a qualifying point this is the eligibility layer's tract; on a verified negative it is the Census coverage tract. Null when the point was not screened.
statestring | nullState name of the containing qualifying tract. Null when not in a LIC or not screened.
countystring | nullCounty name of the containing qualifying tract. Null when not in a LIC or not screened.
county_fipsstring | null5-digit county FIPS (state FIPS + county FIPS) of the containing tract. Null when not screened.
metro_designationstring | nullTract metro/non-metro designation. ALWAYS NULL IN v2.0: this measure was published only by the decommissioned CDFI Fund CIMS service and no keyless replacement was found. Null means NOT CHECKED - never zero and never false. See tract_attributes_note.
poverty_ratenumber | nullTract poverty rate percent. ALWAYS NULL IN v2.0: this measure was published only by the decommissioned CDFI Fund CIMS service and no keyless replacement was found. Null means NOT CHECKED - never zero and never false. See tract_attributes_note.
pct_median_family_incomenumber | nullTract median family income as a percent of the applicable area median. ALWAYS NULL IN v2.0: this measure was published only by the decommissioned CDFI Fund CIMS service and no keyless replacement was found. Null means NOT CHECKED - never zero and never false. See tract_attributes_note.
lic_basisstring | nullText basis for the low-income-community determination. In v2.0 the per-test breakdown (poverty rate vs median family income) is NOT available - the eligibility source publishes membership only. See tract_attributes_note.
qualifies_48e_lowincome_bonusboolean | nullWhether the site meets the IRC 48(e)/48E(h) Category 1 (low-income community) pathway to the +10 percentage-point ITC adder. Null when the NMTC source did not answer. The adder is capacity-limited and allocated by application through the DOE program, so this is a screening indicator, not an allocation and not tax advice. Categories 2-4 are separate pathways not decided here.
bonus_categorystring | nullIRA 48(e) bonus category when qualifying ('48(e) Category 1 - Low-Income Community'). Null when not qualifying.
adderstring | nullThe investment tax credit adder for the category when qualifying. Category 1 = +10 percentage points. Null when not qualifying.
also_in_lihtc_qctboolean | nullInformational cross-flag: whether the point is also in a HUD LIHTC Qualified Census Tract. QCT is a LIHTC concept and not itself a 48(e) pathway. Null when the lookup failed or was switched off with checkQct:false - read qct_status to tell those apart.
nmtc_vintagestring | nullProvenance string for the eligibility source and its tract geography vintage, derived at runtime rather than hard-coded.
citationstring | nullStatutory/regulatory basis for the bonus and the tract data source. Null on ERROR rows.
errorstring | nullError message for an invalid coordinate, a partial result, or a total source failure; null when every enabled source answered.
source_urlstring | nullDOE/NREL 48(e) Category 1 eligibility FeatureServer layer the point was queried against.
checked_atstring | nullUTC timestamp (ISO 8601) when the screening ran.
nmtc_statusstring | nullOutcome of the DOE/NREL 48(e) Category 1 eligibility query: ok / unavailable / not_attempted. This is the only source that can decide Category 1 eligibility.
nmtc_errorstring | nullError message when the eligibility query failed; null when it succeeded.
qct_statusstring | nullOutcome of the HUD LIHTC Qualified Census Tract context query: ok / unavailable / not_attempted / skipped_by_input.
qct_errorstring | nullError message when the QCT query failed; null when it succeeded or was skipped.
tribal_statusstring | nullOutcome of the Census Federal American Indian Reservations context query: ok / unavailable / not_attempted / skipped_by_input.
tribal_errorstring | nullError message when the reservation query failed; null when it succeeded or was skipped.
sources_ok_countinteger | nullHow many of the four sources answered successfully for this asset.
sources_total_countinteger | nullTotal number of sources this Actor can consult per asset (4).
partial_resultboolean | nullTrue when a source that was supposed to run did not answer, so some flags on this row are null (not checked) rather than negative. A source deliberately switched off by input does not count as partial.
nmtc_layer_idinteger | nullLayer index within the resolved eligibility FeatureServer (0).
nmtc_layer_namestring | nullName of the live DOE/NREL eligibility service used, resolved at runtime by NAME PATTERN so a renamed program window is picked up rather than silently missed.
nmtc_vintage_start_yearinteger | nullLegacy field. Null in v2.0 - the eligibility source does not publish an ACS window.
nmtc_vintage_end_yearinteger | nullLegacy field. Null in v2.0 - the eligibility source does not publish an ACS window.
metro_designation_normalizedstring | nullNormalised metro/non-metro designation. ALWAYS NULL IN v2.0: this measure was published only by the decommissioned CDFI Fund CIMS service and no keyless replacement was found. Null means NOT CHECKED - never zero and never false. See tract_attributes_note.
unemployment_ratenumber | nullTract unemployment rate. ALWAYS NULL IN v2.0: this measure was published only by the decommissioned CDFI Fund CIMS service and no keyless replacement was found. Null means NOT CHECKED - never zero and never false. See tract_attributes_note.
unemployment_rate_rationumber | nullTract unemployment rate as a multiple of the national average. ALWAYS NULL IN v2.0: this measure was published only by the decommissioned CDFI Fund CIMS service and no keyless replacement was found. Null means NOT CHECKED - never zero and never false. See tract_attributes_note.
poverty_populationinteger | nullNumber of tract residents below the poverty line. ALWAYS NULL IN v2.0: this measure was published only by the decommissioned CDFI Fund CIMS service and no keyless replacement was found. Null means NOT CHECKED - never zero and never false. See tract_attributes_note.
poverty_rate_qualifiedboolean | nullWhether the tract meets the IRC 45D(e) poverty test. ALWAYS NULL IN v2.0: this measure was published only by the decommissioned CDFI Fund CIMS service and no keyless replacement was found. Null means NOT CHECKED - never zero and never false. See tract_attributes_note.
median_income_qualifiedboolean | nullWhether the tract meets the IRC 45D(e) median-family-income test. ALWAYS NULL IN v2.0: this measure was published only by the decommissioned CDFI Fund CIMS service and no keyless replacement was found. Null means NOT CHECKED - never zero and never false. See tract_attributes_note.
unemployment_ratio_qualifiedboolean | nullCDFI severe-distress indicator: unemployment at or above 1.5x the national average. ALWAYS NULL IN v2.0: this measure was published only by the decommissioned CDFI Fund CIMS service and no keyless replacement was found. Null means NOT CHECKED - never zero and never false. See tract_attributes_note.
high_migration_rural_countyboolean | nullWhether the tract sits in a high out-migration rural county (IRC 45D(e)(2)). ALWAYS NULL IN v2.0: this measure was published only by the decommissioned CDFI Fund CIMS service and no keyless replacement was found. Null means NOT CHECKED - never zero and never false. See tract_attributes_note.
cdfi_nmtc_qualified_flagboolean | nullThe eligibility layer's own NMTCQualif attribute for this tract, carried through so the caller can see the published flag directly. Null when not in a qualifying tract.
lic_qualifying_testsarray | nullThe IRC 45D(e) tests this tract meets, as a list. ALWAYS NULL IN v2.0: this measure was published only by the decommissioned CDFI Fund CIMS service and no keyless replacement was found. Null means NOT CHECKED - never zero and never false. See tract_attributes_note.
severe_distress_indicatorsstring | nullCDFI severe-distress indicators recorded for this tract. ALWAYS NULL IN v2.0: this measure was published only by the decommissioned CDFI Fund CIMS service and no keyless replacement was found. Null means NOT CHECKED - never zero and never false. See tract_attributes_note.
on_federal_indian_reservationboolean | nullWhether the point falls inside a Census TIGERweb Federal American Indian Reservations polygon. Informational context for IRC 48(e) Category 2 only - see category_2_indian_land_note.
federal_indian_reservation_namestring | nullFull name of the containing federal Indian reservation.
federal_indian_reservation_geoidstring | nullCensus AIANNH GEOID of the containing reservation.
category_2_indian_land_notestring | nullStanding caveat: on_federal_indian_reservation is informational, and statutory Indian land under 25 U.S.C. 3501(2) is broader than federal reservations, so false does not rule Category 2 out.
bonus_eligibility_basisstring | nullAudit trail for qualifies_48e_lowincome_bonus. Closed vocabulary: nmtc_low_income_community_category_1 / verified_not_a_low_income_community / verified_not_a_low_income_community_but_on_federal_indian_reservation_see_category_2 / out_of_us_census_tract_coverage_not_screened / coverage_source_unavailable_not_screened / eligibility_source_unavailable_not_screened / source_geoid_disagreement_not_screened.
disclaimerstring | nullInformational-use disclaimer. This is a screening tool, not tax advice and not an IRS or CDFI Fund determination.
source_url_qctstring | nullHUD Qualified Census Tract FeatureServer layer used for the context flag.
source_url_tribalstring | nullCensus TIGERweb Federal American Indian Reservations layer used for the Category 2 context flag.
actor_versionstring | nullVersion of this Actor that produced the row.
coverage_statusstring | nullOutcome of the Census TIGERweb census-tract coverage query: ok / unavailable / not_attempted. This source is LOAD-BEARING for a negative: it is what distinguishes "verified not a low-income community" from "we could not tell".
coverage_errorstring | nullError message when the coverage query failed; null when it succeeded.
coverage_determinationstring | nullWhether the Census coverage layer placed this point inside a US census tract: in_census_tract / outside_census_tracts / null (coverage not established).
determination_notestring | nullPlain-English explanation of how this row's low-income-community answer was reached, including why it is null when it is null.
tract_vintagestring | nullCensus tract geography vintage declared by the eligibility layer.
tract_attributes_statusstring | nullStatus of the per-tract ACS measures (poverty rate, median family income percent, unemployment, metro designation, high-migration flag, poverty population, per-test booleans). Always "unavailable" in v2.0 - see tract_attributes_note.
tract_attributes_notestring | nullStanding explanation of why the per-tract ACS measures are null, so the nulls are never read as negatives or zeros.
source_migration_notestring | nullStanding disclosure that v2.0 changed the upstream source after the CDFI Fund CIMS service was decommissioned, and what it changed to.
source_url_coveragestring | nullCensus TIGERweb census-tract layer used to establish coverage.

Fields that are null, and what that means

Two different kinds of null ship on a healthy run, and they are not the same claim.

1. Structurally unavailable in v2.0 (always null). The per-tract ACS measures - poverty_rate, pct_median_family_income, unemployment_rate, unemployment_rate_ratio, poverty_population, poverty_rate_qualified, median_income_qualified, unemployment_ratio_qualified, high_migration_rural_county, metro_designation, metro_designation_normalized, lic_qualifying_tests and severe_distress_indicators - were published only by the decommissioned CDFI CIMS service. They are kept so nothing downstream breaks, and every row carries tract_attributes_status: "unavailable" plus tract_attributes_note explaining it. nmtc_vintage_start_year and nmtc_vintage_end_year are null for the same reason.

2. Null because nothing went wrong. nmtc_error, coverage_error, qct_error, tribal_error and error are null when every source answered - that is good news, not a dead column. Each is pinned by a fault-injection test and populates during an upstream outage.

The tract-identity fields are null on an out-of-coverage or unscreened point, and federal_indian_reservation_* is null off-reservation. The prefill deliberately includes a qualifying tract, a reservation hit and a genuine clear, so the whole verdict space populates on an auto-QA run.


Use as an MCP tool

This Actor is available to AI agents through mcp.apify.com. It takes plain coordinates and returns a flat, self-describing row: qualifies_48e_lowincome_bonus for the yes/no, bonus_eligibility_basis for why, nmtc_vintage for the data vintage, and nmtc_status / coverage_status / qct_status / tribal_status so an agent can tell a verified negative from an unanswered one.

Pricing

$6 per 1,000 results (pay-per-event, one Result event per screened asset). Graduated discounts apply on paid Apify plans. There are no other charge events.

Billing honesty: if the NMTC layer does not answer for a single asset, the run fails and emits nothing, so you are not billed for an outage.

FAQ

Does a hit mean I get the +10 point adder? No. The 48(e) Low-Income Communities Bonus Credit is capacity-limited and allocated by application through the DOE program. Sitting in a qualifying tract is a necessary condition, not an allocation.

Is this the "energy community" bonus? No, and this is the most common confusion. The IRA has two different +10 point adders. This Actor screens the low-income community bonus (IRC 48(e)/48E(h), Category 1, defined by cross-reference to the NMTC low-income community in IRC 45D(e)). The separate energy community bonus (IRC 45(b)(11) / 48(a)(14)) covers brownfield sites, statistical areas with historical fossil-fuel employment, and census tracts with a retired coal mine or coal-fired plant - that is not checked here.

What about Categories 2, 3 and 4? Category 2 is Indian land, Category 3 a qualified low-income residential building project, Category 4 a qualified low-income economic benefit project. None of them is decided here. on_federal_indian_reservation is informational Category 2 context only, and statutory Indian land under 25 U.S.C. 3501(2) is broader than the federal-reservation layer, so false there does not rule Category 2 out.

Why are poverty_rate, pct_median_family_income and the other tract measures null? Because they have no keyless source any more. They were published only by the CDFI Fund CIMS service, which was decommissioned (see the v2.0 section above). The fields are retained so nothing downstream breaks, and every row carries tract_attributes_status: "unavailable" with a note. Null means not checked - it is never a zero and never a "no". The low-income-community determination itself is unaffected: it comes straight from DOE/NREL's own Category 1 eligibility layer.

What is the difference between false and null on in_nmtc_low_income_community? false is a verified negative: the eligibility layer answered, returned no qualifying tract, and the Census coverage layer independently confirmed the point is inside a US census tract. null means the answer could not be established - the point is outside US census-tract coverage, a source was down, or the two sources disagreed about which tract it is. bonus_eligibility_basis names which. This distinction matters because the eligibility layer contains only qualifying tracts, so a zero-feature response on its own is not evidence of anything.

Why did my run fail with "LIVE DRIFT CHECK FAILED"? Because an upstream no longer matches what this Actor was verified against - a renamed or re-vintaged service, a qualified-tract layer that no longer contains only qualified tracts, a coverage layer that stopped filtering, or a canary that stopped returning known-good data. A loud failure is the correct answer on a tax position. Nothing is billed on a failed run.

Is this tax advice? No. It is an informational screen against public DOE/NREL, Census and HUD data. Confirm against the DOE Low-Income Communities Bonus Credit Program rules and IRS guidance with tax counsel.

  • HUD QCT + DDA Screener - the LIHTC 130% basis boost for the same coordinate.
  • HUD Affordable Housing Explorer - LIHTC, multifamily and public-housing inventory plus Opportunity Zones.
  • Tribal Land Jurisdiction Screener - a fuller jurisdictional picture than the reservation context flag here.
  • Site Due Diligence Bundle - 20 federal constraint layers for one coordinate.

Informational screening tool built on public U.S. Treasury CDFI Fund and HUD data. Not tax advice, and not an IRS or CDFI Fund determination. The 48(e) adder is capacity-limited and allocated by application. Confirm with the CDFI Fund, the DOE program and your tax counsel before relying on it.