API Migration Guide
Migrate from the legacy KLISS API (v1 through v13 at /li/api/vN/) to the new API at /api/v1/. If you're seeing a Deprecation header on your API responses, you're in the right place.
Timeline
| Phase | Period | What happens |
|---|---|---|
| Parallel | Now – Aug 1, 2026 | Both APIs run side-by-side. Migrate at your own pace. |
| Redirects | Aug 1 – Nov 1, 2026 | Legacy endpoints return 301 redirects where a 1:1 mapping exists. |
| Sunset | After Nov 1, 2026 | Legacy endpoints return 410 Gone. The new API is the only option. |
The five things that changed
| # | Legacy (v1–v13) | New (v1) |
|---|---|---|
| 1 | No authentication | Optional API key for higher rate limit (Authorization: Api-Key <key>) |
| 2 | No rate limit | 30 req/min without key; 300 req/min with key |
| 3 | Base URL: http://kslegislature.org/li/api/vN/ | Base URL: https://kslegislature.gov/api/v1/ |
| 4 | Pagination via next link (often "disabled") | ?limit=N&offset=N query parameters |
| 5 | Biennium baked into URL path (/rev-1/) | ?biennium=b2025_26 query parameter (defaults to current) |
openapi-generator (or your language's equivalent) to autogenerate
a typed SDK instead of hand-rolling HTTP calls — much faster than the
legacy API's "read the example, hope the shape holds" workflow.
1. Getting an API key
The new API works without a key (throttled to 30 requests/minute). An API key raises this to 300 requests/minute.
- Visit /api/request-key/.
- Fill out: name, email, organization, and how you plan to use the API.
- Wait for approval — typically one business day.
- You'll receive the key by email with usage instructions.
Include it as an HTTP header on every request:
Authorization: Api-Key <your-key>
cURL example:
curl -H 'Authorization: Api-Key abc123...' \
https://kslegislature.gov/api/v1/bill_status/HB2001/
Python example:
import requests
headers = {'Authorization': 'Api-Key abc123...'}
r = requests.get('https://kslegislature.gov/api/v1/bill_status/HB2001/',
headers=headers)
data = r.json()
2. The easy path: bill_status drop-in
If your code uses bill_status/ (any version), the new API has a purpose-built replacement that matches the v13 response shape. For many consumers this is a two-line change:
- url = 'http://kslegislature.org/li/api/v13/rev-1/bill_status/HB2001/' - r = requests.get(url) + url = 'https://kslegislature.gov/api/v1/bill_status/HB2001/' + r = requests.get(url, headers={'Authorization': 'Api-Key <key>'})
The response carries the same fields: BILLNO, SHORTTITLE, LONGTITLE, SPONSOR_NAMES, STATUS, HISTORY (with action_code, chamber, journal_page_number, occurred_datetime, status, committee_names, amendment_report), and versions.
results (not content) for consistency with all other endpoints. No /rev-1/ prefix — the new API does not use revision numbers. It always returns current data; use ?biennium= for historical sessions./rev-1/ between the version number and the endpoint path (e.g., /li/api/v13/rev-1/bill_status/). Versions 1–4 do not use this segment. The new API has no revision concept at all.3. Endpoint mapping (all resources)
| Legacy path | New path |
|---|---|
/li/api/v1-v4/bill_status/ | /api/v1/bill_status/ |
/li/api/v5-v13/rev-1/bill_status/ | /api/v1/bill_status/ |
/li/api/v5-v13/rev-1/bill_status/<bill_no>/ | /api/v1/bill_status/<bill_no>/ |
/li/api/v5+/rev-1/bill_listing/ | /api/v1/measures/ |
/li/api/v5+/rev-1/calendar/ | /api/v1/daily-calendars/ |
/li/api/v5+/rev-1/calendar/house/ | /api/v1/daily-calendars/?chamber=house |
/li/api/v5+/rev-1/calendar/senate/ | /api/v1/daily-calendars/?chamber=senate |
/li/api/v5+/rev-1/journal/ | /api/v1/daily-journals/ |
/li/api/v5+/rev-1/journal/house/ | /api/v1/daily-journals/?chamber=house |
/li/api/v5+/rev-1/journal/senate/ | /api/v1/daily-journals/?chamber=senate |
/li/api/v5+/rev-1/ctte/ | /api/v1/committees/ |
/li/api/v5+/rev-1/ctte/<kpid>/ | /api/v1/committees/<kpid>/ |
/li/api/v6+/rev-1/members/ | /api/v1/legislators/ |
/li/api/v6+/rev-1/members/house/ | /api/v1/legislators/?chamber=house |
/li/api/v6+/rev-1/members/senate/ | /api/v1/legislators/?chamber=senate |
/li/api/v6+/rev-1/members/<kpid>/ | /api/v1/legislators/<kpid>/ |
/li/api/v6+/rev-1/chamber_status/ | /api/v1/chamber_status/ |
/li/api/v7+/rev-1/appt/ | /api/v1/appointments/ |
/li/api/v7+/rev-1/appt/<apptno>/ | /api/v1/appointments/<apptno>/ |
/li/api/v8+/rev-1/events/ | /api/v1/events/ |
| (new) | /api/v1/leadership/ |
| (new) | /api/v1/session-days/ |
| (new) | /api/v1/votes/ — roll-call votes with tallies and the originating journal entry; detail endpoint returns per-member yea/nay/absent |
| (new) | /api/v1/testimony/ — submitted committee testimony with position (proponent/opponent/neutral) and download URLs |
| (new) | /api/v1/fiscal-notes/, /api/v1/supplemental-notes/ — published notes by bill |
| (new) | /api/v1/conference-committees/ — conference committee meeting schedule with bill assignments |
| (new) | /api/v1/hearings/, /api/v1/hearings/<slug>/ — committee hearings list + detail (stream URL, bills, testimony, minutes) |
| (new) | /api/v1/subjects/ — legislative subject index (list, by-topic, by-bill) |
| (new) | /api/v1/governor-actions/ — bills classified by gubernatorial outcome (signed, vetoed, override, etc.); active + archive biennia |
| (new) | /api/v1/statutes/, /api/v1/statutes/<section>/, /api/v1/statutes/<section>/affected-by/ — K.S.A. browse and bill-to-statute cross-reference |
| (new) | /api/v1/measures/<bill>/statutes-affected/, /api/v1/measures/<bill>/text/ — statutes a bill amends; plain-text bill body |
| (new) | /api/v1/legislators/<kpid>/sponsorships/, /api/v1/legislators/<kpid>/voting-record/ — per-legislator rollups |
| (new) | /api/v1/search/ — full-text search across bills, statutes, and committee documents |
| (new) | /api/v1/now/ — live activity snapshot for ticker-style polling (30–60s cadence) |
| (new) | /api/v1/biennia/ — list of biennia served by this site (use to drive ?biennium= rather than hard-coding) |
4. Response format changes
Legacy v1 through v4
Responses were bare JSON arrays or objects. The new API always wraps content with metadata:
{
"count": 1480,
"next": "https://kslegislature.gov/api/v1/measures/?limit=100&offset=100",
"previous": null,
"results": [ ... ]
}
Field name changes (v4 → v5+)
v5 of the legacy API renamed several keys. If your code still uses v1–v4 field names, update to the v5+ spelling (preserved in the new API):
| Old (v1–v4) | New (v5+, kept in new API) |
|---|---|
bill_number | BILLNO |
long_title | LONGTITLE |
short_title | SHORTTITLE |
sponsor_names | SPONSOR_NAMES |
history | HISTORY |
rs_number | RELATEDRS |
status (bill-level) | STATUS |
5. Pagination
The legacy API used a next link that was often set to "disabled". The new API uses standard limit/offset pagination:
GET /api/v1/measures/?limit=100&offset=0
Loop until next is null to fetch all records:
def fetch_all(url, headers):
results = []
while url:
r = requests.get(url, headers=headers)
data = r.json()
results.extend(data['results'])
url = data['next']
return results
6. Biennium scoping
Legacy URLs encoded the biennium in the path (/li_2022/). The new API uses a query parameter that defaults to the current active biennium:
/api/v1/bill_status/ # current biennium /api/v1/bill_status/?biennium=b2023_24 # historical biennium /api/v1/measures/?biennium=b2023_24 # works on every endpoint
7. RSS & Atom feeds
RSS feeds moved from /li/feeds/rss/ to /feeds/rss/. No authentication required.
| Legacy path | New path |
|---|---|
/li/feeds/rss/events/ | /feeds/rss/events/ |
/li/feeds/rss/journal/ | /feeds/rss/journal/ |
/li/feeds/rss/calendar/ | /feeds/rss/calendar/ |
/li/feeds/rss/ctte/<kpid>/ | /feeds/rss/ctte/<kpid>/ |
/li/feeds/rss/members/<kpid>/ | /feeds/rss/members/<kpid>/ |
/li/feeds/rss/bills/ | /feeds/rss/bills/ |
| (new) | /feeds/rss/measure/HB2001/ |
Atom equivalents: replace /rss/ with /atom/ in any URL above. See /feeds/rsshelp/ for a full list with subscribe links.
8. Errors you may encounter
| HTTP code | Meaning | Fix |
|---|---|---|
| 401 | Invalid API key | Check Authorization header; must start with Api-Key |
| 403 | Key deactivated | Contact us to reactivate |
| 404 | Resource not found or wrong biennium | Double-check the ID; try ?biennium=b2023_24 for older records |
| 429 | Rate limit exceeded | Back off; honor the Retry-After header |
9. Deprecation headers on legacy responses
Every legacy API response now carries these headers:
Deprecation: true
Sunset: Sat, 01 Aug 2026 00:00:00 GMT
Link: <https://kslegislature.gov/api/docs/>; rel="successor-version",
<https://kslegislature.gov/api/docs/migration/>; rel="help"
If your HTTP client can log response headers, you can confirm you're still hitting the legacy API.
10. Getting help
If your use case isn't covered or you hit a bug during migration:
- Email [email protected]
- Reference your API key label (first 12 characters) when reporting issues
- Include the exact URL you called and the response body you received