| 1 | # Docket - Internal API Contract |
| 2 | |
| 3 | Single-box deployment: Next.js app + SQLite (local, `/opt/docket/data/docket.db`) populated by the Python ingest. Frontend reads its OWN Next.js route handlers (`app/api/*`) via `better-sqlite3`. Backend agents write to the SQLite schema below; frontend consumes these JSON shapes. This is the contract - build to it on both sides. |
| 4 | |
| 5 | ## Conventions |
| 6 | - All responses JSON. Every item carries `sourceUrl` (allowlisted official `.gov`/state-leg host; aggregator → underlying official record). |
| 7 | - Pagination: `?limit=` (default 50, max 200) `&offset=`. Responses: `{ items: [...], total, limit, offset }`. |
| 8 | - Dates ISO-8601. Money in integer cents or a numeric `amount` + `amountText`. |
| 9 | - Ranking endpoints obey neutrality rule #3 (action date, dollar magnitude, affected estimate, action type only). |
| 10 | |
| 11 | ## Endpoints |
| 12 | |
| 13 | ### `GET /api/feed` |
| 14 | The Register. Mixed stream of official events, ranked (rule #3). |
| 15 | `?type=bill|vote|award|amendment|rider|procedural|executive|apportionment` (repeatable) `?state=US|CA|…` `?q=` |
| 16 | Item: `{ id, kind, actionDate, chamber, title, summary?, actionType, amount?, amountText?, jurisdiction, sourceUrl, href }` |
| 17 | |
| 18 | ### `GET /api/bills` · `GET /api/bills/:id` |
| 19 | List/lookup. `?q=&state=&status=&congress=&policyArea=&sort=updated|action` |
| 20 | Detail: `{ id, number, title, sponsor{name,party,state}, cosponsors, status, timeline[], policyArea, fullTextUrl, summaryPlain, versions[], diffs[], amendments[], votes[], sourceUrl }` |
| 21 | |
| 22 | ### `GET /api/bills/:id/diff?from=ih&to=rh` ← signature feature |
| 23 | `{ from, to, changes:[{ sectionId, change:"added|removed|amended", snippet, riderFlag:bool }], note? }` |
| 24 | `note` carries honesty text when a change entered via voice/UC/conference ("no individual record exists"). |
| 25 | |
| 26 | ### `GET /api/votes` · `GET /api/votes/:id` |
| 27 | `{ id, billId?, chamber, date, result, yea, nay, present, recorded:bool, positions:[{member,party,state,position}], sourceUrl }` |
| 28 | `recorded:false` → voice/UC; `positions` empty; UI shows "no individual record exists." |
| 29 | |
| 30 | ### `GET /api/spending/*` |
| 31 | `/api/spending/awards` (list), `/api/spending/fiscal` (debt/deficit/outlays), `/api/spending/apportionments` ← impound tracker: `{ agency, account, appropriated, apportioned, status:"released|delayed|withheld", date, sourceUrl }` |
| 32 | |
| 33 | ### `GET /api/executive` - Federal Register: EOs, rules, notices |
| 34 | ### `GET /api/lobbying?bill=` - LDA.gov filings |
| 35 | ### `GET /api/states` · `GET /api/states/:code` |
| 36 | `/api/states` returns coverage + confidence per state: `{ code, name, confidence:"ok|stale|missing", lastScrape, missingTypes[] }`. Detail = state bills/votes. |
| 37 | ### `GET /api/members/:id` - a rep's record (votes, sponsorships, riders authored) |
| 38 | ### `GET /api/search?q=` - global lookup across bills/members/states/awards |
| 39 | |
| 40 | ## Backend → DB contract |
| 41 | Ingest writes the tables in ARCHITECTURE.md "Data model" + "Full-spectrum additions". Each poller module is self-contained, does `CREATE TABLE IF NOT EXISTS`, is idempotent (dedupe on source+externalId+updateDate), and stores an allowlisted `source_url` on every row. Pollers do NOT modify `run.py` - the overseer wires registration. |
| 42 | |
| 43 | ## Keyless data paths (no api.data.gov key needed) |
| 44 | - **GovInfo BULK DATA** `https://www.govinfo.gov/bulkdata/` - BILLS, BILLSTATUS, BILLSUM, CREC (no key). Primary path for bills, status, full text, versions (diff inputs), and Congressional Record. |
| 45 | - **Federal Register** `federalregister.gov/api/v1` - no key. |
| 46 | - **OpenOMB** `openomb.org` - no key (link source to underlying `.max.gov`). |
| 47 | - **USAspending / Treasury Fiscal** - no key (already live). |
| 48 | - **House/Senate vote XML** - no key (already live for Senate). |
| 49 | Key-gated (build code now, run when key present): Congress.gov JSON, GovInfo JSON API (DOCKET_CONGRESS_KEY); OpenStates (DOCKET_OPENSTATES_KEY); LegiScan (DOCKET_LEGISCAN_KEY). |