Spaces:
Running
Running
File size: 4,350 Bytes
2fc729c | 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 | # REST API — read-only integration (Phase 3b)
The REST API exposes the same read-only handlers as the MCP server
(`services/mcp_handlers.py`). OpenAPI documentation is auto-generated at `/docs`.
## Install & run
```bash
pip install -r requirements.txt
pip install -r requirements-api.txt
python api_server.py
# default: http://127.0.0.1:8765
```
Or with uvicorn directly:
```bash
uvicorn api_server:app --host 127.0.0.1 --port 8765
```
## Authentication (optional)
Set `FORECASTER_API_KEY` in the environment to require the `X-API-Key` header on
every request. When unset, the API is open (local development only).
```bash
export FORECASTER_API_KEY=your-secret-here
curl -H "X-API-Key: your-secret-here" http://127.0.0.1:8765/v1/scoreboard
```
Never commit API keys. Prefer environment variables over `config.yaml`.
## Rate limiting
Configured in `config.yaml` → `api.rate_limit_per_minute` (default: 60).
In-memory per-IP sliding window; single-process only.
## Endpoints
| Method | Path | Description |
|--------|------|-------------|
| GET | `/health` | Liveness + auth mode |
| GET | `/v1/scoreboard` | Brier calibration scoreboard |
| GET | `/v1/ood` | OOD assessment (`scenario_json`, `n_bootstrap` query params) |
| POST | `/v1/ood` | OOD with JSON body `{ "scenario": {...}, "n_bootstrap": 50 }` |
| GET | `/v1/jobs/search` | Job hybrid RAG search (query params) |
| POST | `/v1/jobs/search` | Job search with JSON body |
| GET | `/v1/predictions/open` | Open predictions (`limit` query param) |
| GET | `/v1/predictions/{id}/contribute` | **Blind** target for crowd submit (no agent prior) |
| POST | `/v1/predictions/{id}/contributions` | Submit crowd forecast + argument + evidence |
| GET | `/v1/predictions/{id}/crowd` | Crowd aggregate (requires `contributor_id` who has submitted) |
| GET | `/docs` | Swagger UI |
| GET | `/openapi.json` | OpenAPI 3 schema |
## Examples
```bash
# Calibration scoreboard
curl http://127.0.0.1:8765/v1/scoreboard
# OOD (fast bootstrap for dev)
curl "http://127.0.0.1:8765/v1/ood?n_bootstrap=5"
# Job search
curl "http://127.0.0.1:8765/v1/jobs/search?query=risk%20analyst&industry=Finance&limit=5"
# Open predictions
curl "http://127.0.0.1:8765/v1/predictions/open?limit=10"
```
POST scenario override:
```bash
curl -X POST http://127.0.0.1:8765/v1/ood \
-H "Content-Type: application/json" \
-d '{"scenario": {"augmentation_ratio": 0.9, "diffusion_years": 3}, "n_bootstrap": 10}'
```
## Scenario variables
Optional overrides merge onto `evolution.CURRENT_AI_SCENARIO`:
- `augmentation_ratio`, `demand_elasticity`, `oring_leverage`, `skill_distance`
- `diffusion_years`, `absorbing_sector`, `productivity_capture`, `task_frontier_open`
## Crowd contributions (Phase 2)
Anti-anchoring flow:
1. `GET /v1/predictions/{id}/contribute` — returns statement + resolution criteria only
2. `POST /v1/predictions/{id}/contributions` — submit; response includes **your** gate decision, not the aggregate
3. `GET /v1/predictions/{id}/crowd?contributor_id=...` — aggregate visible only after you have submitted
```bash
# 1. Blind target (no agent confidence/rationale)
curl http://127.0.0.1:8765/v1/predictions/{id}/contribute
# 2. Submit
curl -X POST http://127.0.0.1:8765/v1/predictions/{id}/contributions \
-H "Content-Type: application/json" \
-d '{
"contributor_id": "alice",
"probability": 0.35,
"argument": "Because grid constraints bind however budgets are announced therefore spend lags.",
"evidence_urls": ["https://example.com/report"]
}'
# 3. View aggregate (only after submitting as alice)
curl "http://127.0.0.1:8765/v1/predictions/{id}/crowd?contributor_id=alice"
```
One submission per `contributor_id` per prediction. Gate thresholds in `config.yaml` → `crowd`.
---
- **HR-1**: `tests/test_api.py` uses FastAPI TestClient — no live server
- **HR-5**: No write endpoints (no forecast generation, no publish)
- **HR-8**: Commercial API hosting requires BUSL commercial license
## Tests
```bash
python -m pytest tests/test_api.py -v
```
## MCP parity
| REST | MCP tool |
|------|----------|
| `GET /v1/scoreboard` | `get_calibration_scoreboard` |
| `GET/POST /v1/ood` | `get_ood_assessment` |
| `GET/POST /v1/jobs/search` | `search_jobs` |
| `GET /v1/predictions/open` | `list_open_predictions` |
See also [MCP.md](./MCP.md).
|