CDFI Fund NMTC Low-Income Community Screener - IRA 48(e) Bonus
Pricing
from $3.30 / 1,000 results
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
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
8 days ago
Last modified
Categories
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:
| Source | Layer | Role | Live count (2026-09-19) |
|---|---|---|---|
| DOE/NREL 48(e) Category 1 | Category_1_Eligibility_from_20240901_through_2028_2 | decides eligibility | 35,423 |
| Census TIGERweb tracts (2020) | Census Tracts | makes a negative honest | 85,528 |
| Census TIGERweb AIANNHA | Federal American Indian Reservations | context | 312 |
| HUD LIHTC QCT | QUALIFIED_CENSUS_TRACTS_2025 | context | 15,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:
| Host | DNS | Result |
|---|---|---|
cimsprodprep.cdfifund.gov | 164.95.164.53 | connection refused |
cimsprod.cdfifund.gov | 164.95.164.52 | connection refused |
cims.cdfifund.gov | 164.95.164.54 | connect timeout |
www.cdfifund.gov | Akamai | HTTP 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
nullwherever 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:
| label | LIC | 48(e) Cat 1 | basis | coverage | tract | QCT | reservation |
|---|---|---|---|---|---|---|---|
| South Bronx, NY | true | true | nmtc_low_income_community_category_1 | in_census_tract | 36005007900 | true | - |
| Window Rock, AZ | true | true | nmtc_low_income_community_category_1 | in_census_tract | 04001945001 | false | Navajo Nation Reservation |
| Beverly Hills, CA | false | false | verified_not_a_low_income_community | in_census_tract | 06037700801 | false | - |
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):
| label | LIC | 48(e) Cat 1 | basis | coverage |
|---|---|---|---|---|
| Open Pacific (30, -140) | null | null | out_of_us_census_tract_coverage_not_screened | outside_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
| Field | Type | Required | Description |
|---|---|---|---|
assets | array | yes | Points to screen. Each item: lat, lon (WGS84 decimal degrees), optional label. One billable row per asset. |
checkQct | boolean | no | Default true. Also flag the HUD LIHTC Qualified Census Tract as context. Set false to skip; the row then reports qct_status: "skipped_by_input". |
checkTribal | boolean | no | Default true. Also flag a federal Indian reservation as IRC 48(e) Category 2 context. Set false to skip. |
maxAssets | integer | no | Safety 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.
| Field | Type | Description |
|---|---|---|
asset_label | string | null | Your name for the screened asset, echoed from the input. |
asset_lat | number | null | Latitude of the screened point (WGS84). |
asset_lon | number | null | Longitude of the screened point (WGS84). |
in_nmtc_low_income_community | boolean | null | Whether 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_geoid | string | null | 11-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. |
state | string | null | State name of the containing qualifying tract. Null when not in a LIC or not screened. |
county | string | null | County name of the containing qualifying tract. Null when not in a LIC or not screened. |
county_fips | string | null | 5-digit county FIPS (state FIPS + county FIPS) of the containing tract. Null when not screened. |
metro_designation | string | null | Tract 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_rate | number | null | Tract 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_income | number | null | Tract 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_basis | string | null | Text 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_bonus | boolean | null | Whether 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_category | string | null | IRA 48(e) bonus category when qualifying ('48(e) Category 1 - Low-Income Community'). Null when not qualifying. |
adder | string | null | The investment tax credit adder for the category when qualifying. Category 1 = +10 percentage points. Null when not qualifying. |
also_in_lihtc_qct | boolean | null | Informational 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_vintage | string | null | Provenance string for the eligibility source and its tract geography vintage, derived at runtime rather than hard-coded. |
citation | string | null | Statutory/regulatory basis for the bonus and the tract data source. Null on ERROR rows. |
error | string | null | Error message for an invalid coordinate, a partial result, or a total source failure; null when every enabled source answered. |
source_url | string | null | DOE/NREL 48(e) Category 1 eligibility FeatureServer layer the point was queried against. |
checked_at | string | null | UTC timestamp (ISO 8601) when the screening ran. |
nmtc_status | string | null | Outcome 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_error | string | null | Error message when the eligibility query failed; null when it succeeded. |
qct_status | string | null | Outcome of the HUD LIHTC Qualified Census Tract context query: ok / unavailable / not_attempted / skipped_by_input. |
qct_error | string | null | Error message when the QCT query failed; null when it succeeded or was skipped. |
tribal_status | string | null | Outcome of the Census Federal American Indian Reservations context query: ok / unavailable / not_attempted / skipped_by_input. |
tribal_error | string | null | Error message when the reservation query failed; null when it succeeded or was skipped. |
sources_ok_count | integer | null | How many of the four sources answered successfully for this asset. |
sources_total_count | integer | null | Total number of sources this Actor can consult per asset (4). |
partial_result | boolean | null | True 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_id | integer | null | Layer index within the resolved eligibility FeatureServer (0). |
nmtc_layer_name | string | null | Name 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_year | integer | null | Legacy field. Null in v2.0 - the eligibility source does not publish an ACS window. |
nmtc_vintage_end_year | integer | null | Legacy field. Null in v2.0 - the eligibility source does not publish an ACS window. |
metro_designation_normalized | string | null | Normalised 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_rate | number | null | Tract 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_ratio | number | null | Tract 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_population | integer | null | Number 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_qualified | boolean | null | Whether 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_qualified | boolean | null | Whether 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_qualified | boolean | null | CDFI 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_county | boolean | null | Whether 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_flag | boolean | null | The 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_tests | array | null | The 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_indicators | string | null | CDFI 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_reservation | boolean | null | Whether 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_name | string | null | Full name of the containing federal Indian reservation. |
federal_indian_reservation_geoid | string | null | Census AIANNH GEOID of the containing reservation. |
category_2_indian_land_note | string | null | Standing 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_basis | string | null | Audit 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. |
disclaimer | string | null | Informational-use disclaimer. This is a screening tool, not tax advice and not an IRS or CDFI Fund determination. |
source_url_qct | string | null | HUD Qualified Census Tract FeatureServer layer used for the context flag. |
source_url_tribal | string | null | Census TIGERweb Federal American Indian Reservations layer used for the Category 2 context flag. |
actor_version | string | null | Version of this Actor that produced the row. |
coverage_status | string | null | Outcome 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_error | string | null | Error message when the coverage query failed; null when it succeeded. |
coverage_determination | string | null | Whether the Census coverage layer placed this point inside a US census tract: in_census_tract / outside_census_tracts / null (coverage not established). |
determination_note | string | null | Plain-English explanation of how this row's low-income-community answer was reached, including why it is null when it is null. |
tract_vintage | string | null | Census tract geography vintage declared by the eligibility layer. |
tract_attributes_status | string | null | Status 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_note | string | null | Standing explanation of why the per-tract ACS measures are null, so the nulls are never read as negatives or zeros. |
source_migration_note | string | null | Standing disclosure that v2.0 changed the upstream source after the CDFI Fund CIMS service was decommissioned, and what it changed to. |
source_url_coverage | string | null | Census 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.
Related Actors
- 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.
