fix: use FRED official JSON API (bypasses CloudFlare) + API key UI
- fred_bootstrap.py: switch from CSV graph endpoint (CloudFlare-blocked) to api.stlouisfed.org/fred/series/observations JSON API; reads key from DB config 'fred_api_key'; returns clear error if key missing - eco.py: add GET/POST /api/eco/fred-key to check/save the FRED API key - CalendarPage.tsx: BootstrapPanel shows API key section with status, input to paste key + save button, disables Launch if key missing Free key: fred.stlouisfed.org -> My Account -> API Keys Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -48,6 +48,28 @@ def _run_bootstrap(from_date: str, series_ids: Optional[List[str]], force: bool)
|
||||
_bootstrap_status["running"] = False
|
||||
|
||||
|
||||
@router.get("/fred-key")
|
||||
def get_fred_key() -> Dict[str, Any]:
|
||||
"""Check if a FRED API key is configured."""
|
||||
from services.database import get_config
|
||||
key = get_config("fred_api_key") or ""
|
||||
return {
|
||||
"configured": bool(key),
|
||||
"preview": (key[:6] + "…" + key[-4:]) if len(key) > 10 else ("***" if key else ""),
|
||||
}
|
||||
|
||||
|
||||
@router.post("/fred-key")
|
||||
def save_fred_key(key: str = Query(..., description="FRED API key")) -> Dict[str, Any]:
|
||||
"""Save FRED API key to DB config."""
|
||||
from services.database import set_config
|
||||
key = key.strip()
|
||||
if not key:
|
||||
raise HTTPException(400, "Empty key")
|
||||
set_config("fred_api_key", key)
|
||||
return {"status": "saved", "preview": key[:6] + "…" + key[-4:]}
|
||||
|
||||
|
||||
@router.post("/bootstrap")
|
||||
def bootstrap(
|
||||
background_tasks: BackgroundTasks,
|
||||
|
||||
Reference in New Issue
Block a user