Working with the U.S. Census of Governments Finance API
A guide for Southern state, county and city analysis
Author
Civilytics
Published
August 26, 2026
What this is
This guide demonstrates a live web API over U.S. government finance data spanning FY1967 through FY2024 — 56 published fiscal years (FY1968 and FY1969 were never collected). With one deliberate exception — the four summary tables below, cached for reasons explained where they appear — every figure in this guide is fetched from the API at the moment the page is rendered, and the code chunk behind it is included (folded; click “Show the API call” to expand it). Nothing here is a static export: re-render this document tomorrow and, aside from the cached tables’ own noted refresh date, every number reflects whatever is live on the API.
NoteWhich corpus this rendering describes
Rendered 26 August 2026 against corpus vintage 12 August 2026 — pipeline commit d0cc982, schema version 7.
The corpus is a rolling latest: it is rebuilt when corrections land, and the API serves whatever was published most recently. So if a figure here disagrees with what the API returns for you today, check this stamp first — a difference of vintage is the ordinary explanation, and re-rendering the guide resolves it.
What it covers
The API covers government types 0 through 3 — state, county, municipality, and township. Special districts and school districts are not in the corpus. That matters early, because it changes how every later number should be read: a county’s “total spending” here is that county government’s own spending, not spending by the school district or utility district that also serves its residents.
The table below is the exception noted above: it is built from a cached summary rather than fetched live, because assembling it requires sweeping every government type for two fiscal years — roughly 460 paginated requests — which would make this page take the better part of an hour to render and would put real load on a production API for no benefit to the reader. The table shows how many governments of each type sit in the API’s registry today, and how many of them reported at least one dollar of spending or revenue in FY2022, the most recent census year (see “Reading a sample year” below for why FY2022 rather than FY2024 is the right denominator here).
Show the table code
o1_display <- o1 |>transmute(`Government type`= stringr::str_to_title(as.character(gov_type)),`In registry`= scales::comma(n_in_registry),`Reporting, FY2022`= scales::comma(n_reporting_2022),`% reporting`= scales::percent(pct_reporting, accuracy =0.1) )knitr::kable(o1_display, align ="lrrr",caption ="O1 — Governments in the registry vs. reporting in FY2022")
O1 — Governments in the registry vs. reporting in FY2022
Government type
In registry
Reporting, FY2022
% reporting
State
50
50
100.0%
County
3,061
3,025
98.8%
City
20,106
19,205
95.5%
Township
17,119
15,784
92.2%
Cached 2026-08-06. Scope: gov types 0-3, FY1967-2024 (no source data FY1968, FY1969).
Which total you mean
Every dollar figure in this guide follows one of two nested concept models. For spending, primary ⊂ direct ⊂ total: primary is spending on services, direct adds interest on long-term debt (Census’s own published “Direct Expenditure”), and total adds payments to other governments but is available on exactly one endpoint, the single-government detail route. For revenue, the pair is general ⊂ total, and general — Census’s published “General Revenue” — is the figure this guide uses throughout.
To make those definitions concrete, here is FY2022 spending (primary concept, the API’s default) and general revenue (general concept), summed across every reporting government of each type. As above, this is the cached summary, not a live call — the same 460-request sweep behind table O1 produced these totals too.
Show the table code
o2_display <- o2 |>transmute(`Government type`= stringr::str_to_title(as.character(gov_type)),`Spending, FY2022 (primary)`=usd_short(value) )knitr::kable(o2_display, align ="lr",caption ="O2 — Total spending, FY2022, primary concept, by government type")
O2 — Total spending, FY2022, primary concept, by government type
Government type
Spending, FY2022 (primary)
State
$2.00T
County
$489.35B
City
$689.00B
Township
$63.23B
Show the table code
o3_display <- o3 |>transmute(`Government type`= stringr::str_to_title(as.character(gov_type)),`Revenue, FY2022 (general)`=usd_short(value) )knitr::kable(o3_display, align ="lr",caption ="O3 — Total general revenue, FY2022, by government type")
O3 — Total general revenue, FY2022, by government type
Government type
Revenue, FY2022 (general)
State
$2.92T
County
$347.17B
City
$463.20B
Township
$51.38B
Cached 2026-08-06. Scope: gov types 0-3, FY1967-2024 (no source data FY1968, FY1969).
Reading a sample year — the year-selection rule
The Census of Governments is a complete census only in years ending in 2 or 7 — 2012, 2017, 2022. Every other year, including FY2024, is a sample. Large governments sit in a certainty stratum and are collected every year regardless of the cycle; small governments do not, and drop in and out of the corpus between census years. That single fact governs how every comparison in this guide picks its year.
ImportantThe rule
A figure whose denominator is “all units of type X” uses FY2022, the census year. A figure comparing named or population-matched units uses FY2024, the newest year available.
A national median, share, or count is only unbiased in a census year, because a sample year systematically under-represents small governments. A matched comparison of large or named units is sound in the newest year, because those units are exactly the ones the certainty stratum guarantees every year, census or not.
Table O4 is the evidence for this rule, not an assertion of it. It splits counties and cities into four population bands and shows, for each band, what share of the governments in it actually reported spending in FY2022 versus FY2024.
Counties with population under 50,000 go from 98.0% reporting in FY2022 to 42.2% in FY2024; counties over 1 million stay at 100.0% and 100.0% in both years. Cities under 50,000 go from 97.5% to 17.7%; cities over 1 million hold at 100.0% and 100.0%. The smallest band collapses. The largest band does not move.
O4 — Coverage by population band: FY2022 (census year) vs. FY2024 (sample year)
Government type
Population band
In band
FY2022 (n)
FY2022 (%)
FY2024 (n)
FY2024 (%)
Change (pts)
County
<50k
2,096
2,055
98.0%
885
42.2%
-55.8%
County
50k-250k
687
684
99.6%
591
86.0%
-13.5%
County
250k-1M
206
206
100.0%
206
100.0%
0.0%
County
>=1M
40
40
100.0%
40
100.0%
0.0%
City
<50k
18,553
18,091
97.5%
3,276
17.7%
-79.9%
City
50k-250k
704
701
99.6%
584
83.0%
-16.6%
City
250k-1M
75
75
100.0%
75
100.0%
0.0%
City
>=1M
10
10
100.0%
10
100.0%
0.0%
Cached 2026-08-06. Scope: gov types 0-3, FY1967-2024 (no source data FY1968, FY1969). Bolded changes are 30 percentage points or larger.
State view — access to healthcare
Every remaining section of this guide follows the same shape: a call (or a couple of calls) against the live API, a chart, and a short read-out of what the chart actually shows. This section works at the state level — government type 0 — using Health & Hospitals operating spending as a running example of “access to healthcare.” States are also the one layer where the year-selection rule above needs no asterisk: all 50 states sit in the certainty stratum, so a single FY2024 call already returns the complete fifty-state universe, sample year or not. That will stop being true once this guide reaches counties and cities.
S1 — revenue and operating spending, all fifty states
Two calls, joined on canonical_govid: general revenue per capita and expenditure per capita, both FY2024, summed across every category. Under the default expenditure_concept=primary this route uses, /spending’s spend_subtype field takes the values operations, capital, and assistance (verified live against all four government types); this chart keeps only operations after the fact — capital is lumpy, and one bond-funded hospital or prison can make a single ordinary year look like an outlier. (A fourth value, intergovernmental, is real too, but it only exists under expenditure_concept=total — see the caveat in the read-out below.)
Show the API call
spending_state <-cog_get_all("/spending", type ="state", years =2024, per_capita =TRUE)revenue_state <-cog_get_all("/revenue", type ="state", years =2024, per_capita =TRUE,revenue_concept ="general")
Show the chart code
ggplot(s1, aes(rev_pc, exp_pc)) +#geom_abline(slope = 1, intercept = 0, linetype = "dashed", colour = "grey60", linewidth = 0.4) +geom_smooth(aes(group = south, color = south), se =FALSE, method ="lm", linetype =2) +geom_point(aes(colour = south), size =3.2) +geom_text_repel(data =filter(s1, south), aes(label = state_abbr), colour = ACCENT, size =4.4,seed =42, segment.size =0.45, min.segment.length =0, max.overlaps =20 ) +scale_colour_manual(values =c(`TRUE`= ACCENT, `FALSE`= MUTED),labels =c(`TRUE`="South", `FALSE`="Rest of U.S."), name =NULL ) +scale_x_continuous(labels = scales::dollar_format()) +scale_y_continuous(labels = scales::dollar_format(), limits =c(0, NA)) +labs(title ="State government revenue vs. operating\nspending per capita, FY2024",x ="General revenue per capita", y ="Operating expenditure per capita" )
Figure 1: State general revenue vs. operating expenditure per capita, FY2024, all 50 states; Southern states highlighted.
Read-out. Southern states sit systematically in the lower-left of this chart, not scattered through it. On average the 16 states here collected $8,463.48 per person in general revenue and spent $5,972.25 on operations in FY2024; the other 34 states averaged $9,859.94 and $6,793.39 — roughly 16% more revenue and 14% more operating spending per person. Florida and Georgia are the two lowest-revenue states in the entire fifty-state universe, and 4 of the 5 lowest-revenue states are Southern. None of the top 5 — New Mexico, North Dakota, Vermont, Alaska, Hawaii — is: those are small-population states where one severance-tax or federal-transfer line item swings the per-capita figure a long way, which is a different phenomenon from a systematic regional pattern. One honest caveat about the reference line itself: almost no state, Southern or not, sits on or above it, because a large share of state general revenue funds aid to counties, cities, and school districts, and that money never shows up as operations spending here. It is not, however, a spend_subtype this chart filters out: intergovernmental is a real subtype, but it exists in this API only under expenditure_concept=total — a concept the flat /spending route doesn’t support at all (total is available on exactly one endpoint, the single-government /governments/{govid}/spending route; a request for it here is rejected with a 400). Under the default primary concept this chart uses, those transfer dollars are structurally absent from /spending’s response, not merely filtered out of it. The 45° line is a frame for comparing states to each other, not a claim that revenue should equal operating spending.
S2 — Health & Hospitals, ranked
/rollups?layer=state sums Health & Hospitals spending per capita for every state in one call — and because layer=state resolves to the complete fifty-state universe rather than a scoped subset, the median computed from this one call is a genuine national median. That will not be true once this guide reaches the county and city sections, where a rollup is scoped to whatever geography the request names (a state, say), not the whole country in one shot.
One wrinkle before the chart: the District of Columbia is not registered as a state-type government in this corpus — it carries govs_type 2, the same code used for cities — so it never appears in a layer=state rollup. Putting DC into a state-level comparison means a second, different call: looking DC up directly and pulling its numbers from the per-government /governments/{govid}/spending route instead.
ggplot(s2, aes(x = amt, y = label, fill = is_dc)) +geom_col(width =0.7) +geom_vline(xintercept = national_median, linetype ="dashed", colour ="grey30", linewidth =0.5) +scale_fill_manual(values =c(`TRUE`= ACCENT, `FALSE`= NAVY), guide ="none") +scale_x_continuous(labels = scales::dollar_format()) +labs(title ="Health & Hospitals operating spending\nper capita, FY2024",subtitle ="16 Southern states + DC, ranked;\ndashed line = median across all 50 states",x ="Operating expenditure per capita", y =NULL )
Figure 2: Health & Hospitals operating spending per capita, FY2024, 16 Southern states plus DC, ranked against the all-50-state median.
Read-out. DC is the clear outlier, exactly as flagged above: at $1,228.79 per capita it stands well above every state shown, including South Carolina ($1,155.00), the highest state on the list. DC’s population is a single, dense city government carrying state-like functions (including Medicaid), so the same health-spending dollar spreads over far fewer residents than it would in a full state — a mechanical effect of the denominator, not necessarily a difference in generosity. Leaving DC aside, the South is not uniformly low on this measure: 7 of the 16 states sit above the all-50 median of $602.29, while Louisiana ($260.59) anchors the bottom. Because layer=state resolves to the complete fifty-state universe in a single call, this median is the real thing — an honest national benchmark, not a sample-year estimate.
S3 — the long view, FY1972–FY2024
Same measure as S2, extended across time: adjust=real&base_year=2024 for constant dollars, and every available year instead of just FY2024.
NoteOmitting years does not behave the same way on every route
On the per-government routes (/spending, /revenue, /profile for one govid), leaving years off returns that government’s entire history — the opening page of this guide leans on exactly that behavior. /rollups is different: per its own openapi.json parameter description, this fleet route “does NOT default to the full corpus span” when years is omitted — it defaults to the latest published year, the same as S1 and S2 above (confirmed live before writing this chart, not assumed from the per-government behavior). Getting the full span here means asking for it explicitly, years=1967-2024.
ggplot() +vintage_rules() +geom_ribbon(data = nonsouth_band, aes(x = year, ymin = q25, ymax = q75),fill ="grey70", alpha =0.4) +geom_line(data = south_med, aes(x = year, y = median), colour = ACCENT, linewidth =1.0) +geom_line(data = named, aes(x = year, y = amt_per_capita_real, colour = gov_name),linewidth =0.8) +geom_text_repel(data = end_labels, aes(x = year, y = amt_per_capita_real, label = state_label, colour = gov_name),hjust =0, direction ="y", size =4.1, seed =1, segment.size =0.45, show.legend =FALSE ) +annotate("text", x =max(south_end$year) +2, y = south_end$median, label ="South median",colour = ACCENT, hjust =0, size =4.1, fontface ="bold") +scale_colour_manual(values = NAMED_COLORS, guide ="none") +scale_x_continuous(limits =c(1967, 2024+11), breaks =seq(1970, 2020, 10)) +scale_y_continuous(labels = scales::dollar_format()) +labs(title ="Health & Hospitals operating spending\nper capita, real FY2024 dollars",subtitle ="South median vs. non-South interquartile range, FY1972-FY2024",x =NULL, y ="Real 2024 $ per capita" ) +theme(plot.margin =margin(t =5.5, r =20, b =5.5, l =5.5))
Figure 3: Health & Hospitals operating spending per capita, real FY2024 dollars, South median vs. non-South interquartile range, FY1972-FY2024, with Kentucky, Texas, and California named for contrast.
Read-out. The story here is less “South vs. non-South” than the spread within the South. Kentucky — one of the first Southern states to expand Medicaid, in January 2014 — climbs from $516.47 in FY2012 to $1,083.01 in FY2024, by far the highest line on this chart, Southern or not. Texas, which has never expanded Medicaid, tracks close to the South median throughout and finishes FY2024 at $610.13. The South median itself ($523.23 in FY2024) sits modestly below both the non-South median ($618.08) and California ($663.23) in the most recent year — a real but not dramatic gap. Kentucky’s post-expansion trajectory looks nothing like Texas’s, and that split tracks a real, named policy choice rather than anything about how the series is assembled.
TipTableau: extracting this section’s data
For a state-level extract, pull /rollups?layer=state&category=Health%20%26%20Hospitals&years=2024&per_capita=true&expenditure_concept=direct (the call behind S2) and land .data in the workbook. The one consideration that bites at this level: DC carries govs_type 2, the same code used for cities, so it never appears in a layer=state response — S2 above resolves it only with a second, separate call, and an extract built on the rollup alone will silently omit it rather than show a $0 row. If DC belongs in a state-level workbook, union in that second source explicitly; don’t assume the rollup already covers it. Every other field in this section’s response is a flat, ordinary Tableau column.
County view — environmental justice
This section moves down to the county level — government type 1 — and follows a different thread than the state view’s health-access question: water and sewer infrastructure, the category of county spending most directly tied to environmental-justice questions about who gets clean water, functioning sewer service, and reliable solid-waste collection. Counties do not sit in the certainty stratum the way all fifty states do, so the year-selection rule from the opening page is back in full force: the all-county cross-sections below (C2, C3) use FY2022, the census year; the matched named-unit comparison (C1) uses FY2024. The section builds to Jefferson County, Alabama — home to Birmingham, and the site of the largest municipal bankruptcy in U.S. history, a bankruptcy driven by a sewer construction bond program — whose full FY1967–FY2024 financial history is this guide’s centerpiece (C4).
C1 — revenue and operating spending, large counties matched on population
Southern and non-Southern counties are matched here by a population threshold — every county with population_acs at or above 500,000 — rather than by rank. Rank-matching (the 40 largest Southern counties against the 40 largest non-Southern) was tried during design and rejected: it silently compares differently-sized places under the same “top 40” label, as the read-out below shows with the actual population figures. The threshold avoids that, at the cost of an uneven split between the two groups — sizes resolved below from the live registry, not assumed in advance.
One /profile call per county resolves both flows for FY2024 at once: general revenue from its flow == "revenue" rows, and operating expenditure from its flow == "expenditure" & subtype == "operations" rows — the same concept pair S1 used at the state level.
Figure 4: County government revenue vs. operating expenditure per capita, FY2024, all counties with population >=500,000; Southern counties highlighted, Jefferson County AL marked.
Read-out. The population threshold resolves to 41 Southern counties and 79 non-Southern counties clearing 500,000 population in FY2024 (120 total, one /profile call each) — and it is the right method, not merely a simpler one: rank-matching instead (top 40 vs. top 40) would have compared a Southern cohort bottoming out at a population of 539,557 against a non-Southern cohort bottoming out at 808,098 — visibly different-sized places under the same “top 40” label.
At the large-county level the regional gap itself runs the opposite direction from S1’s state-level finding: the 41 Southern counties here average $1,700.23 revenue and $1,890.08 operating spending per capita, against $1,142.58 and $1,485.70 for the 79 non-Southern counties — Southern large counties run 49% higher revenue and 27% higher operating spending, not lower. That reversal comes with its own caveat, the same shape as S1’s small-state one: 4 of the 5 highest-revenue Southern counties in this set — Montgomery County, MD, Fairfax County, VA, Anne Arundel County, MD, Baltimore County, MD — are wealthy Washington-DC-suburb counties that happen to fall inside the Census South region definition, not evidence of a general Southern pattern. Jefferson County itself sits at $1,362.45 revenue but only $604.74 operating spending per capita — one of the larger revenue-minus-operations gaps on the chart, and a first hint of where the rest of that money goes: C4 below traces a large share of it to debt service, not services.
One caveat carries through this chart and every other /profile-based revenue figure in this guide: general revenue resolves to own-source revenue only for a government whose intergovernmental aid sits on aggregate *89 codes, which M2 in the city section below demonstrates concretely and shows how to recover.
C2 — water and sewer capital investment, ranked (FY2022)
Two /rollups calls, one per category, summed per government: Water Utilities and Sewerage & Solid Waste, both subtype=capital, per_capita=true, years=2022, coverage=census. Capital, not operations — infrastructure investment (new and replacement pipe, treatment-plant construction) is the environmental-justice-relevant measure here, not the recurring cost of running what already exists.
ggplot(c2_top20, aes(x = total_pc, y = label)) +geom_col(fill = NAVY, width =0.7) +geom_vline(xintercept = c2_reporting_median, linetype ="dashed", colour ="grey30", linewidth =0.5) +scale_x_continuous(labels = scales::dollar_format()) +labs(title ="Water + sewer capital spending\nper capita, FY2022",subtitle ="Top 20 Southern counties; dashed line = median among\ncounties with any nonzero capital spending",x ="Capital spending per capita\n(Water Utilities + Sewerage & Solid Waste)", y =NULL )
Figure 5: Water Utilities + Sewerage & Solid Waste, capital spending per capita, FY2022, top 20 Southern counties.
provenance.coverage, printed for both calls — the single most valuable thing a Tableau user pulling .data alone would never see, and the reason FY2022 rather than FY2024 is the right year for this cross-section:
Show the table code
knitr::kable( c2_prov |>transmute(Category = category, Year = year,`Units reporting`= scales::comma(n_units_reporting),`Units expected`= scales::comma(n_units_expected),`Census year?`=ifelse(is_census_year, "Yes", "No") ),align ="lrrrl", caption ="provenance.coverage for both /rollups calls behind C2")
provenance.coverage for both /rollups calls behind C2
Category
Year
Units reporting
Units expected
Census year?
Water Utilities
2022
512
3,061
Yes
Sewerage & Solid Waste
2022
1,904
3,061
Yes
Read-out. 512 of 3,061 counties reported any Water Utilities activity in FY2022, and 1,904 reported any Sewerage & Solid Waste activity — both figures cover any subtype (operations included), a wider net than the capital-only, nonzero rows actually charted here, and worth keeping straight: “reporting” and “reporting a nonzero capital figure this year” are different denominators.
The chart’s dashed line is a third denominator again, narrower still: /rollups?...&subtype=capital returns only rows with a nonzero capital figure, so 707 is the count of counties with any water or sewer capital spending in FY2022, and $6.04 is the median among those counties — a real, useful benchmark for how far the top 20 outspend a typical investing county, but not a national figure despite the shorthand “median” label doing a lot of work. Padding the remaining counties in the registry with their true $0 (not dropping them, which is what a naive .data-only pull would effectively do) puts the actual national all-county median at $0.00: 76.9% of the nation’s 3,061 counties reported no water or sewer capital spending at all in FY2022. In a section about environmental justice that zero is arguably the more important number on this page — most U.S. counties make no water or sewer infrastructure investment in a typical year, and the minority that do are unevenly distributed both across time (the lumpiness described next) and across place, as the Jefferson County comparisons in C3 and C4 below make concrete for one specific county.
Capital spending is lumpy by nature — a county with an active bond-funded plant or pipe project shows up near the top of this ranking in the year the money moves, and drops out the next — so this single-year ranking is as much a snapshot of when counties are borrowing as of how much they ultimately invest; the ranking would look different in FY2017 or FY2024. Jefferson County itself, this section’s centerpiece, is not in the top 20 shown here: at $57.56 per capita it ranks 52 of the 372 Southern counties reporting any water or sewer capital activity in FY2022 — a modest single-year figure that gives no hint, on its own, of the decades-long construction boom C4 uncovers by looking at Jefferson’s own history rather than one cross-sectional year.
C3 — Jefferson County vs. its national peer cohort
/governments/011073160527/peers returns Jefferson’s national peer cohort — ten counties matched on population, drawn from anywhere in the country, not just the South — which is the mechanism for putting a Southern county against the rest of the nation rather than against other Southern counties. /peer-comparison?category=Sewerage%20%26%20Solid%20Waste&years=2022 then scores Jefferson against that cohort.
Show the API call
c3_peers <-cog_get("/governments/011073160527/peers")c3_comparison <-cog_get("/governments/011073160527/peer-comparison",category ="Sewerage & Solid Waste", years =2022)
Show the chart code
ggplot(c3_bars, aes(x = amt_per_capita_nominal, y = gov_label)) +geom_rect(data = c3_summary, aes(xmin = summary_p25, xmax = summary_p75), ymin =-Inf, ymax =Inf,inherit.aes =FALSE, fill ="grey85" ) +geom_vline(data = c3_summary, aes(xintercept = summary_p50), linetype ="dashed",colour ="grey40", linewidth =0.5 ) +geom_col(aes(fill = is_target), width =0.6) +facet_wrap(~subtype_label, scales ="free_x") +scale_fill_manual(values =c(`TRUE`= ACCENT, `FALSE`= MUTED), guide ="none") +scale_x_continuous(labels = scales::dollar_format()) +labs(title ="Jefferson County AL vs. its national peer cohort",subtitle ="Sewerage & Solid Waste spending per capita, FY2022\nshaded band = peer 25th-75th percentile, dashed line = peer median",x ="Spending per capita", y =NULL )
Figure 6: Jefferson County AL vs. its 10-county national peer cohort, Sewerage & Solid Waste spending per capita, FY2022.
Read-out. Filter on role before doing anything with this response: the summary_p25/summary_p50/summary_p75 rows are per-category, per-subtype quantiles across whichever peers actually reported that subtype — 4 of Jefferson’s 10 peers reported an operations figure, but only 1 reported a capital figure, so the two bands are built from different-sized, and not necessarily overlapping, sets of counties. They are not additive: adding the operations peer median ($42.39) to the capital peer median ($0.02) produces $42.41 as a “peer median total” — a real-looking number that describes no actual peer government, since the county at the operations median need not be the county at the capital median (and here the capital “median” is one peer’s single reported value, not a real distribution at all — the collapsed band in the left-hand (“Capital”) panel above is that fact rendered visible, not a chart defect). The one number that is legitimately additive here is Jefferson’s own: its real capital-plus-operations total, summed from its own two rows rather than from summary rows, is $198.24 per capita — because both halves describe the same government. On both measures the API’s own target_rank field marks Jefferson rank 1 on operations and rank 1 on capital — the highest per-capita spender in its own national peer cohort on both, so far as the thin capital sample can show.
C4 — the long view, FY1967–FY2024: the guide’s centerpiece
Everything above is a snapshot. This chart is Jefferson County’s own financial history across all 56 published fiscal years, FY1967 through FY2024 (FY1968 and FY1969 were never collected, as the read-out below notes) — the sewer construction boom that put the county on this guide’s map, and the debt service that followed it into the largest municipal bankruptcy in U.S. history (filed November 2011).
One thing has to be demonstrated before the chart makes sense: the interest series below does not exist under this guide’s every other example, because every other chart in this guide uses the API’s default expenditure_concept=primary, and interest on long-term debt is not part of primary — it is what directadds. The point is easiest to make concretely rather than by assertion:
Show the API call
c4_primary_check <-cog_get("/governments/011073160527/spending",category ="Interest on Debt", years =2010,expenditure_concept ="primary")
Requesting Jefferson County’s Interest on Debt for FY2010 — the peak year, verified below — under the default primary concept returns meta$total = 0: zero rows, not merely a small or suppressed one. direct is required to see this series exist at all, which is exactly why this example needs it rather than merely mentioning it.
ggplot(c4_series, aes(year, amt_per_capita_real, colour = series)) +vintage_rules() +geom_line(linewidth =0.9, na.rm =TRUE) +geom_text_repel(data = c4_end_labels, aes(label = series), hjust =0, direction ="y",size =4.1, seed =7, segment.size =0.45, show.legend =FALSE ) +scale_colour_manual(values = C4_COLORS, guide ="none") +scale_x_continuous(limits =c(1967, 2024+11), breaks =seq(1970, 2020, 10)) +scale_y_continuous(labels = scales::dollar_format()) +labs(title ="Jefferson County, AL: sewer spending\nand debt service",subtitle ="Real FY2024 dollars per capita, FY1967-FY2024,\ndirect expenditure concept",x =NULL, y ="Real 2024 $ per capita" ) +theme(plot.margin =margin(t =5.5, r =65, b =5.5, l =5.5))
Figure 7: Jefferson County, AL: sewer capital, sewer operations, and interest on debt, real FY2024 dollars per capita, FY1967-FY2024.
Read-out. The shape tells a two-part story, and the two parts are offset from each other by close to a decade. Sewer capital spending climbs to a sharp peak in FY2002 at $1,008.31 per capita real — the same year Jefferson County’s whole Sewerage & Solid Waste total (capital plus operations combined) also peaks, at $427,522,000 nominal county-wide, the figure this chart’s underlying data is verified against above — the construction boom that rebuilt Jefferson County’s sewer system under a federal consent decree and financed it with bond debt (later restructured into variable-rate warrants and interest-rate swaps) that eventually forced the county into bankruptcy. Interest on Debt does not peak with it: it keeps climbing for another eight years, past the 2002 construction peak, to its own high point in FY2010 at $559.82 per capita real ($256,379,000 nominal that year) — those swaps reset against the county after the 2008 financial crisis, so debt service cost peaked years after debt proceeds stopped buying new pipe. The county filed for bankruptcy the following year. By FY2024 interest has fallen back to $142.49 per capita real ($94,814,000 nominal) — still a substantial ongoing cost, post-restructuring, but well off its peak. Two honest gaps in the picture: FY1968-1969 have no published source data for any of these three series (a known corpus limitation), and Jefferson County specifically has no reported capital figure for FY2012, the year immediately following its bankruptcy filing — geom_line() draws straight across both gaps rather than marking a break, so no year-over-year change should be read across exactly those points.
The teaching point, made explicit. This chart could not be built under expenditure_concept=primary, the default every other example in this guide uses — the demonstration above showed the API returning zero rows for Interest on Debt under primary, not merely a warning that it might be thin. The concept model this guide opened with — primary ⊂ direct ⊂ total — is not a technicality here: an analyst who never reads past the default concept would produce a Jefferson County sewer story with no debt service in it at all, missing the single fact that explains why Jefferson County is a bankruptcy case study rather than an ordinary infrastructure-spending example.
TipTableau: extracting this section’s data
For a county-level extract, pull /rollups?layer=county&category=Water%20Utilities&years=2022&coverage=census&subtype=capital&per_capita=true (one of the two calls behind C2) and land .data in the workbook. The one consideration that bites at this level: a subtype-filtered rollup returns only counties with a nonzero figure, so the 2,354 counties that spent $0 on water/sewer capital in FY2022 are simply absent from the extract rather than present as zero rows — C2’s read-out shows what that does to a naive average. Pad the extract against a full /governments?type=county pull before computing any average or median in the workbook, exactly as C2 does with county_registry. Skipping that step is the most common way a Tableau county map ends up overstating typical county spending.
City view — economic security
This final section moves to the city level — government type 2 — for a running theme of economic security: whether large cities support residents through hardship and house them, measured through Public Welfare (cash assistance, general relief, and other social services) and Housing & Community Development spending. Cities vastly outnumber the counties and states examined above — the cached O1 sweep at the top of this guide counted 20,106 city-type governments in the registry (this section does not repeat that sweep live) — so the population threshold C1 used for counties returns here at a lower cutoff: every city with population_acs at or above 250,000. As with the county section, the named/matched-unit charts (M1, M3) use FY2024 per the year-selection rule from the opening page. The section closes on Atlanta, Georgia (132121194678) — this guide’s second and final centerpiece government, and the subject of M2, which this guide considers its single best demonstration of what separates this API from a bare number lookup.
M1 — revenue and operating spending, large cities matched on population
Same method as C1: every city with population_acs at or above 250,000, split on is_south(), one /governments/{id}/profile call per city resolving both flows for FY2024 at once — general revenue from its flow == "revenue" rows, operating expenditure from its flow == "expenditure" & subtype == "operations" rows.
Figure 8: City government revenue vs. operating expenditure per capita, FY2024, all cities with population >=250,000; Southern cities highlighted, Atlanta marked.
Read-out. The threshold resolves to 85 cities clearing 250,000 population in FY2024 — 30 Southern, 55 non-Southern, one /profile call each. The regional gap runs the same direction it did among large counties (C1), not the state-level direction S1 found: Southern cities here average $3,035.24 revenue and $3,671.96 operating spending per capita, against $2,834.02 and $3,462.20 for non-Southern cities — 7% more revenue and 6% more operating spending. That is the same direction as C1’s county-level finding (49% and 27%), though a substantially narrower gap at the city level.
One caveat carries through this whole comparison: general revenue via /profile is effectively own-source revenue only for a government whose intergovernmental aid sits on aggregate *89 codes, so the gap above is a South-vs-non-Southern own-source comparison, not a total-general-revenue one. M2, immediately below, demonstrates exactly what that excludes for Atlanta and how to recover it.
Three points sit well outside the main cluster and are not part of that regional pattern. Washington DC — $18,061.40 revenue, $26,487.15 operating spending per capita — is the same outlier S2 already flagged at the state level: a single government carrying state-like functions for a comparatively small population, so the same dollar concentrates over far fewer residents. It reappears here because DC is registered as a city-type government (govs_type 2), the fact S2 established when it looked DC up directly. San Francisco ($15,101.56) and New York City ($10,552.76) sit in similar territory for a different, non-Southern reason: both are consolidated city-county governments whose “city” finances cover functions an ordinary municipality splits across a separate county layer. None of the three is Southern, so leaving them in does not change the direction of the regional finding above — it only makes the remaining 82 cities’ cluster hard to read at this scale, which is why the chart shows all 85 rather than hiding any of them. Atlanta itself sits close to the center of the Southern cluster, at $4,547.40 revenue and $4,096.94 operating spending per capita — an unremarkable city on this particular measure, which is exactly what makes M2’s finding, four sections below, worth reading: nothing on this chart would predict it.
M2 — Atlanta’s FY2022 general revenue: reported vs. recovered
Atlanta is this guide’s other centerpiece, chosen for a single demonstration: what happens when the concept this guide has used for every revenue figure so far — revenue_concept=general — quietly excludes real money by design, and how the API itself signals that it did.
For a large city like Atlanta, Census reports most intergovernmental revenue on aggregate *89 item codes — combined federal, state, or local aid lines that cannot be reliably attributed to one harmonized category — rather than on individual per-program codes. The general concept excludes those aggregate rows by design. The practical effect: a request for Atlanta’s general revenue, broken out by category, returns real dollars for property tax, other taxes, current charges, and miscellaneous revenue, and nothing at all for any intergovernmental category, even though Atlanta plainly receives federal, state, and local aid. This example uses FY2022 throughout — the year this guide’s verified recovery figures below are pinned to.
Show the API call
m2_own <-cog_get(paste0("/governments/", ATLANTA_ID, "/revenue"),revenue_concept ="general", years =2022, per_capita =TRUE)
Requesting each intergovernmental category directly, for the same government and year, confirms the gap and reveals the fix:
Show the API call
m2_ig_federal_demo <-cog_get(paste0("/governments/", ATLANTA_ID, "/revenue"),revenue_concept ="general", years =2022, category ="IG Federal")m2_ig_state_demo <-cog_get(paste0("/governments/", ATLANTA_ID, "/revenue"),revenue_concept ="general", years =2022, category ="IG State")m2_ig_local_demo <-cog_get(paste0("/governments/", ATLANTA_ID, "/revenue"),revenue_concept ="general", years =2022, category ="IG Local")
All three categories come back with zero rows of data — and a suggestions payload, every time. This is the payload itself, not a paraphrase of it:
Show the table code
knitr::kable( m2_suggestions |>transmute(Category = category, `Recipe ID`= recipe_id, Trigger = trigger,`Suppressed amount`=fmt_usd(suppressed_amount),`Suppressed year`= suppressed_years, Hint = hint ),align ="llllrl",caption ="The API's own `suggestions` payload for Atlanta's three empty IG categories, FY2022")
The API’s own suggestions payload for Atlanta’s three empty IG categories, FY2022
Category
Recipe ID
Trigger
Suppressed amount
Suppressed year
Hint
IG Federal
ig_federal_b89_wide
empty_year
$94,119,000
2022
re-run with recipe = ‘ig_federal_b89_wide’
IG Federal
ig_federal_total_wide
empty_year
$94,119,000
2022
re-run with recipe = ‘ig_federal_total_wide’
IG State
ig_state_total_wide
empty_year
$72,974,000
2022
re-run with recipe = ‘ig_state_total_wide’
IG State
ig_state_c89_wide
empty_year
$72,974,000
2022
re-run with recipe = ‘ig_state_c89_wide’
IG Local
ig_local_d89_wide
empty_year
$225,726,000
2022
re-run with recipe = ‘ig_local_d89_wide’
IG Local
ig_local_total_wide
empty_year
$225,726,000
2022
re-run with recipe = ‘ig_local_total_wide’
Each category comes back with two candidate recipes rather than one. The narrow *89_wide pulls the aggregate *89 code directly instead of trying to attribute it to a category; the broader *_total_wide takes the whole prefix family. For Atlanta in FY2022 the two recover the same dollars, because *89 is the only code of its family this return carries — on a government that still reports per-function detail they would diverge, and the choice would be yours to make. Every row carries the suppressed_amount this city’s own FY2022 return holds with no home in a category-based query.
Taking the narrow recipe in each case recovers real dollars:
ggplot(m2, aes(x = amt_nominal, y =reorder(leg, amt_nominal))) +geom_col(aes(fill = group), width =0.6) +geom_text(aes(label =usd_short(amt_nominal)), hjust =-0.15, size =4.6) +facet_wrap(~group, scales ="free", ncol =1) +scale_fill_manual(values =c(`Reported directly`= NAVY, `Recovered via recipe`= ACCENT), guide ="none") +scale_x_continuous(labels = usd_short, expand =expansion(mult =c(0.02, 0.28))) +labs(title ="Atlanta's FY2022 general revenue:\nreported vs. recovered",subtitle ="Own-source (reported directly) vs. the three\nintergovernmental legs (recovered via recipe)",x ="Nominal $", y =NULL )
Figure 9: Atlanta, GA: FY2022 general revenue, own-source (reported directly) vs. the three intergovernmental legs (recovered via recipe).
Read-out. The trap is real and, as suspected, systematic rather than a one-off: all three intergovernmental categories return zero rows under revenue_concept=general and exactly one suggestions row apiece, each naming a different wide recipe for the same reason — the money sits on an aggregate *89 code the harmonized general concept excludes by design. Fetching each recipe reproduces this guide’s verified figures exactly: $94,119,000 in federal aid, $72,974,000 in state aid, and $225,726,000 in local aid (mostly aid from other local governments, per Census’s own *89 convention).
None of those three dollars appears anywhere in the general-concept, category-broken-out response this guide’s every other revenue chart relies on. An analyst who trusted that response at face value would report Atlanta’s FY2022 general revenue as $1,627,842,000, own-source only — short $392,819,000, or 19.4% of Atlanta’s true $2,020,661,000, not because the money doesn’t exist but because it lives on a code family one concept-level query cannot see. This is the single clearest demonstration in this guide of what separates this API from a bare number lookup: when a number is incomplete, it does not just return a smaller number, it says so, by name, with the exact fix attached.
M3 — Public Welfare and Housing & Community spending, the Southern 30
Back to this section’s threshold set: Public Welfare and Housing & Community Development spending per capita, FY2024, across the 30 Southern cities M1 identified above, category totals (operations plus capital, where both exist). Two categories only, so the plain qualitative treatment — not the grey-and-highlight M1 needed for 85 series — is the right tool here.
Show the API call
m3_pw <-cog_get_all("/spending", type ="city", category ="Public Welfare",years =2024, per_capita =TRUE)m3_hc <-cog_get_all("/spending", type ="city", category ="Housing & Community",years =2024, per_capita =TRUE)
Show the chart code
ggplot(m3, aes(x = pc, y = label, fill = category)) +geom_col(position =position_dodge(width =0.75), width =0.7) +scale_fill_manual(values =c("Public Welfare"= ACCENT, "Housing & Community"= NAVY), name =NULL) +scale_x_continuous(labels = scales::dollar_format()) +labs(title ="Public Welfare + Housing & Community\nspending per capita, FY2024",subtitle ="29 Southern cities (pop >=250,000);\nDC excluded from this chart, see read-out",x ="Spending per capita", y =NULL ) +theme(legend.position ="top", legend.location ="plot",legend.justification.top ="left")
Figure 10: Public Welfare + Housing & Community spending per capita, FY2024, 29 of the 30 Southern cities with population >=250,000; DC excluded, see read-out.
Read-out. Housing & Community coverage is complete — all 30 of the 30 Southern cities report a figure — but Public Welfare is not: only 16 of 30 do. That split is worth reading as a real institutional fact rather than a data gap: in much of the country, cash assistance and general relief are administered by a county or state government, not a city one, so a city with no reported Public Welfare figure here is plausibly a city that does not run that program directly, not one this corpus failed to capture.
Washington DC does not appear on the chart above for a familiar reason: at $8,663.95 Public Welfare and $2,261.22 Housing & Community per capita, DC dwarfs every other Southern city on both measures — the same state-like-function effect M1’s read-out and S2 both already flagged, now visible in a second, unrelated category pair. Leaving it on the chart would have compressed the other 29 cities into an unreadable sliver at the left edge, so it is reported here in text rather than hidden from the reader: the underlying fetch still includes it, and the 30-of-30 count above counts DC too.
Among the remaining 29, New Orleans’s $910.05 Housing & Community figure is the highest on the chart, well ahead of the rest of the field. Atlanta’s own profile is lopsided in the opposite direction from most of its peers: its Public Welfare figure ($119.40) ranks 3 of the 15 Southern cities that report one at all — behind only Virginia Beach ($164.64) and San Antonio ($134.82) — while its Housing & Community figure ($14.39) sits near the very bottom of the same 29-city set. Atlanta leans on one half of this section’s economic-security pair far more than the other, a pattern this chart alone can show but not explain.
M4 — Atlanta vs. its national peer cohort: Public Welfare spending
/governments/{id}/peers returns Atlanta’s national peer cohort — ten cities matched on population, drawn from anywhere in the country — the same mechanism C3 used to put Jefferson County against the nation rather than other Southern counties. /peer-comparison?category=Public%20Welfare&years=2024 then scores Atlanta against that cohort on this section’s own theme category.
ggplot(m4_bars, aes(x = amt_per_capita_nominal, y = gov_label)) +geom_rect(data = m4_summary, aes(xmin = summary_p25, xmax = summary_p75), ymin =-Inf, ymax =Inf,inherit.aes =FALSE, fill ="grey85" ) +geom_vline(data = m4_summary, aes(xintercept = summary_p50), linetype ="dashed",colour ="grey40", linewidth =0.5 ) +geom_col(aes(fill = is_target), width =0.6) +scale_fill_manual(values =c(`TRUE`= ACCENT, `FALSE`= MUTED), guide ="none") +scale_x_continuous(labels = scales::dollar_format()) +labs(title ="Atlanta vs. its national peer cohort:\nPublic Welfare spending",subtitle ="Per capita, FY2024; shaded band = peer 25th-75th percentile,\ndashed line = peer median",x ="Spending per capita", y =NULL )
Figure 11: Atlanta, GA vs. its national peer cohort, Public Welfare spending per capita, FY2024.
Read-out. As with Jefferson County in C3 above, filter this response on role before using it. The same partial-role-coverage pattern C3 found recurs here, in a milder form: there, capital reporting thinned to a single peer out of ten; here, 3 of Atlanta’s 10 national peers reported a Public Welfare figure at all in FY2024 (provenance.coverage: 3 of 10) — less extreme than C3’s thinnest case, but the same underlying lesson: a peer cohort’s size and its reporting coverage are two different numbers, and only the second one tells you how much of the response you can actually use. The other 7 peers — Colorado Springs, Mesa, Omaha, Raleigh, Fresno, Tucson, and Long Beach — simply have no Public Welfare row in this response; the most plausible reading, consistent with M3’s finding above, is that most of them do not administer this program at the city level at all, not that the corpus is missing their data.
Atlanta’s own $119.40 per capita ranks 2 of the 4 reporting governments (target included) — behind only Virginia Beach, and well above both Sacramento and Kansas City. The reporting peer median itself, $11.86, is of limited use as a benchmark with a cohort this thin: it is pulled down by the two low peers and says little about the “typical” peer city on this measure. Atlanta’s rank against the three actual peers is the more honest read of this chart than any single summary statistic drawn from them.
M5 — the long view, FY1967–FY2024: operations vs. capital
The city section closes, like the county section did, on one government’s full history — Atlanta’s own spending across all 56 published fiscal years (FY1967 through FY2024, minus FY1968-1969, which were never collected — see M5’s gate below), this time not one category but the two broadest expenditure subtypes summed across every category: operations against capital, real per capita.
knitr::kable( m5_cap_peak_detail |>transmute(Category = category, `FY2007 capital ($)`=fmt_usd(amt_nominal),`Item codes`= codes_included),align ="lrl", caption ="Atlanta's capital spending by category, FY2007 -- the peak year")
Atlanta’s capital spending by category, FY2007 – the peak year
Category
FY2007 capital ($)
Item codes
Other Transportation
$435,775,000
F01,G01
Water Utilities
$313,671,000
F91,G91
Sewerage & Solid Waste
$211,524,000
F80,G80,G81
General Government
$70,928,000
F29,F89,G23,G29,G89
Parks & Recreation
$27,965,000
F61,G61
Highways
$25,274,000
F44,G44
Police
$8,216,000
G62
Housing & Community
$6,632,000
F50,G50
Fire
$3,349,000
F24,G24
Judicial & Legal
$100,000
G25
Show the chart code
ggplot(m5, aes(year, pc, colour = series)) +vintage_rules() +geom_line(linewidth =0.9, na.rm =TRUE) +geom_text_repel(data = end_labels, aes(label = series), hjust =0, direction ="y",size =4.1, seed =7, segment.size =0.45, show.legend =FALSE ) +scale_colour_manual(values =c("Operations"= NAVY, "Capital"= ACCENT), guide ="none") +scale_x_continuous(limits =c(1967, 2024+8), breaks =seq(1970, 2020, 10)) +scale_y_continuous(labels = scales::dollar_format()) +labs(title ="Atlanta: operations vs. capital spending",subtitle ="Real FY2024 dollars per capita, FY1967-FY2024,\nsummed across every category",x =NULL, y ="Real 2024 $ per capita" ) +theme(plot.margin =margin(t =5.5, r =55, b =5.5, l =5.5))
Figure 12: Atlanta, GA: operations vs. capital spending, real FY2024 dollars per capita, FY1967-FY2024.
Read-out. Operations climbs almost without interruption across the whole series and reaches its all-time high in FY2024, $4,096.94 per capita real — the identical figure M1 computed independently above for the same government, flow, subtype, and year, a useful cross-check that the two very differently-shaped queries behind M1 and M5 agree with each other.
Capital tells a different story: a sharp, sustained peak from the early 2000s through 2010, topping out in FY2007 at $3,432.12 per capita real — roughly 15x FY2024’s capital figure of $221.87. The category breakdown table above shows what built that peak: the top three categories alone — Other Transportation ($435,775,000, item codes F01,G01, Census’s Air Transportation construction and capital-outlay codes — airport spending, folded into this harmonized “Other Transportation” category), Water Utilities ($313,671,000), and Sewerage & Solid Waste ($211,524,000) — account for 87.1% of that year’s total capital spending. That mix — a major airport expansion alongside a multi-year water and sewer rebuild — is consistent with Atlanta’s own well-documented Hartsfield-Jackson modernization and a federally mandated sewer overhaul that ran through the same decade, the same kind of infrastructure-and-consent-decree story C4 told for Jefferson County, here playing out one government layer up and a few years later. After 2011 capital falls sharply and stays low through the end of the series, while operations keeps climbing — the two series cross and re-cross several times in the 2000s and settle, by FY2024, into operations running roughly 18x capital. One honest gap: FY1968-1969 have no published source data for either series here, the same known corpus limitation C4 flagged for Jefferson County; geom_line() draws straight across it rather than marking a break.
TipTableau: extracting this section’s data
For a city-level extract, pull /revenue?type=city&revenue_concept=general&years=2024&per_capita=true and land .data in the workbook. The one consideration that bites at this level: revenue_concept=general excludes aggregate *89 intergovernmental codes by design, so a citywide extract built this way understates every city’s revenue the same way M2 shows it understating Atlanta’s alone — by a nontrivial share, not a rounding error. M2’s suggestions payload names the exact recipe fix per category and government, but that payload does not travel with a flat multi-city .data extract, so recovering IG revenue for a whole fleet of cities means a second, per-government pass, not a single query. Budget for that second pass before a Tableau workbook promises “total” city revenue.
Building this in Tableau
Every chart in this guide is fetched live and rendered in R, but the same API is also a clean source for a Tableau workbook: page through .data, land it in an extract, and build from there. The three boxes above cover what bites at each geography level; two more considerations apply to any workbook built this way, regardless of level.
provenance does not survive a .data-only extract. Every response’s provenance block — coverage counts, the census-year flag, corpus break references — sits alongside .data, not inside it, so a workbook wired to .data alone drops it entirely, along with the audit trail C2 above builds directly from provenance.coverage. Six months from now, that workbook can no longer answer “where did this number come from” or “was this a complete population,” even though the live API still can. /rollups responses are the one exception: /rollups also mirrors its coverage block into meta, and an extract built to include meta alongside .data — not .data alone — keeps that disclosure. /spending, /revenue, and the per-government routes have no such mirror.
summary_p25/summary_p50/summary_p75 rows must never be SUMmed. C3 and M4 above both use these rows — they arrive in .data as ordinary rows, indistinguishable from a real government’s spending except by the role field, so a Tableau calculated field or a careless SUM() that doesn’t filter on role first will silently fold a peer-cohort quantile into a total it does not belong in. Filter on role before summing anything, and leave the summary_p* rows out of any additive calculation entirely — C3’s read-out shows concretely what a naive sum of two summary rows produces: a real-looking number that describes no actual government.
Known limitations
That is worth stating plainly rather than burying in a footnote: the API surface this guide documents is actively maintained, not merely described as it happened to be found.
Behaviour
Status
Workaround
summary_p* rows are per-category quantiles, not additive
Live — documented, role is the tell
Filter on role before aggregating anything; never sum summary_p25/summary_p50/summary_p75 rows — see the Tableau note above and C3’s read-out for a worked example.
provenance discarded by a .data-only extract
Live — inherent to BI extracts; use meta where mirrored
Include meta alongside .data in any BI extract; /rollups mirrors coverage into meta, but /spending, /revenue, and the per-government routes do not.
Local-government IG revenue sits on aggregate rows
By design — recipes recover it and suggestions names them
Fetch the suggestions-named recipe for each intergovernmental category rather than trusting a general-concept, category-broken-out response alone — M2 above walks through the fix for one government.