Download OpenAPI specification:
DRAFT. Read-only JSON access to Colorado legislative data: bills, committees, legislators, calendars, ballot measures and initiatives. This is the same data that feeds the Colorado General Assembly website, delivered as a stable, structured API so that you do not need to scrape web pages.
This documentation was written from observed API behavior. Field meanings are as observed, not from an official data dictionary.
x-api-key: <your key>.curl -H "x-api-key: $API_KEY" \
"https://api.coleg.gov/v1/bills/lm/2026-09-01T00:00:00Z/all"
Everything is GET. There are no write operations.
Most data types offer a lm ("last modified") endpoint that returns only the IDs of records
changed since a timestamp. Poll these instead of re-downloading everything, then fetch the full
record only for IDs that changed.
| Endpoint pattern | Returns |
|---|---|
/{entity}/lm/{since}/all or /{entity}/lm/{since}/{sessionId} |
IDs changed since {since} |
/{entity}/{id} |
The full record for one ID |
{since} is an ISO 8601 UTC timestamp such as 2026-09-01T00:00:00Z, or 0 for "everything".
Store the time you last checked and pass it on the next poll. Schedules have no lm endpoint;
fetch the current schedule directly.
Suggested cadence during session: calendar every 15 minutes, bills every 30 minutes, legislators and committees hourly, documents nightly. Outside session, far less often.
Responses in Production are cached at the gateway for up to the times below, so polling more often than this returns the same data and only uses your quota.
| Data | Maximum cache age |
|---|---|
| Legislators / directory | 6 hours |
| Committee info, ballots, initiatives, past committee meetings | 24 hours |
| Bills, committee meeting lists | 60 minutes |
| Schedules (calendars) | 10 minutes |
The lm "changed since" lists are effectively not cached, because each caller's timestamp differs.
Limits apply per API key according to the key's usage tier, and are set when your key is issued. A request over your limit returns HTTP 429 and never reaches the data source. Back off and retry.
You can receive three different kinds of failure. Check the error.source field to tell them apart.
| What you see | Meaning |
|---|---|
JSON with "error": {"source": "gateway", ...} |
Rejected by the gateway before reaching the data: missing or invalid key (403), over your limit (429), unknown path (403 MISSING_AUTHENTICATION_TOKEN), or a gateway timeout (504) |
JSON with "error": {"source": "cloudflare", ...} |
The data source rejected or failed the request (403 or 502) |
| HTTP 200 with an error inside the body | The data source hit an internal problem but still answered 200. Treat a 200 whose body contains a top-level error string as a failure. An unknown ID returns {} |
Always log the requestId from an error. LCS can use it when you report a problem.
MM/DD/YYYY form; timestamps look like 03/26/2026 09:36:14 AM. Times of day are not
captured for bill history entries, so several actions on one day have no reliable order.active use "T" and "F" strings.session_laws_files is an empty string "" when there is none and an
object when there is; schedule order can be a number or a string. Handle both.leg.state.co.us pages. Please preserve them and
attribute the source.| Base URL | Notes | |
|---|---|---|
| Production | https://api.coleg.gov/v1 |
Live data |
| Test | https://<api-id>.execute-api.us-west-2.amazonaws.com/test, provided with your test key |
For integration testing. Use the same paths as Production after the base URL (there is no /v1 segment in the Test URL). Data is test data and may differ or change without notice. Keys are issued separately for each environment |
Returns the bill numbers modified since {since}. Fetch each with GET /bills/{billNumber}.
| since required | string Example: 2026-09-01T00:00:00Z A UTC timestamp such as |
[- "HB26-1178",
- "SB26-086",
- "SB26-001"
]Same as above, limited to one session. Use 0 for {since} to list every bill in the session.
| since required | string Example: 2026-09-01T00:00:00Z A UTC timestamp such as |
| sessionId required | string Example: 2026A A session such as |
[- "string"
]The complete record for one bill. This single response carries almost everything most consumers need: status, sponsors, committee assignments, history, votes and every document group.
Status is bill_status plus summarized_history. progress_bar shows lifecycle position: when the
last step's end is "T" the bill has concluded, and active is "F".
An unknown bill number returns {} with HTTP 200.
| billNumber required | string Example: HB26-1178 A bill number such as |
{- "bill_num": "HB26-1178",
- "lls_num": "26-0264",
- "origin": "House",
- "short_title": "string",
- "full_bill_topic": "string",
- "long_title": "string",
- "special_type": "string",
- "bill_category": "string",
- "bill_sub_category": "string",
- "bill_sub_sub_category": "string",
- "is_budget_package": "Yes",
- "subject": [
- "State Revenue & Budget"
], - "bill_status": "Signed into Law",
- "sponsors": [
- {
- "id": "KB002",
- "title": "Representative",
- "first_name": "string",
- "last_name": "string",
- "full_name": "string",
- "s_type": "Prime Sponsor",
- "chamber": "House",
- "sponsor_order": "string"
}
], - "committees": [
- {
- "id": "H_APP_2026A",
- "chamber": "string",
- "name": "string"
}
], - "first_chamber_third_reading_date": "string",
- "second_chamber_third_reading_date": "string",
- "summarized_history": [
- {
- "date": "03/26/2026",
- "location": "Governor",
- "action": "Governor Signed"
}
], - "progress_bar": [
- {
- "position": 0,
- "label": "Became Law",
- "end": "T"
}
], - "active": "T",
- "session": "2026A",
- "allow_testimony": "T",
- "long_bill_files": [
- {
- "date": "03/26/2026",
- "lastModified": "03/27/2026 09:36:14 AM",
- "label": "Signed Act",
- "label_detailed": "string",
- "url_html": "string"
}
], - "bill_files": [
- {
- "date": "03/26/2026",
- "lastModified": "03/27/2026 09:36:14 AM",
- "label": "Signed Act",
- "label_detailed": "string",
- "url_html": "string"
}
], - "fiscal_note_files": [
- {
- "date": "03/26/2026",
- "lastModified": "03/27/2026 09:36:14 AM",
- "label": "Signed Act",
- "label_detailed": "string",
- "url_html": "string"
}
], - "research_note_files": [
- {
- "date": "03/26/2026",
- "lastModified": "03/27/2026 09:36:14 AM",
- "label": "Signed Act",
- "label_detailed": "string",
- "url_html": "string"
}
], - "budget_staff_analysis_files": [
- {
- "date": "03/26/2026",
- "lastModified": "03/27/2026 09:36:14 AM",
- "label": "Signed Act",
- "label_detailed": "string",
- "url_html": "string"
}
], - "preamended_files": [
- {
- "date": "03/26/2026",
- "lastModified": "03/27/2026 09:36:14 AM",
- "label": "Signed Act",
- "label_detailed": "string",
- "url_html": "string"
}
], - "committee_report_files": [
- {
- "date": "03/26/2026",
- "lastModified": "03/27/2026 09:36:14 AM",
- "label": "Signed Act",
- "label_detailed": "string",
- "url_html": "string"
}
], - "updated_bill_summary_files": [
- {
- "date": "03/26/2026",
- "lastModified": "03/27/2026 09:36:14 AM",
- "label": "Signed Act",
- "label_detailed": "string",
- "url_html": "string"
}
], - "demographic_note_files": [
- {
- "date": "03/26/2026",
- "lastModified": "03/27/2026 09:36:14 AM",
- "label": "Signed Act",
- "label_detailed": "string",
- "url_html": "string"
}
], - "GHG_report_files": [
- {
- "date": "03/26/2026",
- "lastModified": "03/27/2026 09:36:14 AM",
- "label": "Signed Act",
- "label_detailed": "string",
- "url_html": "string"
}
], - "amendment_files": [
- {
- "date": "03/26/2026",
- "lastModified": "03/27/2026 09:36:14 AM",
- "label": "Signed Act",
- "label_detailed": "string",
- "url_html": "string"
}
], - "bill_summary": "string",
- "session_laws_files": "",
- "votes": [
- {
- "vote_id": "string",
- "chamber": "SENATE",
- "action": "Third Reading",
- "date": "02/20/2026",
- "vote_date_time": "02/20/2026 09:41:40 AM",
- "lay_over_date": "string",
- "motion": "BILL",
- "vote_yes": 0,
- "vote_no": 0,
- "vote_others": 0,
- "vote_abs": 0,
- "vote_exc": 0,
- "vote_17C": 0,
- "vote_17D": 0,
- "vote_result": "Aye: 32 No: 1 Other: 1",
- "voice_vote": "Y",
- "member_votes": [
- {
- "last_name": "string",
- "vote": "string"
}
]
}
]
}| since required | string Example: 2026-09-01T00:00:00Z A UTC timestamp such as |
| sessionId required | string Example: 2026A A session such as |
[- {
- "commid": "H_APP_2026A"
}
]| committeeId required | string Example: S_TRA_2026A A committee ID from the list endpoints. The format is |
{- "committee_id_session": "S_TRA_2026A",
- "generic_id": "S_TRA",
- "committee_type": "Committee of Reference",
- "committee_name": "string",
- "chamber": "string",
- "committee_abbrev": "string",
- "display_member_page": "string",
- "committee_staff": [
- {
- "staff_name": "string",
- "staff_phone": "string"
}
], - "committee_staff_email": "string",
- "committee_session": "string",
- "committee_meetings": [
- {
- "meeting_day": "string",
- "meeting_time": "string",
- "meeting_location": "string"
}
], - "alternate_meeting_day_language": "string",
- "committee_members": [
- {
- "m_member_id": "string",
- "title": "string",
- "full_name": "string",
- "last_name": "string",
- "position": "Chair",
- "legislator": "Yes"
}
], - "committee_description": "string",
- "committee_subject": [
- "string"
], - "twitter_handle": "string",
- "granicus_id": 0,
- "sliq_id": 0
}Returns one entry per committee that has meetings, listing every meeting date and its meeting ID as
parallel arrays. The committee names here come from a broader set than /committees/info; they
include conference committees keyed by bill number.
| since required | string Example: 2026-09-01T00:00:00Z A UTC timestamp such as |
[- {
- "committee_name": "H_APP_2026A",
- "meeting_dates": [
- "2026-05-01T08:04:57Z"
], - "meeting_uids": [
- "H_APP_2026A_20260501_080457"
]
}
]The full summary of a single meeting, including per-member votes with member IDs.
| meetingUid required | string Example: CC_HB26-1084_2026A_20260429_080744 A meeting ID from |
{- "meeting_date": "04/29/2026",
- "meeting_time": "08:07:44 AM",
- "committee_id": [
- "string"
], - "meeting_uid": "string",
- "meeting_room": "string",
- "members": [
- {
- "member_id": "string",
- "title": "string",
- "full_name": "string",
- "attendance": "Present"
}
], - "committee_actions": [
- {
- "bill_item": "string",
- "bill_action": "string"
}
], - "attachments": [
- {
- "tag": "string",
- "url": "string"
}
], - "bill_summaries": [
- {
- "bill_num": "string",
- "bill_action": "string",
- "bill_summ_url": "string",
- "vote_summaries": [
- {
- "bill_num": "string",
- "vote_time": "string",
- "vote_motion": "string",
- "vote_result": "string",
- "vote_moved": "string",
- "vote_seconded": "string",
- "number_yes": 0,
- "number_no": 0,
- "number_absent": 0,
- "number_excused": 0,
- "final_action": "PASS",
- "member_votes": [
- {
- "member_id": "string",
- "full_name": "string",
- "vote": "Yes"
}
]
}
]
}
]
}Returns the same record as /committees/summary/mId/{meetingUid}, addressed by committee and meeting time.
| committeeId required | string Example: CC_HB26-1084_2026A |
| meetingDateTime required | string Example: 2026-04-29T08:07:44Z The meeting time from |
{- "meeting_date": "04/29/2026",
- "meeting_time": "08:07:44 AM",
- "committee_id": [
- "string"
], - "meeting_uid": "string",
- "meeting_room": "string",
- "members": [
- {
- "member_id": "string",
- "title": "string",
- "full_name": "string",
- "attendance": "Present"
}
], - "committee_actions": [
- {
- "bill_item": "string",
- "bill_action": "string"
}
], - "attachments": [
- {
- "tag": "string",
- "url": "string"
}
], - "bill_summaries": [
- {
- "bill_num": "string",
- "bill_action": "string",
- "bill_summ_url": "string",
- "vote_summaries": [
- {
- "bill_num": "string",
- "vote_time": "string",
- "vote_motion": "string",
- "vote_result": "string",
- "vote_moved": "string",
- "vote_seconded": "string",
- "number_yes": 0,
- "number_no": 0,
- "number_absent": 0,
- "number_excused": 0,
- "final_action": "PASS",
- "member_votes": [
- {
- "member_id": "string",
- "full_name": "string",
- "vote": "Yes"
}
]
}
]
}
]
}Every current legislator with full detail in one response, including party (affiliation), district,
chamber and leadership title (special_position). This is the easiest way to join a legislator ID
from a bill's sponsors to a party and district: fetch it once and cache it.
[- {
- "member_id": "LG005",
- "prefix": "string",
- "suffix": "string",
- "first_name": "string",
- "middle_name": "string",
- "last_name": "string",
- "name_line": "string",
- "display_name1": "string",
- "display_name2": "string",
- "special_position": "string",
- "special_position_order": "string",
- "affiliation": "Democrat",
- "occupation": "string",
- "chamber": "House",
- "district": "string",
- "counties": [
- "string"
], - "phone": "string",
- "email": "string",
- "website": "string",
- "session": "2026A",
- "organisation_name": "string",
- "administrative_area": "string",
- "locality": "string",
- "postal_code": "string",
- "thoroughfare": "string",
- "premise": "string",
- "country": "string",
- "all_sessions": [
- {
- "session": "string",
- "chamber": "string",
- "district": 0,
- "member_id": "string",
- "full_name": "string",
- "party": "string",
- "leadership_title": "string"
}
]
}
]Use 0 for {since} to list every legislator back to 2016.
| since required | string Example: 2026-09-01T00:00:00Z A UTC timestamp such as |
[- {
- "memberId": "LG005"
}
]Full details for the current or most recent session, plus all_sessions with the legislator's history across sessions.
| memberId required | string Example: LG005 |
{- "member_id": "LG005",
- "prefix": "string",
- "suffix": "string",
- "first_name": "string",
- "middle_name": "string",
- "last_name": "string",
- "name_line": "string",
- "display_name1": "string",
- "display_name2": "string",
- "special_position": "string",
- "special_position_order": "string",
- "affiliation": "Democrat",
- "occupation": "string",
- "chamber": "House",
- "district": "string",
- "counties": [
- "string"
], - "phone": "string",
- "email": "string",
- "website": "string",
- "session": "2026A",
- "organisation_name": "string",
- "administrative_area": "string",
- "locality": "string",
- "postal_code": "string",
- "thoroughfare": "string",
- "premise": "string",
- "country": "string",
- "all_sessions": [
- {
- "session": "string",
- "chamber": "string",
- "district": 0,
- "member_id": "string",
- "full_name": "string",
- "party": "string",
- "leadership_title": "string"
}
]
}There is no changed-since endpoint for schedules; fetch them directly.
type = floor or committee returns the most recently published calendar for the chamber, with
events. events can legitimately be empty (for example, no floor session scheduled). In an event's
e_details, bill_or_text is "B" when hearing_item is a bill number and "T" when it is free
text. Cancellation and postponement status is not provided.
type = journal or ss returns a link to a single PDF instead of events. journal is the
cumulative journal for the current session; ss is the status sheet. The response is an array of
DocumentLink, not a Calendar.
| chamber required | string Enum: "house" "senate" |
| type required | string Enum: "floor" "committee" "journal" "ss" |
{- "publish_date_time": "8/5/2026 1:21:26 PM",
- "calendar_date_time": "string",
- "events": [
- {
- "event_id": "H01",
- "e_date": "08/05/2026",
- "e_time": "09:00 AM",
- "e_newKey": "string",
- "e_title": [
- {
- "id": "O_ETH_2026A",
- "display_title": "string"
}
], - "e_loc": "HCR 0112",
- "e_chamber": "string",
- "e_agendaurl": "string",
- "e_details": [
- {
- "order": 0,
- "bill_or_text": "B",
- "hearing_item": "string",
- "addendum_text": "string"
}
]
}
]
}{- "Ballots": [
- {
- "ballot_status": "Ballot Analysis Active",
- "key": "2026-Initiative_195",
- "old_key": "string",
- "ballot_reference": "Initiative 195",
- "ballot_title": "string",
- "ballot_type": "Statutory",
- "election_cycle": "2025-2026",
- "election_year": "string",
- "email": "string",
- "research_staff": [
- "string"
], - "fiscal_analyst": "string",
- "ballot_files": [
- {
- "file_type": "Text of Measure",
- "lastModified": "string",
- "mailing_date": "string",
- "comment_due": "string"
}
]
}
]
}| key required | string Example: 2026-Initiative_195 A key from the list endpoints: |
{- "ballot_status": "Ballot Analysis Active",
- "key": "2026-Initiative_195",
- "old_key": "string",
- "ballot_reference": "Initiative 195",
- "ballot_title": "string",
- "ballot_type": "Statutory",
- "election_cycle": "2025-2026",
- "election_year": "string",
- "email": "string",
- "research_staff": [
- "string"
], - "fiscal_analyst": "string",
- "ballot_files": [
- {
- "file_type": "Text of Measure",
- "lastModified": "string",
- "mailing_date": "string",
- "comment_due": "string"
}
]
}{- "initiatives": [
- {
- "key": "2026-195",
- "initiative_title": "string",
- "election_cycle": "string",
- "election_year": "string",
- "number": "string",
- "initiative_type": "Constitutional, Statutory",
- "date_submitted": "12/23/2025",
- "initiative_status": "string",
- "initiative_status_current": "string",
- "proponents": [
- {
- "proponent_type": "Primary",
- "name": "string",
- "address": "string"
}
],
}
]
}Initiatives and ballot measures track the same underlying measures at different stages
(for example 2026-195 here and 2026-Initiative_195 under ballot measures). To follow a measure
through its lifecycle, query both and match on year and number.
| key required | string Example: 2026-195 A key such as |
{- "key": "2026-195",
- "initiative_title": "string",
- "election_cycle": "string",
- "election_year": "string",
- "number": "string",
- "initiative_type": "Constitutional, Statutory",
- "date_submitted": "12/23/2025",
- "initiative_status": "string",
- "initiative_status_current": "string",
- "proponents": [
- {
- "proponent_type": "Primary",
- "name": "string",
- "address": "string"
}
],
}