Civic Beacon API
Federal legislation data with AI-powered summaries, designed for advocacy organizations, newsrooms, and civic education programs. Stable, versioned, and production-ready. Use a free 30-day test key below — no credit card.
Quickstart
Every request includes your API key in the X-API-Key header. Bills are returned as paginated JSON. AI summaries are generated on demand from the bill text.
One curl call to confirm your key works:
curl -H "X-API-Key: cb_org_test_xxxxxxxxxxxxxxxx" \
https://api.civicbeacon.app/api/v3/bills?limit=3A successful response looks like:
{
"items": [
{
"id": 12345,
"congress": 119,
"billType": "hr",
"billNumber": 1234,
"title": "Healthcare Affordability Act",
"introducedDate": "2026-04-15T00:00:00Z",
"latestActionDate": "2026-04-22T00:00:00Z",
"latestActionText": "Reported by Committee on Energy and Commerce",
"policyAreas": ["Health"],
"sponsorName": "Rep. Jane Smith",
"sponsorBioguideId": "S000123"
}
],
"nextCursor": 2,
"hasMore": true
}Authentication
Every request must include an API key. Two ways to send it:
- Header (preferred):
X-API-Key: cb_org_xxxxxxxxxxxxxxxx - Query parameter (for embeds):
?api_key=cb_org_xxxxxxxxxxxxxxxx
Two key types exist. They differ only in expiration; both work against every endpoint.
| Prefix | Type | Expires | Get one |
|---|---|---|---|
cb_org_test_* | Test (sandbox) | 30 days | Free signup below |
cb_org_* | Live (production) | Never | Subscribe to a paid plan |
Treat your API key like a password. Don't commit it to public repos. If you accidentally leak one, contact support to rotate it.
Rate limits
The default per-key rate limit is 200 requests per minute. Both test and live keys share this limit.
When you exceed the limit, you'll get a 429 Too Many Requests response. Back off and retry after a few seconds. If you need a higher limit for a legitimate use case (e.g., bulk historical research), reply to your onboarding email and we'll bump it for your account.
One note on AI summaries: live keys generate summaries on demand; test keys can read cached summaries only (the underlying LLM tokens cost real money). If you're stress-testing, focus on cheap endpoints like list-bills.
Errors
Errors are returned with a 4xx or 5xx status code and a JSON body:
{
"error": "this test API key has expired — request a new one or upgrade to a paid plan"
}| Status | Meaning |
|---|---|
| 400 | Bad request — malformed JSON or missing required field |
| 401 | Missing, invalid, or expired API key |
| 403 | Org deactivated, or feature not available on your plan |
| 404 | Resource doesn't exist |
| 409 | Conflict — usually duplicate creation (e.g. a topic that already exists) |
| 429 | Rate limit exceeded — back off and retry |
| 500 | Server error — retryable, please report if persistent |
Pagination
List endpoints accept page (default 1) and limit (default 20, max 100). The response includes nextCursor and hasMore:
{
"items": [ /* up to 100 items */ ],
"nextCursor": 2,
"hasMore": true
}Request the next page with ?page=2 (the value of nextCursor). hasMore: false means you've reached the end.
Endpoints
/api/v3/billsList bills
Returns paginated federal bills, most recently acted-on first. Filter by topic, sponsor state, congress, chamber, or text search — or use updated_since to see what moved since your last check. Most clients want this as their primary feed.
Parameters
topicstring · query | Filter by tracked topic identifier (e.g. "healthcare"). See your org topics with /api/v3/org/topics. |
statestring · query | Filter to bills whose sponsor is from this state (2-letter code, e.g. "IL"). Note: this is the sponsor's state — coverage is federal legislation only. |
congressint · query | Filter to a specific Congress number (e.g. 119). Defaults to current. |
chamberstring · query | Origin chamber: "house" or "senate". |
querystring · query | Text search across bill titles, summaries, and bill numbers. |
updated_sincedate · query | Only bills with action on or after this date (YYYY-MM-DD or RFC3339). This is your change-tracking feed. |
updated_beforedate · query | Only bills with action on or before this date (YYYY-MM-DD or RFC3339). |
pageint · query | Page number. Defaults to 1. |
limitint · query | Page size, 1-100. Defaults to 20. |
Example request
curl -H "X-API-Key: $CB_KEY" \
"https://api.civicbeacon.app/api/v3/bills?topic=healthcare&updated_since=2026-09-01&limit=10"Example response
{
"items": [
{
"id": 12345,
"congress": 119,
"billType": "hr",
"billNumber": 1234,
"title": "Healthcare Affordability Act",
"introducedDate": "2026-04-15T00:00:00Z",
"latestActionDate": "2026-04-22T00:00:00Z",
"latestActionText": "Reported by Committee on Energy and Commerce",
"policyAreas": ["Health"],
"sponsorName": "Rep. Jane Smith",
"sponsorBioguideId": "S000123"
}
],
"nextCursor": 2,
"hasMore": true
}/api/v3/bills/{id}Get bill
Single bill detail: official CRS summaries, actions, amendments, sponsors, cosponsors, related bills, policy areas, laws, and committees.
Parameters
idint · path | Bill ID from a list response. |
Example request
curl -H "X-API-Key: $CB_KEY" \
https://api.civicbeacon.app/api/v3/bills/12345Example response
{
"id": 12345,
"congress": 119,
"billType": "hr",
"billNumber": 1234,
"title": "Healthcare Affordability Act",
"introducedDate": "2026-04-15T00:00:00Z",
"latestActionDate": "2026-04-22T00:00:00Z",
"latestActionText": "Reported by Committee on Energy and Commerce",
"policyAreas": ["Health"],
"sponsors": [ /* ... */ ],
"cosponsors": [ /* ... */ ],
"actions": [ /* ... */ ],
"amendments": [ /* ... */ ],
"committees": [ /* ... */ ],
"relatedBills": [ /* ... */ ]
}/api/v3/bills/{id}/summaryAI bill summary
Plain-English AI summary of the bill — the differentiator versus raw Congress.gov data. Live keys: generated on demand if no cached summary exists. Test keys: cached summaries only.
Parameters
idint · path | Bill ID. |
Example request
curl -H "X-API-Key: $CB_KEY" \
https://api.civicbeacon.app/api/v3/bills/12345/summaryExample response
{
"id": 67890,
"entityType": "bill",
"entityId": 12345,
"summaryJson": {
"summary": "This bill caps out-of-pocket prescription drug costs at $2,000/year for Medicare beneficiaries, and requires HHS to negotiate prices on the top 50 drugs by Medicare spend. It also extends ACA premium subsidies through 2028.",
"key_points": [
"Caps prescription costs at $2,000/year",
"HHS price negotiation expanded to 50 drugs",
"ACA subsidies extended through 2028"
]
},
"createdAt": "2026-04-22T14:30:00Z",
"updatedAt": "2026-04-22T14:30:00Z"
}/api/v3/bills/{id}/votesBill votes
All roll-call votes on a bill, most recent first, with per-party totals (yea/nay/present/not voting). Use the vote IDs with /api/v3/votes/{voteId}/details for per-legislator positions.
Parameters
idint · path | Bill ID. |
Example request
curl -H "X-API-Key: $CB_KEY" \
https://api.civicbeacon.app/api/v3/bills/12345/votesExample response
{
"items": [
{
"voteId": 987,
"billId": 12345,
"rollNumber": 214,
"chamber": "house",
"question": "On Passage",
"result": "Passed",
"voteDate": "2026-04-22T00:00:00Z",
"partyBreakdown": [
{"party": "D", "yeaTotal": 210, "nayTotal": 2, "presentTotal": 0, "notVotingTotal": 3}
]
}
],
"count": 1
}/api/v3/votes/{voteId}/detailsVote details
Per-legislator positions for a single roll-call vote — the data behind "how did my rep vote".
Parameters
voteIdint · path | Vote ID from a bill's votes response. |
Example request
curl -H "X-API-Key: $CB_KEY" \
https://api.civicbeacon.app/api/v3/votes/987/detailsExample response
{
"items": [
{"legislatorBioguideId": "D000563", "legislatorName": "Durbin", "party": "D", "state": "IL", "votePosition": "Yea"}
],
"count": 435
}/api/v3/representativesList representatives
All current federal legislators with party, state, district, and bioguide IDs. Returns the full list in one response — filter client-side.
Example request
curl -H "X-API-Key: $CB_KEY" \
"https://api.civicbeacon.app/api/v3/representatives"Example response
{
"items": [
{
"id": 456,
"bioguideId": "D000563",
"officialFullName": "Richard J. Durbin",
"firstName": "Richard",
"lastName": "Durbin"
}
],
"count": 535
}/api/v3/orgGet org profile
Returns your organization's plan, member count, and tracked topics.
Example request
curl -H "X-API-Key: $CB_KEY" \
https://api.civicbeacon.app/api/v3/orgExample response
{
"id": "0a1b2c3d-...",
"name": "League of Women Voters Illinois",
"slug": "league-of-women-voters-illinois",
"plan": "pro",
"maxMembers": 25,
"createdAt": "2026-03-12T..."
}/api/v3/org/keys/rotateRotate API key
Issues a replacement API key. The old key stops working immediately; the new raw key is returned once — store it yourself, only its hash is kept server-side. Test keys rotate to new test keys and keep their original expiry.
Example request
curl -X POST -H "X-API-Key: $CB_KEY" \
https://api.civicbeacon.app/api/v3/org/keys/rotateExample response
{
"apiKey": "cb_org_9f8e7d6c...",
"message": "Store this key securely — it is shown once and the previous key no longer works."
}/api/v3/org/topicsManage tracked topics
Your org's topic watchlist — the topics and keywords your organization actively follows.
Example request
# List
curl -H "X-API-Key: $CB_KEY" \
https://api.civicbeacon.app/api/v3/org/topics
# Add (replaces list of keywords)
curl -X POST -H "X-API-Key: $CB_KEY" \
-H "Content-Type: application/json" \
-d '{"topic":"voting rights","keywords":["voter id","ballot access","redistricting"]}' \
https://api.civicbeacon.app/api/v3/org/topics
# Remove
curl -X DELETE -H "X-API-Key: $CB_KEY" \
https://api.civicbeacon.app/api/v3/org/topics/voting-rightsExample response
{
"topics": [
{"topic":"voting rights","keywords":["voter id","ballot access","redistricting"]}
]
}/api/v3/org/usageAPI usage stats
Daily breakdown of API calls by endpoint, trailing 30 days. Useful for capacity planning and confirming you're under the rate limit.
Example request
curl -H "X-API-Key: $CB_KEY" \
"https://api.civicbeacon.app/api/v3/org/usage"Example response
{
"usage": [
{"endpoint":"/api/v3/bills","date":"2026-04-22","requestCount":847},
{"endpoint":"/api/v3/bills/{id}/summary","date":"2026-04-22","requestCount":12}
],
"since": "2026-03-24T00:00:00Z"
}/api/v3/org/webhookWebhook alerts
Configure a URL and we'll POST a signed bills.updated payload whenever a bill matching your tracked topics moves. The signing secret is returned once on setup. See the Webhooks section below for the payload format and signature verification.
Example request
# Configure (returns the signing secret once)
curl -X PUT -H "X-API-Key: $CB_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://yourorg.org/hooks/civicbeacon"}' \
https://api.civicbeacon.app/api/v3/org/webhook
# Check configuration (secret never returned again)
curl -H "X-API-Key: $CB_KEY" \
https://api.civicbeacon.app/api/v3/org/webhook
# Remove (stops alerts)
curl -X DELETE -H "X-API-Key: $CB_KEY" \
https://api.civicbeacon.app/api/v3/org/webhookExample response
{
"webhookUrl": "https://yourorg.org/hooks/civicbeacon",
"webhookSecret": "whsec_9f8e7d6c...",
"message": "Webhook configured. Store the secret — it is shown once..."
}Webhook alerts
Once you've configured /api/v3/org/webhook and added topics via /api/v3/org/topics, we match your topics against every bill action as it lands (data refreshes 4× daily on weekdays; alerts batch hourly). All matches for your org arrive in one POST:
{
"event": "bills.updated",
"org": {"slug": "your-org", "name": "Your Org"},
"alerts": [
{
"topic": "voting rights",
"matchedKeyword": "ballot access",
"bill": {
"id": 12345,
"congress": 119,
"billType": "hr",
"billNumber": 1234,
"title": "Voting Rights Advancement Act",
"latestActionDate": "2026-09-11T13:00:00Z",
"latestActionText": "Ordered to be Reported"
}
}
],
"sentAt": "2026-09-11T14:07:00Z"
}Verifying signatures. Every delivery carries an X-CivicBeacon-Signature header: hex-encoded HMAC-SHA256 of the raw request body, keyed with your webhook secret. Compute the same HMAC over the body you receive and compare — reject anything that doesn't match.
Delivery semantics. At-most-once per (bill, topic, action date). A bill that moves again on a later date alerts again. Respond with any 2xx; failures are logged on our side but not retried automatically — the change-tracking feed (updated_since) is your backstop if you need guaranteed coverage.
Try it — get a free 30-day test key
Enter your org name and email. We'll provision a sandbox API key, email it to you, and surface it on this page. No credit card. The key works against every endpoint, expires in 30 days, and can be upgraded to a live key anytime.
Upgrade to a live key
Ready for production? Pick a plan and you'll be sent straight to Stripe Checkout. Your live API key is emailed the moment payment completes — no sales call, no waiting on us. Month-to-month, cancel anytime.
Need help?
This page is the canonical reference, but if something's missing or unclear, just ask:
- Email: [email protected] — replies within 24 hours on weekdays
- Onboarding call: Schedule a 30-minute walkthrough
- Terms: Terms of service & acceptable use
- Status: no formal status page yet — our ingestion schedule and availability approach are described in the terms; if you suspect an outage, email us and you'll get a human answer fast