Endpoints
Every route the API serves, grouped by collection, with its parameters. All of them are public reads except the two chat routes, which are the site's own.
At a glance
Every collection answers the same eight routes below https://api.georgiacommons.org/api/{collection}, where the collection is code, bills, or opinions. Learn these and the rest is each collection's own document addresses.
| Route | What it does |
|---|---|
| `` | The collection's root: its routes, and its coverage sentence with the qualifications. |
/meta | Coverage, counts, and corpus version, computed from the store at request time. |
/search | Full-text search. Add in=headings to search only headings and titles. |
/items?ids= | Up to 20 documents in one request. |
/verify | Whether a quotation appears verbatim in the stored text. POST. |
/index/markdown | The collection's map: every unit at routing depth, one line each. |
/about/markdown | Provenance, coverage, license, and the independence statement. |
/search/markdown | The same search as Markdown, about ten hits with snippets. |
/sitemap-entries | Document ids, for enumerating the collection. Bills and opinions give the whole list with dates; the Code pages it. |
Reads need no key and no account. The full rules for identifiers, caching, and rate limits are on getting started.
Bills
Bills of the Georgia General Assembly, addressed by session and number. The doubled segment in /api/bills/bills/... is not a typo: the first is the collection, the second the resource.
/api/{slug}A collection's root (/api/bills, /api/opinions, /api/code, /api/meetings): its routes, and its coverage sentence with the qualifications.
/api/bills/metaCoverage, counts, sessions, and corpus version.
lang:esfor the coverage sentence and qualifications in Spanish
/api/bills/recentBills with the newest activity first.
limit: 1 to 100, default 20offset: 0 to 10000lang:esfor the Spanish translations of the summaries; quotes and source fields stay in English
/api/bills/filteredThe same slim list, narrowed.
session: a session slug such as2025-2026chamber:HorSbill_type:B,R,CR, orJRstatus: a status code: 1 Introduced, 2 Engrossed, 3 Enrolled, 4 Passed, 5 Vetoed, 6 Failedq: at least two characterslimit,offset: as abovelang:esfor the Spanish translations of the summaries; quotes and source fields stay in English
/api/bills/searchFull-text search over bill text, titles, and the labeled summaries. A bare bill number is a direct lookup.
q: required, 1 to 300 charactersin:headingsto search only titles, tags, and subjectssession,chamber,bill_type,status: as abovelimit: 1 to 100, default 20lang:esfor the Spanish translations of the summaries; quotes and source fields stay in English
/api/bills/sessionsEvery session with its bill count.
/api/bills/sessions/{session}One session: counts by kind, its caption subjects, and a window of bills.
kind:hb,sb,hr, orsrstart: 0 or morelimit: 1 to 500, default 500lang:esfor the Spanish translations of the summaries; quotes and source fields stay in English
/api/bills/resolveWhere a written bill reference leads. Accepts HB 136, H.B. 136, hb-136, House Bill 136, with or without a session. With none, the newest regular session that has the number; also_in names the same number in other sessions.
q: 1 to 200 characters
/api/bills/resolve/markdownA redirect to the Markdown twin of the bill a written reference leads to, chosen as /resolve chooses. The site's /bills/hb136.md answers from it.
q: 1 to 200 charactersfull=1: as on the twin
/api/bills/bills/{session}/{number}One bill: sponsors, status, history, and the labeled summaries. The bill text is not included.
lang:esfor the Spanish translations of the summaries; quotes and source fields stay in English
/api/bills/bills/{session}/{number}/full-textThe stored bill text with minimal metadata, as JSON. paragraphs is the same text joined into paragraphs for display; only line breaks change. has_marks says whether the text carries amendment marks.
/api/bills/bills/{session}/{number}/textThe bill text alone as text/plain. The page and its twin are named in the Link header.
/api/bills/bills/{session}/{number}/markdownThe bill's Markdown twin: frontmatter, the text as filed, then the labeled summaries.
full=1: add history, votes, and amendments
/api/bills/itemsSeveral bills at once, with their text. Up to 20 a call; the response names the rest in next_ids.
ids: a comma-separated list, 1 to 2000 characterslang:esfor the Spanish translations of the summaries; quotes and source fields stay in English
/api/bills/votes/{vote_id}One floor vote on a stored bill: its totals, with vacant seats counted apart from members not voting, the bills it covered, and how each member voted, with party, chamber, and district. The id is a vote's roll_call_id in a bill's votes_json, whose detail_url points here. A 404 when the vote is not stored.
/api/bills/verifyWhether a quotation appears verbatim in the stored bill, after the same normalization the ingestion quote filter uses. in names the reading that matched: text (the words as printed), text_as_amended (struck passages left out), or text_before_amendment (added passages left out).
- body:
{"id": ..., "quote": ...} - quotes shorter than 12 characters are refused with a 422
/api/bills/index/markdownThe map: sessions with their counts, kinds, and caption subjects.
/api/bills/about/markdownProvenance, coverage, license, and the independence statement.
/api/bills/search/markdownThe same search as Markdown: about ten hits with an id, a title, a status, a snippet, and a URL.
q: the words; with none, the twin says how to searchsession,in: as abovelimit: 1 to 40, default 10
/api/bills/sessions/{session}/markdownOne session as Markdown, 250 bills a page.
type:hb,sb,hr, orsrstart: where the page begins
/api/bills/sitemap-entriesEvery bill id with its date. No ETag on this one.
/api/bills/bills/{bill_id}/askThe grounded question answering behind the chat panel on a bill page, streamed. This one route holds a server-side key and is not part of the public API.
Opinions
Opinions of the Supreme Court of Georgia, addressed by docket number. A record id (a CourtListener cluster id, or ga- and the docket for a record read from the court's own website) or a lower-case docket redirects to the docket address.
/api/opinions/metaCoverage, counts, years, and corpus version.
lang:esfor the coverage sentence and qualifications in Spanish
/api/opinions/recentOpinions with the newest filing date first.
limit: 1 to 100, default 20offset: 0 to 10000lang:esfor the Spanish translations of the summaries; quotes and source fields stay in English
/api/opinions/filteredThe same slim list, narrowed.
year: a comma-separated listcase_type: a comma-separated listq: at least two characterslimit,offset: as abovelang:esfor the Spanish translations of the summaries; quotes and source fields stay in English
/api/opinions/searchFull-text search over opinion text, case names, and the labeled summaries. A bare docket or reporter citation is a direct lookup.
q: required, 1 to 300 charactersin:headingsto search only names, legal areas, and case typeyear: 1900 to 2100case_typelimit: 1 to 100, default 20lang:esfor the Spanish translations of the summaries; quotes and source fields stay in English
/api/opinions/search-by-nameSearch case names alone. Prefix matches rank first.
q: at least two characterslimit: 1 to 100, default 20
/api/opinions/yearsEvery year with its opinion count.
/api/opinions/years/{year}One year: counts by case type and a window of opinions.
case_typestart: 0 or morelimit: 1 to 400, default 400lang:esfor the Spanish translations of the summaries; quotes and source fields stay in English
/api/opinions/resolveWhere a written reference leads. Accepts a docket in any case, a reporter citation in 883 S.E.2d 746, 883 SE2d 746, or 308 Ga. 283 form, a record id, or a case name.
q: 1 to 200 characters
/api/opinions/cases/{ref}One opinion by docket, citation, record id, or case name. The opinion text is not included. record_source says whether CourtListener or the court's website wrote the record.
lang:esfor the Spanish translations of the summaries; quotes and source fields stay in English
/api/opinions/cases/{docket}/{cluster_id}One opinion at its stable address, for the 77 dockets that carry more than one row.
full: add the summarized reasoning and the checked quoteslang:esfor the Spanish translations of the summaries; quotes and source fields stay in English
/api/opinions/cases/{docket}/{cluster_id}/textThe opinion text alone as text/plain.
/api/opinions/cases/{docket}/{cluster_id}/markdownThe opinion's Markdown twin: frontmatter, the court's text, then the labeled summaries.
full=1: add the reasoning, the checked quotes, and the upstream opinion recordsstart: one part of a long opinion's text, 60,000 characters at a time; a twin longer than that lists its parts
/api/opinions/cases/{docket}/{cluster_id}/full-textThe stored opinion text with its metadata, as JSON. paragraphs is the same text joined into paragraphs for display; only line breaks change.
/api/opinions/itemsSeveral opinions at once, with their text. Up to 20 a call.
ids: a comma-separated list, 1 to 2000 characterslang:esfor the Spanish translations of the summaries; quotes and source fields stay in English
/api/opinions/verifyWhether a quotation appears verbatim in the stored opinion.
- body:
{"id": ..., "quote": ...} - quotes shorter than 12 characters are refused with a 422
/api/opinions/index/markdownThe map: years with their counts and case types.
/api/opinions/about/markdownProvenance, coverage, license, and the independence statement.
/api/opinions/search/markdownThe same search as Markdown, about ten hits with snippets.
q: the words; with none, the twin says how to searchyear,case_type,in: as abovelimit: 1 to 40, default 10
/api/opinions/years/{year}/markdownOne year as Markdown, 400 opinions a page.
case_typestart: where the page begins
/api/opinions/sitemap-entriesEvery opinion id with its date. No ETag on this one.
/api/opinions/clusters/{cluster_id}/askThe grounded question answering behind the chat panel on an opinion page, streamed. This one route holds a server-side key and is not part of the public API.
The Code
The Official Code of Georgia Annotated, addressed by citation. Source text only: there is no chat route here, and no model anywhere in this path.
/api/code/metaCoverage sentence and its qualifications, counts, corpus version, release date, and the bulk download addresses.
/api/code/treeEvery title with its headings and counts, plus both constitutions.
/api/code/sections/{ref}One section by citation, written any of the ways people write it. Returns every version, whether it is in force now, and the neighboring sections. A range or a list redirects to /items?ids=.
version: one stored version rather than the current one
/api/code/sections/{ref}/textThe statute text alone as text/plain.
version
/api/code/sections/{ref}/markdownThe section's Markdown twin.
versionnotes=all: the printed notes in pages of 60,000 characters instead of the 12,000-character capstart: withnotes=all, where the page of notes begins; each page names the nextsubsection: one subsection, such asa-1
/api/code/titles/{title}One title's chapters, with its articles, parts, and subparts.
/api/code/titles/{title}/markdownThe title's map as Markdown.
/api/code/titles/{title}/chapters/{chapter}One chapter's sections, slim.
/api/code/titles/{title}/chapters/{chapter}/markdownThe chapter as Markdown.
full=1: inline the section text, under a 200,000-character capstart: where the page begins
/api/code/searchFull-text search of the Code. A bare citation is a direct lookup; an act's short title returns the section that states it.
q: required, 1 to 300 charactersin:headingsto search only catchlines and headingstitle: 1 to 99chapterstatus:active(the default),repealed,reserved,redesignated,superseded,note_only, orallscheme:ocga(the default),ga, oruslimit: 1 to 100, default 20
/api/code/actsThe short-title index: every name a statute gives itself, with the section that states it.
qlimit: 1 to 100, default 25
/api/code/itemsSeveral sections at once. Up to 20 ids, or a range of up to 40 sections, under a 300,000-character budget.
ids: a comma-separated list;44-7-30..44-7-35for a range
/api/code/verifyWhether a quotation appears verbatim in the stored text.
- body:
{"id": ..., "quote": ...} idis a citation, orga-const:{slug}orus-const:{slug}
/api/code/index/markdownThe map: 53 titles with their chapters, about 50 KB.
/api/code/about/markdownProvenance, coverage, license, and the independence statement.
/api/code/acts/markdownEvery short title, alphabetically, as Markdown, 300 a page.
start: where the page begins
/api/code/search/markdownThe same search as Markdown, about ten hits with snippets.
q: the words; with none, the twin says how to searchtitle,chapter,status,scheme,in: as abovelimit: 1 to 40, default 10
/api/code/bulkA JSON listing of the download bundle: the release page, the checksum file, and each asset with its address. Always a listing, never a redirect.
/api/code/bulk/{filename}One asset of the bundle.
/api/code/sitemap-entriesSection ids, a page at a time.
page: 0 or more; omit it for the list of pages
The constitutions
The Georgia and United States constitutions as printed in the Code, under the same collection. {scheme} is ga or us.
/api/code/constitution/{scheme}The articles and sections, plus any standalone provisions.
/api/code/constitution/{scheme}/index/markdownEvery provision, one line each.
/api/code/constitution/{scheme}/{citation}One provision, by slug (art-i-sec-i-para-i) or by citation.
/api/code/constitution/{scheme}/{citation}/markdownThe provision's Markdown twin.
notes=allstartsubsection
/api/code/constitution/{scheme}/{citation}/textThe provision's text alone as text/plain.
Meetings
Machine transcripts of Georgia House and Senate floor sessions, standing committee meetings, and Rules Committee meetings, with the summaries Georgia Commons wrote. A meeting is addressed by its date and body: {day} is 2026-02-05 and {name} is house-rules, senate-judiciary, or house-floor-am for a meeting recorded in parts. Transcripts are not official records, speakers are not identified, and the video on the General Assembly's Vimeo channel is the record. The doubled segment in /api/meetings/meetings/... is the collection, then the resource.
/api/meetings/metaCoverage, counts, years, the bodies, and corpus version, computed from the store.
lang:esfor the coverage sentence and qualifications in Spanish
/api/meetings/recentThe newest published meetings first, each with its summary.
limit: 1 to 100, default 20offset: 0 to 10000chamber:houseorsenatekind:floor,committee, orruleslang:esfor the Spanish summaries; transcripts stay in English
/api/meetings/searchFull-text search over the transcripts, the summaries, and the meetings' titles and committees, grouped by meeting. Each hit carries up to three moments of the transcript with their timestamps. A bill number alone (HB 629) lists the meetings that took the bill up, in direct.
q: required, 1 to 300 charactersin:headingsto search only titles and committee nameschamber,kind: as abovebody: a body such assenate-judiciarylimit: 1 to 50, default 20lang: as above
/api/meetings/resolveWhere a written meeting reference leads: an address (2026-02-05/house-rules), the General Assembly's video id or Vimeo URL, a date, a body, or a body and a date (House Rules 2/5/2026). Answers one meeting, the meetings to choose from, or a body.
q: 1 to 300 characters
/api/meetings/meetings/{day}/{name}One meeting: its body, date, the video address and the player to embed, the agenda, the session, the summary and the bill discussions (each bill named, each discussion with its moment in the video and the official record that confirms it), the official records of the meeting, and the meetings before and after. The transcript is not included. An address the meeting had before redirects.
lang:esfor the Spanish summaries; record quotes stay in English
/api/meetings/meetings/{day}/{name}/transcriptThe machine transcript as turns: seq, start_seconds, end_seconds, timestamp, the moment's video_url, and text.
start: the first turn, default 0limit: 1 to 5000, default 2000;next_startnames the next window
/api/meetings/meetings/{day}/{name}/textThe machine transcript alone as text/plain, one paragraph a turn led by its timestamp. The page and its twin are named in the Link header.
/api/meetings/meetings/{day}/{name}/markdownThe meeting's Markdown twin: frontmatter, the transcript notice, the labeled summary and bill discussions with one heading per bill, the bills read aloud, the official records, then the timestamped transcript.
start: one part of a long transcript, from this character; the frontmatter lists the parts
/api/meetings/bills/{bill_id}The published meetings that took up a bill (the General Assembly's bill_id, as /api/bills gives it), oldest first, each with the moment in its video, the summary of the discussion, and the record that confirms it. Empty when none did.
lang: as above
/api/meetings/itemsSeveral meetings at once, as the meeting route gives them. Up to 20 a call; missing names any not found.
ids: comma-separated addresses or video idslang: as above
/api/meetings/verifyWhether a quotation appears verbatim in a meeting's machine transcript, after the normalization the ingestion quote filter uses. A quote found is in the transcript; the video is what was said.
- body:
{"id": ..., "quote": ...}with the meeting's address or video id - quotes shorter than 12 characters are refused with a 422
/api/meetings/yearsEvery year with published meetings: its count, first and last dates, and hours of video.
/api/meetings/years/{year}One year: its days with their counts, and a window of its meetings in date order.
chamber,kind: as abovestart: 0 or morelimit: 1 to 500, default 100lang: as above
/api/meetings/years/{year}/markdownOne year as Markdown, 400 meetings a page.
start: where the page begins
/api/meetings/days/{day}One day's published meetings, each with its summary.
lang: as above
/api/meetings/days/{day}/markdownOne day as Markdown, each meeting with its summary.
/api/meetings/bodiesEvery body with published meetings (each chamber's floor, its Rules Committee, its standing committees): its slug, name, count, and dates.
/api/meetings/bodies/{body}One body's published meetings in date order.
start: 0 or morelimit: 1 to 500, default 100lang: as above
/api/meetings/bodies/{body}/markdownOne body's meetings as Markdown, 400 a page.
start: where the page begins
/api/meetings/index/markdownThe map: the coverage, every body, and every year with its days.
/api/meetings/about/markdownWhere the meetings come from, how the transcripts and summaries are made, coverage, and the independence statement.
/api/meetings/search/markdownThe same search as Markdown: about ten meetings with their summary snippets and matching moments.
q: the words; with none, the twin says how to searchin,chamber,kind,body: as abovelimit: 1 to 40, default 10
/api/meetings/sitemap-entriesEvery published meeting's address with its last change. No ETag on this one.
The API itself
Two routes that describe the service rather than a document.
/The API's own index: its version, the collections it serves, and where the MCP server is mounted.
/healthWhether the process is up and which collections are loaded, with each one's count and corpus version.