API REFERENCE

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
curl -H "X-API-Key: cb_org_test_xxxxxxxxxxxxxxxx" \
  https://api.civicbeacon.app/api/v3/bills?limit=3

A successful response looks like:

json
{
  "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.

PrefixTypeExpiresGet one
cb_org_test_*Test (sandbox)30 daysFree signup below
cb_org_*Live (production)NeverSubscribe 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:

json
{
  "error": "this test API key has expired — request a new one or upgrade to a paid plan"
}
StatusMeaning
400Bad request — malformed JSON or missing required field
401Missing, invalid, or expired API key
403Org deactivated, or feature not available on your plan
404Resource doesn't exist
409Conflict — usually duplicate creation (e.g. a topic that already exists)
429Rate limit exceeded — back off and retry
500Server 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:

json
{
  "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

GET /api/v3/bills

List 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

topic
string · query
Filter by tracked topic identifier (e.g. "healthcare"). See your org topics with /api/v3/org/topics.
state
string · 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.
congress
int · query
Filter to a specific Congress number (e.g. 119). Defaults to current.
chamber
string · query
Origin chamber: "house" or "senate".
query
string · query
Text search across bill titles, summaries, and bill numbers.
updated_since
date · query
Only bills with action on or after this date (YYYY-MM-DD or RFC3339). This is your change-tracking feed.
updated_before
date · query
Only bills with action on or before this date (YYYY-MM-DD or RFC3339).
page
int · query
Page number. Defaults to 1.
limit
int · query
Page size, 1-100. Defaults to 20.

Example request

curl
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

json
{
  "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
}
GET /api/v3/bills/{id}

Get bill

Single bill detail: official CRS summaries, actions, amendments, sponsors, cosponsors, related bills, policy areas, laws, and committees.

Parameters

id
int · path
Bill ID from a list response.

Example request

curl
curl -H "X-API-Key: $CB_KEY" \
  https://api.civicbeacon.app/api/v3/bills/12345

Example response

json
{
  "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": [ /* ... */ ]
}
GET /api/v3/bills/{id}/summary

AI 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

id
int · path
Bill ID.

Example request

curl
curl -H "X-API-Key: $CB_KEY" \
  https://api.civicbeacon.app/api/v3/bills/12345/summary

Example response

json
{
  "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"
}
GET /api/v3/bills/{id}/votes

Bill 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

id
int · path
Bill ID.

Example request

curl
curl -H "X-API-Key: $CB_KEY" \
  https://api.civicbeacon.app/api/v3/bills/12345/votes

Example response

json
{
  "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
}
GET /api/v3/votes/{voteId}/details

Vote details

Per-legislator positions for a single roll-call vote — the data behind "how did my rep vote".

Parameters

voteId
int · path
Vote ID from a bill's votes response.

Example request

curl
curl -H "X-API-Key: $CB_KEY" \
  https://api.civicbeacon.app/api/v3/votes/987/details

Example response

json
{
  "items": [
    {"legislatorBioguideId": "D000563", "legislatorName": "Durbin", "party": "D", "state": "IL", "votePosition": "Yea"}
  ],
  "count": 435
}
GET /api/v3/representatives

List 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
curl -H "X-API-Key: $CB_KEY" \
  "https://api.civicbeacon.app/api/v3/representatives"

Example response

json
{
  "items": [
    {
      "id": 456,
      "bioguideId": "D000563",
      "officialFullName": "Richard J. Durbin",
      "firstName": "Richard",
      "lastName": "Durbin"
    }
  ],
  "count": 535
}
GET /api/v3/org

Get org profile

Returns your organization's plan, member count, and tracked topics.

Example request

curl
curl -H "X-API-Key: $CB_KEY" \
  https://api.civicbeacon.app/api/v3/org

Example response

json
{
  "id": "0a1b2c3d-...",
  "name": "League of Women Voters Illinois",
  "slug": "league-of-women-voters-illinois",
  "plan": "pro",
  "maxMembers": 25,
  "createdAt": "2026-03-12T..."
}
POST /api/v3/org/keys/rotate

Rotate 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
curl -X POST -H "X-API-Key: $CB_KEY" \
  https://api.civicbeacon.app/api/v3/org/keys/rotate

Example response

json
{
  "apiKey": "cb_org_9f8e7d6c...",
  "message": "Store this key securely — it is shown once and the previous key no longer works."
}
GET POST DELETE /api/v3/org/topics

Manage tracked topics

Your org's topic watchlist — the topics and keywords your organization actively follows.

Example request

curl
# 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-rights

Example response

json
{
  "topics": [
    {"topic":"voting rights","keywords":["voter id","ballot access","redistricting"]}
  ]
}
GET /api/v3/org/usage

API 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
curl -H "X-API-Key: $CB_KEY" \
  "https://api.civicbeacon.app/api/v3/org/usage"

Example response

json
{
  "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"
}
PUT GET DELETE /api/v3/org/webhook

Webhook 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

curl
# 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/webhook

Example response

json
{
  "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:

json
{
  "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.

One key per email. Live keys cost from $199/month — see plans.

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.

Enterprise or grassroots 501(c)(3) pricing? Talk to us.

Need help?

This page is the canonical reference, but if something's missing or unclear, just ask: