Public API
Developers and journalists migrating from OpenSecrets or ProPublica APIs can use this static
reference to find Civibus's nonpartisan, source-linked federal public-record endpoints.
FastAPI router owner: /public/v1; Caddy public URL prefix: /api/public/v1.
Endpoint reference
GET /api/public/v1/federal/officials
Parameters: chamber, state, party.
Curl
: "${CIVIBUS_PUBLIC_API_BASE:?Set CIVIBUS_PUBLIC_API_BASE to a Civibus origin that serves /api}" && curl "${CIVIBUS_PUBLIC_API_BASE}/api/public/v1/federal/officials?state=NC&chamber=House"
Sample JSON
[
{
"person_id": "11111111-1111-1111-1111-111111111111",
"person_name": "Sample Official",
"officeholding_id": "22222222-2222-2222-2222-222222222222",
"office_id": "33333333-3333-3333-3333-333333333333",
"office_name": "U.S. House NC-01",
"chamber": "House",
"state": "NC",
"district": "01",
"district_or_class": "01",
"party": "Independent",
"portrait_source_image_url": "https://www.congress.gov/img/member/sample.jpg",
"person_detail_path": "/person/11111111-1111-1111-1111-111111111111"
}
]
GET /api/public/v1/federal/officials/{person_id}/money
Parameters: none beyond person_id in the path.
Every money field is nullable — the fundraising fields (total_raised, total_spent, net, cash_on_hand, summary_source) and the outside-spending fields (ie_support_total, ie_oppose_total, ie_support_count, ie_oppose_count). A null value means the figure is unknown and never means zero: the official has no linked FEC candidate, or the FEC filings for the selected cycle were never loaded. A fundraising_coverage / ie_coverage block accompanies every non-populated state and says why. A candidate whose loaded filings genuinely total nothing still sends "0.00" — the coverage state, never the number, says which is which.
Curl
: "${CIVIBUS_PUBLIC_API_BASE:?Set CIVIBUS_PUBLIC_API_BASE to a Civibus origin that serves /api}" && curl "${CIVIBUS_PUBLIC_API_BASE}/api/public/v1/federal/officials/11111111-1111-1111-1111-111111111111/money"
Sample JSON
{
"person_id": "11111111-1111-1111-1111-111111111111",
"person_name": "Sample Official",
"has_fec_money": true,
"candidate_id": "44444444-4444-4444-4444-444444444444",
"total_raised": "125000.00",
"total_spent": "100000.00",
"net": "25000.00",
"cash_on_hand": "45000.00",
"summary_source": "fec_weball",
"ie_support_total": "5000.00",
"ie_oppose_total": "0.00",
"ie_support_count": 2,
"ie_oppose_count": 0,
"sources": [
{
"domain": "campaign_finance",
"jurisdiction": "federal",
"data_source_name": "FEC candidate master",
"data_source_url": "https://www.fec.gov/data/browse-data/?tab=candidates",
"source_record_key": "H4NC00000",
"record_url": "https://www.fec.gov/data/candidate/H4NC00000/",
"pull_date": "2026-07-10T00:00:00Z"
}
]
}
Sample JSON (money not loaded)
{
"person_id": "66666666-6666-6666-6666-666666666666",
"person_name": "Sample Official Without Loaded Filings",
"has_fec_money": false,
"candidate_id": null,
"total_raised": null,
"total_spent": null,
"net": null,
"cash_on_hand": null,
"summary_source": null,
"fundraising_coverage": {
"activity_state": "not_loaded",
"completeness": "unknown",
"basis": "no_authoritative_load_evidence"
},
"ie_support_total": null,
"ie_oppose_total": null,
"ie_support_count": null,
"ie_oppose_count": null,
"ie_coverage": {
"activity_state": "not_loaded",
"completeness": "unknown",
"basis": "no_authoritative_load_evidence"
},
"sources": []
}
GET /api/public/v1/federal/officials/{person_id}/contributors
Parameters: none beyond person_id in the path.
Curl
: "${CIVIBUS_PUBLIC_API_BASE:?Set CIVIBUS_PUBLIC_API_BASE to a Civibus origin that serves /api}" && curl "${CIVIBUS_PUBLIC_API_BASE}/api/public/v1/federal/officials/11111111-1111-1111-1111-111111111111/contributors"
Sample JSON
{
"person_id": "11111111-1111-1111-1111-111111111111",
"contributors": [
{
"name": "Sample Contributor",
"total_amount": "5000.00",
"transaction_count": 3
}
],
"sources": [
{
"domain": "campaign_finance",
"jurisdiction": "federal",
"data_source_name": "FEC itemized individual contributions",
"data_source_url": "https://www.fec.gov/data/receipts/individual-contributions/",
"source_record_key": "H4NC00000",
"record_url": "https://www.fec.gov/data/candidate/H4NC00000/",
"pull_date": "2026-07-10T00:00:00Z"
}
]
}
GET /api/public/v1/federal/officials/{person_id}/employers
Parameters: none beyond person_id in the path.
Curl
: "${CIVIBUS_PUBLIC_API_BASE:?Set CIVIBUS_PUBLIC_API_BASE to a Civibus origin that serves /api}" && curl "${CIVIBUS_PUBLIC_API_BASE}/api/public/v1/federal/officials/11111111-1111-1111-1111-111111111111/employers"
Sample JSON
{
"person_id": "11111111-1111-1111-1111-111111111111",
"employers": [
{
"employer": "Unclassified / not provided",
"total_amount": "29150.00",
"transaction_count": 85,
"industry": "UNKNOWN_INDUSTRY"
}
],
"classified_count": 837,
"unknown_count": 13487,
"sampled_coverage_percentage": "5.843340",
"sources": [
{
"domain": "campaign_finance",
"jurisdiction": "federal",
"data_source_name": "FEC itemized individual contributions",
"data_source_url": "https://www.fec.gov/data/receipts/individual-contributions/",
"source_record_key": "H4NC00000",
"record_url": "https://www.fec.gov/data/candidate/H4NC00000/",
"pull_date": "2026-07-10T00:00:00Z"
}
]
}
GET /api/public/v1/federal/export.json
Parameters: none.
Rows use the same nullable-money contract as the per-official money endpoint: officials whose money is unknown appear with null totals and a fundraising_coverage / ie_coverage block saying why, never with fabricated zeros.
Curl
: "${CIVIBUS_PUBLIC_API_BASE:?Set CIVIBUS_PUBLIC_API_BASE to a Civibus origin that serves /api}" && curl "${CIVIBUS_PUBLIC_API_BASE}/api/public/v1/federal/export.json"
Sample JSON
[
{
"person_id": "11111111-1111-1111-1111-111111111111",
"person_name": "Sample Official",
"has_fec_money": true,
"candidate_id": "44444444-4444-4444-4444-444444444444",
"total_raised": "125000.00",
"total_spent": "100000.00",
"net": "25000.00",
"cash_on_hand": "45000.00",
"summary_source": "fec_weball",
"ie_support_total": "5000.00",
"ie_oppose_total": "0.00",
"ie_support_count": 2,
"ie_oppose_count": 0,
"sources": [
{
"domain": "campaign_finance",
"jurisdiction": "federal",
"data_source_name": "FEC candidate master",
"data_source_url": "https://www.fec.gov/data/browse-data/?tab=candidates",
"source_record_key": "H4NC00000",
"record_url": "https://www.fec.gov/data/candidate/H4NC00000/",
"pull_date": "2026-07-10T00:00:00Z"
}
]
}
]
GET /api/public/v1/federal/export.csv
Parameters: none.
The money columns write an empty cell when the value is unknown — an empty cell never means zero. The CSV carries no coverage columns; consult export.json's fundraising_coverage / ie_coverage blocks for why a value is unknown.
Curl
: "${CIVIBUS_PUBLIC_API_BASE:?Set CIVIBUS_PUBLIC_API_BASE to a Civibus origin that serves /api}" && curl -L "${CIVIBUS_PUBLIC_API_BASE}/api/public/v1/federal/export.csv" -o civibus_federal_money.csv
Sample CSV
person_id,person_name,has_fec_money,candidate_id,total_raised,total_spent,net,cash_on_hand,summary_source,ie_support_total,ie_oppose_total,ie_support_count,ie_oppose_count,source_urls
11111111-1111-1111-1111-111111111111,Sample Official,true,44444444-4444-4444-4444-444444444444,125000.00,100000.00,25000.00,45000.00,fec_weball,5000.00,0.00,2,0,https://www.fec.gov/data/candidate/H4NC00000/
66666666-6666-6666-6666-666666666666,Sample Official Without Loaded Filings,false,,,,,,,,,,,
GET /api/public/v1/federal/metadata
Parameters: none.
Curl
: "${CIVIBUS_PUBLIC_API_BASE:?Set CIVIBUS_PUBLIC_API_BASE to a Civibus origin that serves /api}" && curl "${CIVIBUS_PUBLIC_API_BASE}/api/public/v1/federal/metadata"
Sample JSON
{
"data_sources": [
{
"data_source_id": "55555555-5555-5555-5555-555555555555",
"domain": "campaign_finance",
"jurisdiction": "federal/fec",
"name": "FEC bulk data",
"source_url": "https://www.fec.gov/data/browse-data/",
"update_frequency": "weekly",
"last_pull_at": "2026-07-20T09:00:00Z",
"last_pull_status": "success",
"record_count": 542,
"latest_source_record_id": null,
"latest_source_record_key": null,
"latest_source_record_url": null,
"latest_source_pull_date": "2026-07-20T09:00:00Z"
}
],
"rate_limit": {
"max_requests": 100,
"window_seconds": 60
},
"coverage": {
"current_officeholder_count": 543,
"officeholder_denominator_is_fixed": false,
"employer_industry": {
"classified_count": 837,
"unknown_count": 13487,
"sampled_coverage_percentage": "5.843340"
},
"donor_identity_resolution": "unresolved"
}
}
CSV columns
person_idperson_namehas_fec_moneycandidate_idtotal_raisedtotal_spentnetcash_on_handsummary_sourceie_support_totalie_oppose_totalie_support_countie_oppose_countsource_urls
OpenSecrets and ProPublica migration mapping
| Source API and endpoint/product | Civibus equivalent | Honest delta |
|---|
| ProPublica Congress API members | GET /api/public/v1/federal/officials | Current federal officeholders only; no historical membership or legislative activity. |
| OpenSecrets API candSummary | GET /api/public/v1/federal/officials/{person_id}/money | FEC summary totals and Schedule E support or opposition, keyed by Civibus person_id. |
| OpenSecrets API candContrib | GET /api/public/v1/federal/officials/{person_id}/contributors | Aggregated contributor names from itemized FEC receipts; donor identities remain unresolved. |
| OpenSecrets API candIndustry | GET /api/public/v1/federal/officials/{person_id}/employers | Employer rollups disclose sparse industry classification and do not reproduce OpenSecrets categories. |
| OpenSecrets bulk candidate summaries (JSON) | GET /api/public/v1/federal/export.json | Current federal officeholders with FEC summaries and Schedule E totals; not a full OpenSecrets bulk mirror. |
| OpenSecrets bulk candidate summaries (CSV) | GET /api/public/v1/federal/export.csv | The same bounded Civibus export in spreadsheet form with source URLs. |
| ProPublica Congress API roll-call votes | No Civibus equivalent yet | Civibus does not currently publish roll-call votes or voting positions. |
Reference links
Stability, freshness, and limits
Endpoint schemas are the stable client contract. Read the metadata endpoint for live source
freshness, coverage qualifications, and the effective rate-limit policy.
Metadata endpoint: GET /api/public/v1/federal/metadata.
Public API requests are rate limited. Public responses use Cache-Control: public, max-age=900.
Report a data issue