Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
File size: 5,516 Bytes
4aa353b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | # HTTP API
All backend routes live under `/api/` and are served by FastAPI. In
production, the browser hits them same-origin via a Next.js rewrite; in
dev they're at `http://localhost:8000/api/...`. Full auto-generated docs
are always at `http://localhost:8000/docs` (Swagger UI).
## Public endpoints (no auth)
### Health / readiness
| Method | Path | Response |
|---|---|---|
| GET | `/api/health` | `{status, data_dir, data_dir_exists}` β always 200 if process is up |
| GET | `/api/ready` | `{ready, checks, bills_count}` β 200 if data is loaded, 503 otherwise |
### Bills
| Method | Path | Notes |
|---|---|---|
| GET | `/api/bills` | List bills. Query: `state`, `status`, `session_year`, `category`, `search`, `limit`, `offset` |
| GET | `/api/bills/stats` | Totals: `{total_bills, federal_bills, state_bills, most_active_state, last_updated_at}` |
| GET | `/api/bills/filters` | Dropdown data: `{states, statuses, years, categories}` |
| GET | `/api/bills/{bill_id}` | Full bill detail (used by the row-detail modal) |
| GET | `/api/bills/by-state` | `{STATE: count}` for the choropleth. Optional `?year=YYYY` |
| GET | `/api/bills/export.csv` | Filtered CSV download (same filters as `/api/bills`) |
### Insights
| Method | Path |
|---|---|
| GET | `/api/insights/by-state?limit=N` |
| GET | `/api/insights/by-category?limit=N` |
| GET | `/api/insights/over-time` |
### Calendar
| Method | Path | Notes |
|---|---|---|
| GET | `/api/calendar` | Month view. Query: `year`, `month`, `types[]` |
| GET | `/api/calendar/upcoming` | Next N days. Query: `days` (default 7, max 30) |
### Newsletter
| Method | Path | Notes |
|---|---|---|
| GET | `/api/newsletters` | List available dates |
| GET | `/api/newsletters/{date}` | Markdown of one newsletter |
| GET | `/api/newsletters/{date}/changes` | Weekly changes CSV rows for that date |
| GET | `/api/newsletters/{date}/digest` | Stats + in-motion bills for the hero + Bills in Motion sections |
| GET | `/api/newsletters/{date}/featured-bill` | "Bill of the Week" β scored pick from the week's changes |
| GET | `/api/newsletters/{date}/category-trends` | Top IAPP categories affected this week |
### States
| Method | Path |
|---|---|
| GET | `/api/states/featured` |
| GET | `/api/states/{state}/spotlight?key_bills=N` |
### Feedback / subscribe
| Method | Path | Body |
|---|---|---|
| POST | `/api/feedback` | `{name?, email?, type, description}` |
| POST | `/api/newsletter/subscribe` | `{email}` |
| POST | `/api/newsletter/unsubscribe` | `{email}` |
### AI tools
| Method | Path | Body |
|---|---|---|
| GET | `/api/ai/bills/list` | Bills available in the AI tools dropdown |
| GET | `/api/ai/bill/{state}/{bill_number}` | Bill + summary + suggested questions + has_report flag |
| GET | `/api/ai/report/{state}/{bill_number}` | Pre-generated report markdown |
| POST | `/api/ai/qa` | `{state, bill_number, question}` |
| POST | `/api/ai/compare` | `{focus_state, focus_bill_number, compare[], question}` |
| POST | `/api/ai/eu-compare` | `{state, bill_number, question}` |
## Auth
| Method | Path | Notes |
|---|---|---|
| POST | `/api/auth/login` | `{username, password}` β `{token, username, name}` |
| GET | `/api/auth/me` | Current user; requires `Authorization: Bearer <token>` |
| POST | `/api/auth/logout` | Client discards the token |
## Admin endpoints
All under `/api/admin/*`. Require `Authorization: Bearer <jwt>` where the
JWT was issued by `/api/auth/login`. Enforced by the `require_admin`
dependency in every admin route.
### Overview
| Method | Path | Notes |
|---|---|---|
| GET | `/api/admin/overview` | Card counts, including `new_feedback_count` (fed to the nav badge) |
### Users
| Method | Path | Body |
|---|---|---|
| GET | `/api/admin/users` | List |
| POST | `/api/admin/users` | `{username, name, email, password}` |
| PATCH | `/api/admin/users/{username}` | `{name?, email?, password?}` (any subset) |
| DELETE | `/api/admin/users/{username}` | |
### Subscribers
| Method | Path |
|---|---|
| GET | `/api/admin/subscribers` |
| DELETE | `/api/admin/subscribers/{email}` |
### Feedback
| Method | Path | Body |
|---|---|---|
| GET | `/api/admin/feedback` | |
| PATCH | `/api/admin/feedback/{id}` | `{status}` β one of `new`, `read`, `resolved` |
| DELETE | `/api/admin/feedback/{id}` | |
### Pipeline
| Method | Path | Body / Notes |
|---|---|---|
| GET | `/api/admin/pipeline/status` | Current or last run |
| GET | `/api/admin/pipeline/history?limit=N` | Last N runs |
| GET | `/api/admin/pipeline/scripts` | The 14 step list with names + indices |
| GET | `/api/admin/pipeline/log?tail=N` | Last N lines of the pipeline log |
| POST | `/api/admin/pipeline/run` | `{pull?, test?, test_count?, start_from?, stop_after?, reset_vectorstore?, upload_to_hf?}` (all optional) |
| POST | `/api/admin/pipeline/cancel` | Kills the running subprocess group |
| POST | `/api/admin/pipeline/rebuild-manifest` | Standalone `rebuild_vectorstore_manifest.py` run |
### Weekly changes
| Method | Path |
|---|---|
| GET | `/api/admin/weekly-changes` |
| GET | `/api/admin/weekly-changes/{week_of}` |
## Error format
Errors follow FastAPI's default `{"detail": "..."}` shape. Server-side
5xx errors also include a `request_id` β a short hex string echoed in
the `X-Request-ID` response header. When a user reports an error, ask
for the request ID and grep the backend logs for `rid=<id>`.
## Rate limiting
None currently. Add one at the ingress layer (HF's edge) if traffic ever
warrants it.
|