Developer access
REST API documentation
The Bill Commons API is free, public, and read-only. It serves JSON over HTTPS with a consistent pagination envelope, ETags, and request IDs. Interactive OpenAPI 3.1 docs are available at https://api.billcommons.org/docs.
Base URL
https://api.billcommons.orgAuthentication & rate limits
No API key is required for the public anonymous tier: 60 requests/minute per IP. API keys for higher-volume tiers are planned; see the about page for status.
Pagination envelope
Every list endpoint returns the same shape:
Response shape
{
"data": [ ... ],
"pagination": {
"page": 1,
"per_page": 20,
"total": 431,
"total_pages": 22
},
"meta": {
"source_freshness": "2026-07-23T14:02:00Z",
"api_version": "v1",
"request_id": "a1b2c3d4"
}
}Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/jurisdictions | List all 51 jurisdictions. |
| GET | /api/v1/jurisdictions/{id} | Get one jurisdiction. |
| GET | /api/v1/sessions | List legislative sessions (filter by jurisdiction, active). |
| GET | /api/v1/bills | List bills. Filters: jurisdiction, session, identifier, chamber, status, subject, sponsor. (No committee or date-range filter — those were listed here before they existed.) |
| GET | /api/v1/bills/{id} | Get a bill with full detail (sponsors, actions, versions, votes, sources). |
| GET | /api/v1/bills/{id}/versions | List a bill's text versions. |
| GET | /api/v1/bills/{id}/actions | List a bill's full action history. |
| GET | /api/v1/bills/{id}/sponsors | List a bill's sponsors and cosponsors. |
| GET | /api/v1/bills/{id}/votes | List recorded votes, including member-level detail. |
| GET | /api/v1/bills/{id}/documents | List associated documents (fiscal notes, amendments, etc). |
| GET | /api/v1/people | NOT COLLECTED — always returns []. Legislator records are not ingested; responses carry data_status: "not_collected". Sponsor names are available per bill. |
| GET | /api/v1/people/{id} | NOT COLLECTED — always 404s. No legislator records exist. |
| GET | /api/v1/committees | NOT COLLECTED — always returns []. Committee referrals are visible in each bill's action history. |
| GET | /api/v1/committees/{id} | NOT COLLECTED — always 404s. |
| GET | /api/v1/events | NOT COLLECTED — always returns []. No hearing or calendar data is ingested for any jurisdiction. Empty means we lack the data, not that nothing is scheduled. |
| POST | /api/v1/alerts/subscribe | Email digest for a topic. Optional jurisdiction (e.g. "FL") scopes it to one state instead of all 51. |
| GET | /api/v1/search | Full-text and structured search across all jurisdictions. |
| GET | /api/v1/sources | List source registry entries per jurisdiction. |
| GET | /api/v1/coverage | Public per-jurisdiction coverage matrix. |
| GET | /api/v1/health | Liveness check (DB ping). |
| GET | /api/v1/ready | Readiness check. |
Example: search for a bill
curl
curl "https://api.billcommons.org/api/v1/search?q=HB+123&jurisdiction=NC"Python
import requests
resp = requests.get(
"https://api.billcommons.org/api/v1/search",
params={"q": "HB 123", "jurisdiction": "NC"},
)
resp.raise_for_status()
data = resp.json()
for bill in data["data"]:
print(bill["identifier"], bill["title"])JavaScript
const url = new URL("https://api.billcommons.org/api/v1/search");
url.searchParams.set("q", "HB 123");
url.searchParams.set("jurisdiction", "NC");
const res = await fetch(url);
const { data } = await res.json();
for (const bill of data) {
console.log(bill.identifier, bill.title);
}Example: get a bill's full record
curl
curl "https://api.billcommons.org/api/v1/bills/{bill_id}"All bill and document text is sourced from official legislative records or Open States and is provided as-is; see methodology for attribution and known limitations.