API
Last updated: 2026-09-25Everything on this page answers today, without a key, from the same code that renders the pages, so a number you read here is the number the page shows. There is no version in these paths yet and nothing here calls a race. If you build on it, read the sections on caching, rate limits and data use; they are the whole of the contract.
What answers
| Endpoint | What you get | Cache-Control | Per-IP limit |
|---|---|---|---|
/bill/<slug>/?format=json | One bill or resolution | public, max-age=300, s-maxage=3600 | none of its own |
/legislator/<bioguide>/?format=json | One member of Congress | public, max-age=300, s-maxage=3600 | none of its own |
/vote/<id>/?format=json | One roll-call vote | public, max-age=300, s-maxage=3600 | none of its own |
/floor/live.json | Both chambers now, plus the last 18 hours | public, max-age=30, stale-while-revalidate=10 | 120 an hour |
/api/zip-lookup/<zip>/ | The House members and senators for a ZIP | public, max-age=900 | 60 an hour |
/elections/results.json | 2026 results from the state feeds | documented at /elections/api/ | |
All are GET, all return application/json, and all carry Access-Control-Allow-Origin: *, so a page on any other site can fetch them directly. Dates are YYYY-MM-DD; timestamps are ISO 8601 with an offset. On-site links come back as a site-relative path; prefix https://openamerica.io.
A bill
The slug is <congress>-<TYPE>-<number>, the same one in the page URL: 119-HR-1, 119-S-2296, 119-HCONRES-89. Types are HR, S, HRES, SRES, HJRES, SJRES, HCONRES and SCONRES.
curl -s 'https://openamerica.io/bill/119-HR-1/?format=json'
Abbreviated response, as the site returned it on 2026-09-25:
{
"type": "bill",
"url": "https://openamerica.io/bill/119-HR-1/",
"legislation_id": "119-HR-1",
"congress": 119,
"legislation_type": "HR",
"legislation_number": 1,
"title": "An act to provide for reconciliation pursuant to title II of H. Con. Res. 14.",
"origin_chamber": "House",
"policy_area": "Economics and Public Finance",
"subjects": ["Abortion", "Accounting and auditing", "Administrative law and regulatory procedures", "..."],
"date_introduced": "2025-05-20",
"latest_action": {"text": "Became Public Law No: 119-21.", "date": "2025-07-04"},
"lifecycle": "enacted",
"sponsor": {
"bioguide_id": "A000375",
"name": "Arrington, Jodey C.",
"state": "Texas",
"party": "Republican",
"image_url": "https://www.congress.gov/img/member/115_rp_tx_19_arrington_jodey_200.jpg",
"path": "/legislator/A000375/"
},
"cosponsor_count": 0,
"actions_preview": [
{"date": "2025-07-04", "text": "Became Public Law No: 119-21.", "type": "36000"},
{"date": "2025-07-04", "text": "Signed by President.", "type": "36000"},
"..."
],
"congress_gov_source": "https://api.congress.gov/v3/bill/119/hr/1?format=json",
"path": "/bill/119-HR-1/"
}
| Field | Type | Meaning |
|---|---|---|
type | string | Always bill. |
url | string | The absolute URL of the page this record belongs to. |
legislation_id | string | The slug. |
congress | integer | The Congress, for example 119. |
legislation_type | string | One of the eight types above. |
legislation_number | integer | The number within the type. |
title | string | The title as congress.gov gives it. |
origin_chamber | string or null | House or Senate. |
policy_area | string or null | The congress.gov policy area. |
subjects | array of strings | The congress.gov legislative subjects. Can be long, can be empty. |
date_introduced | date or null | When it was introduced. |
latest_action | object | text (string or null) and date (date or null): the newest action. |
lifecycle | string | One of active, enacted, agreed, vetoed, died. Our classification of where the bill stands, biased toward active when unsure; the methodology page explains it. |
sponsor | object or null | The sponsor's summary: bioguide_id, name, state, party, image_url, path. |
cosponsor_count | integer | How many cosponsors. The list itself is on the page. |
actions_preview | array | The newest 25 actions, newest first, each with date (date or null), text (string) and type (string, the congress.gov action code). |
congress_gov_source | string | The api.congress.gov record this was read from. |
path | string | The site-relative page path. |
Not included: bill text, the CRS or AI summary, the cosponsor list, amendments, related bills, committee referrals and roll-call votes. They are on the page.
A member of Congress
Keyed by the bioguide ID that congress.gov uses; upper case, and the same one in the page URL.
curl -s 'https://openamerica.io/legislator/A000370/?format=json'
The full response on 2026-09-25:
{
"type": "legislator",
"url": "https://openamerica.io/legislator/A000370/",
"bioguide_id": "A000370",
"name": "Adams, Alma S.",
"state": "North Carolina",
"party": "Democratic",
"image_url": "https://www.congress.gov/img/member/a000370_200.jpg",
"path": "/legislator/A000370/",
"first_name": "Alma",
"last_name": "Adams",
"current_member": true,
"official_website": "https://adams.house.gov",
"birth_year": 1946,
"totals": {"bills_sponsored": 183, "bills_cosponsored": 2420}
}
| Field | Type | Meaning |
|---|---|---|
type | string | Always legislator. |
url | string | The absolute URL of the member's page. |
bioguide_id | string | The congress.gov bioguide ID. |
name | string | Inverted, as the Clerk writes it: Last, First M. |
state | string | The full state name. |
party | string | Democratic, Republican or Independent. |
image_url | string or null | The congress.gov portrait. |
path | string | The site-relative page path. |
first_name, last_name | string | Present when we hold the member's full record, which is every current member. |
current_member | boolean | Whether the member serves in the current Congress. |
official_website | string or null | The member's official site. |
birth_year | integer or null | Birth year, when congress.gov gives it. |
totals | object | bills_sponsored and bills_cosponsored: career counts, amendments excluded, from the same source as the page. |
senate_class, next_election_year | string, integer | Senators only: the Senate class and the year that seat is next on the ballot. |
leadership | array | Only when the member holds a current leadership role: each entry has role (string), congress (integer) and current (boolean). |
Not included: the voting record, committee seats, party unity, missed votes, sponsored bills and contact details. They are on the page.
A roll-call vote
The id is Open America's own integer, the one in the page URL. Find them on the votes list, on a bill page, or in the senate_recent_votes of the floor feed below.
curl -s 'https://openamerica.io/vote/10782/?format=json'
The full response on 2026-09-25:
{
"type": "vote",
"url": "https://openamerica.io/vote/10782/",
"vote_id": 10782,
"congress": 119,
"chamber": "S",
"date": "2026-09-24T17:45:00+00:00",
"question": "On the Concurrent Resolution H.Con.Res. 89",
"result": "rejected",
"bill": {
"legislation_id": "119-HCONRES-89",
"title": "Directing the President, pursuant to section 5(c) of the War Powers Resolution, to remove United States Armed Forces from hostilities with Iran.",
"path": "/bill/119-HCONRES-89/"
},
"breakdown": {"yea": 49, "not_voting": 1, "nay": 50}
}
| Field | Type | Meaning |
|---|---|---|
type | string | Always vote. |
url | string | The absolute URL of the vote's page. |
vote_id | integer | Open America's id for the vote. |
congress | integer | The Congress. |
chamber | string or null | H or S. |
date | timestamp or null | When the vote closed, with offset. |
question | string | The question as the chamber recorded it. |
result | string | One of passed, failed, agreed_to, rejected, confirmed, not_confirmed, sustained, not_sustained, guilty, not_guilty, override_passed, override_failed, other. |
bill | object or null | The measure voted on, when it is a bill or resolution we hold: legislation_id, title, path. Null for nominations and for votes we could not link. |
breakdown | object | Members by position: yea, nay, present, not_voting. A position nobody took is absent. |
Per-member positions are not in the vote JSON yet; the page lists every member's position, and a versioned endpoint that carries them is on the list below. Party splits, the roll-call number and the session are also page-only for now.
The floor, live
The payload the floor page polls: both chambers' status right now, the House floor narrative from the last 18 hours and the Senate roll calls from the last 18 hours.
curl -s 'https://openamerica.io/floor/live.json'
The full response on 2026-09-25, a day neither chamber sat, so both lists are empty:
{
"fetched_at": "2026-09-25T14:44:12.533761+00:00",
"house": {
"ok": true,
"in_session": false,
"is_pro_forma": false,
"subline": "Next Session: September 28th, 2026 at 12:00 PM",
"live_stream": "https://live.house.gov/",
"public_state": "not_in_session",
"public_label": "Not in session",
"state": "adjourned",
"state_label": "Not in session",
"confidence": "high",
"last_activity_at": "2026-09-24T18:33:35+00:00"
},
"senate": {
"ok": true,
"in_session": false,
"is_pro_forma": false,
"subline": "Convenes at 3:00 p.m.",
"live_stream": "https://www.senate.gov/isvp/stv.html?type=live&comm=stv&filename=stv092826",
"public_state": "not_in_session",
"public_label": "Not in session",
"state": "stale_data",
"state_label": "Data stale (18h)",
"confidence": "low",
"last_activity_at": "2026-09-24T17:45:00+00:00"
},
"recent_floor": [],
"senate_recent_votes": []
}
| Field | Type | Meaning |
|---|---|---|
fetched_at | timestamp | When this response was built. It moves on every response, so this endpoint has no ETag: poll on a timer. |
house, senate | object | One chamber, with the fields below. |
ok | boolean | The chamber's own status feed answered. |
in_session | boolean | The chamber is sitting now. |
is_pro_forma | boolean | Sitting, but pro forma: no business. |
subline | string | The chamber's own status line, verbatim. |
live_stream | string | Where to watch. |
public_state | string | One of active, pro_forma, scheduled, recessed, not_in_session. Build on this one. |
public_label | string | The label the page shows for public_state. |
state, state_label, confidence | string | The diagnostic detail behind public_state, including our own freshness doubts (stale_data, unreachable). The vocabulary is internal and can change; confidence is high, medium or low. |
last_activity_at | timestamp or null | The newest floor action or vote we hold for the chamber. |
recent_floor | array | House floor narrative from the last 18 hours, newest first, at most 40. Each item: id (integer, the Clerk's id for the action), time_iso (timestamp, Eastern offset), time_label (string, for example 5:18 PM EDT), action_item (string, the Clerk's item label such as H.R. 1, or empty), bill_slug (string, or empty), desc (string, the narrative). |
senate_recent_votes | array | Senate roll calls from the last 18 hours, newest first, at most 15. Each item: id (the vote id above), time_iso, time_label, roll_call (integer), question (cut at 180 characters), result and result_label, outcome_class (success, danger or empty), yea and nay (integers), bill_slug (string, or empty), detail_url (the vote's path). |
The site's own page polls this once a minute and holds a push stream between polls. Poll no faster than every 30 seconds: the per-IP limit is 120 requests an hour, which is exactly one every 30 seconds. The Senate has no minute-by-minute narrative feed; its side of this payload is roll calls and status.
Find your representatives by ZIP
The House members whose districts touch the ZIP, resolved through the House's own ziplook service and cached on our side for 30 days, plus the state's two senators.
curl -s 'https://openamerica.io/api/zip-lookup/78201/'
The full response on 2026-09-25:
{
"ok": true,
"zip": "78201",
"state": "TX",
"representatives": [
{"bioguide_id": "C001091", "name": "Castro, Joaquin", "party": "Democratic", "state": "Texas",
"image_url": "https://www.congress.gov/img/member/69d7f5b07304cef7a0c977b1_200.jpg", "detail_url": "/legislator/C001091/"},
{"bioguide_id": "C001131", "name": "Casar, Greg", "party": "Democratic", "state": "Texas",
"image_url": "https://www.congress.gov/img/member/c001131_200.jpg", "detail_url": "/legislator/C001131/"}
],
"senators": [
{"bioguide_id": "C001056", "name": "Cornyn, John", "party": "Republican", "state": "Texas",
"image_url": "https://www.congress.gov/img/member/c001056_200.jpg", "detail_url": "/legislator/C001056/"},
{"bioguide_id": "C001098", "name": "Cruz, Ted", "party": "Republican", "state": "Texas",
"image_url": "https://www.congress.gov/img/member/c001098_200.jpg", "detail_url": "/legislator/C001098/"}
]
}
| Field | Type | Meaning |
|---|---|---|
ok | boolean | true on a 200. A ZIP we cannot resolve is a 404 with {"ok": false, "reason": "zip_not_found"}. |
zip | string | The ZIP as looked up. |
state | string | The two-letter state code. |
representatives | array | One member, or several where the ZIP crosses district lines. |
senators | array | The state's two senators. |
| each member | object | bioguide_id, name (inverted), party, state (the full name), image_url (empty string when none) and detail_url (the member's path). |
Election results
/elections/results.json (with ?year= and ?office=) and /elections/seat/<key>.json carry the 2026 results the district map draws, as the official state feeds report them, from November 3. They are keyless, they carry an ETag, and they call no race: any leader or call in them is the state feed's own. Their fields are documented at /elections/api/.
Caching and polling
The bill, member and vote JSON answer with Cache-Control: public, max-age=300, s-maxage=3600 and an ETag. The edge may hold a copy for up to an hour, so a change on the page can take that long to reach the JSON. Send If-None-Match with the ETag you last saw and you get a 304 with no body when nothing changed. A bill or a member changes a few times a day at most, and a vote never changes once it is recorded, so once an hour is plenty.
curl -s -D - 'https://openamerica.io/vote/10782/?format=json' -H 'If-None-Match: W/"14c8d570e3a6616b0f6943aec9af9ceb"'
HTTP/2 304
The floor feed answers with public, max-age=30, stale-while-revalidate=10 and no ETag; poll it on a timer, 30 seconds at the fastest. The ZIP lookup answers with public, max-age=900. The election JSON has its own, shorter times, on its own page.
Rate limits
| Endpoint | Limit |
|---|---|
/floor/live.json | 120 requests an hour per IP address |
/api/zip-lookup/ | 60 requests an hour per IP address |
| bill, member and vote JSON | No limit of their own beyond the edge cache |
| everything, for crawlers on the slow list | 60 requests a minute site-wide, answered 429 with Retry-After |
Past a per-IP limit you get HTTP 403 with an HTML body until the hour rolls over; it is not a 429 today, and turning it into one is on the list below. The slow list is the set of crawlers that ignore the crawl delay in robots.txt. Ordinary scripts are not on it and need no special User-Agent.
Cross-origin requests
Every JSON response above carries Access-Control-Allow-Origin: *, on the 200 and on the 304, so a browser page on another domain can fetch() it with no proxy. The header is only ever added to a response produced for a request that carried no cookie, so send the request without credentials, which is the default. An HTML page never carries it.
Errors
A bill, member or vote that does not exist is a 404 with an HTML body, not JSON; check the status before parsing. The ZIP lookup's 404 is JSON, shown above. A request past a rate limit is a 403.
What this is not
- No race calls. Nothing on this site names a winner; the election JSON repeats what the state feed says and says which state said it.
- No keys, no per-key quotas, no bulk export, no CSV, no list endpoints in JSON. The lists (bills, members, votes, lobbying filings, trades, discharge petitions) are pages.
- No version. These paths are unversioned and will keep answering as they do today. A versioned
/api/v1/is planned, and the policy we intend to publish with it is that within a version fields are only added, a field or endpoint is removed only in a new version with the old one kept running for twelve months after, and a change is noted on this page the day it is decided. - No per-member vote positions in JSON yet, and no lobbying, disclosure or trades JSON yet; those are pages for now.
- No AI summaries in JSON. Where a summary written by a model appears on a page it is labelled AI-generated, and if one is ever added to a JSON response it will carry the same label.
Freshness
While a chamber is in session, floor activity, roll-call votes and White House bill statements are re-checked every minute and new bills, committee meetings and hearings every five minutes; lobbying filings, House financial disclosures and committee rosters refresh once a day, the Senate's daily floor record hourly through the evening, discharge petitions every six hours, and election results every five minutes from the state feeds once counting begins on November 3, and every minute through election night.
How current each source is right now is on the status page, which is itself refreshed every two minutes. The methodology page says where every field comes from and how every statistic is computed.
Data use
The same statement appears on the methodology page, in the Terms of Service and in llms.txt.
Draft. This data-use statement is published for review and its wording may change before it is adopted.
Government records
Source records from congress.gov, the House Clerk (clerk.house.gov and disclosures-clerk.house.gov), senate.gov, lda.gov and whitehouse.gov are works of the United States government. Open America republishes them without any claim of copyright (17 U.S.C. 105) and adds no restriction of its own to them.
State election feeds
The election results on /elections/ come from official state election offices whose terms vary from state to state; at least one publishes its feed under a state copyright notice and marks its results unofficial. Those feeds are not part of any grant made here, and election results are never part of an export or bulk download.
What Open America adds
Open America's own derived fields (transactions parsed from PTR filings, lobbying-to-bill links, LD-203 honoree matches, bill lifecycle states, member statistics and AI summaries) may be used, quoted, republished and built on, for paid or unpaid work, with the attribution "Open America (openamerica.io)" and the date you retrieved the data, subject to the lobbying and disclosure notices below.
Lobbying data
Lobbying data comes from lda.gov, whose terms of service ask three things of anyone who reuses it: cite the date the data was retrieved; do not modify content and still cite it as LDA.gov; and state that "Senate Office of Public Records cannot vouch for the data or analyses derived from these data after the data have been retrieved from LDA.gov." Carry all three with any lobbying figure you take from this site.
Financial disclosures
Financial disclosure data (everything on /disclosures/ and /trades/, and anything derived from a House PTR filing) is subject to 5 U.S.C. 13107(c): a report may not be obtained or used for any commercial purpose other than by news and communications media for dissemination to the general public, to determine or establish anyone's credit rating, or in the solicitation of money for any political, charitable or other purpose, and the Attorney General may seek a penalty of up to $10,000 for a violation. Open America does not sell this data and it is not part of any paid plan.
Live feeds
Repackaging one of the live endpoints as your own API, or reselling the feed as it stands, needs a written agreement: write to [email protected]. There is no Creative Commons licence on the live endpoints; attribution and the notices here are the whole of the grant.
AI summaries
Summaries written by a model are labelled as AI-generated wherever they appear, on a page or in JSON, and where one disagrees with the bill, the bill is right.
References: 17 U.S.C. 105, lda.gov terms of service, 5 U.S.C. 13107.
Changes
This page carries its date at the top. When a field is added, it is added here the same day; a test fails the build when a field the code returns is missing from this page. Questions, or something you need that is not here: [email protected] or report a problem.