Zion Boggan
repos/Docket/docs/API.md
zionboggan.com ↗
49 lines · markdown
History for this file →
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).