← back to Norma

app/api/fred/route.ts

60 lines

import { NextRequest, NextResponse } from 'next/server';
import { requireRole } from '@/lib/require-role';

const FRED_BASE = 'https://api.stlouisfed.org/fred';

// Key economic series for student debt advocacy
const SERIES_CATALOG: Record<string, { id: string; label: string; units: string }> = {
  total_student_debt:       { id: 'SLOAS',       label: 'Total Student Loans Outstanding', units: 'Billions of $' },
  avg_student_debt:         { id: 'STDSL',       label: 'Avg Student Loan Balance',        units: 'USD' },
  fed_funds_rate:           { id: 'FEDFUNDS',    label: 'Federal Funds Rate',              units: 'Percent' },
  delinquency_rate:         { id: 'DRSFRMACBS',  label: 'Delinquency Rate (Consumer)',     units: 'Percent' },
  unemployment_rate:        { id: 'UNRATE',      label: 'US Unemployment Rate',            units: 'Percent' },
  cpi:                      { id: 'CPIAUCSL',    label: 'Consumer Price Index',            units: 'Index 1982-84=100' },
};

/**
 * GET /api/fred?action=series|observations&series=total_student_debt
 */
export async function GET(request: NextRequest) {
  const auth = requireRole(request, 'admin', 'staff');
  if (auth instanceof NextResponse) return auth;

  const apiKey = process.env.FRED_API_KEY;
  if (!apiKey) {
    return NextResponse.json({ error: 'FRED_API_KEY not configured', catalog: SERIES_CATALOG }, { status: 503 });
  }

  const { searchParams } = new URL(request.url);
  const action = searchParams.get('action') || 'catalog';

  try {
    if (action === 'catalog') {
      return NextResponse.json({ catalog: SERIES_CATALOG });
    }

    if (action === 'observations') {
      const seriesKey = searchParams.get('series') || 'total_student_debt';
      const seriesInfo = SERIES_CATALOG[seriesKey];
      if (!seriesInfo) return NextResponse.json({ error: 'Unknown series key' }, { status: 400 });

      const limit = searchParams.get('limit') || '24';
      const res = await fetch(
        `${FRED_BASE}/series/observations?series_id=${seriesInfo.id}&api_key=${apiKey}&file_type=json&sort_order=desc&limit=${limit}`
      );
      if (!res.ok) throw new Error(`FRED returned ${res.status}`);
      const data = await res.json();

      return NextResponse.json({
        series: seriesInfo,
        observations: data.observations || [],
        count: data.count || 0,
      });
    }

    return NextResponse.json({ error: `Unknown action: ${action}` }, { status: 400 });
  } catch (err) {
    return NextResponse.json({ error: (err as Error).message }, { status: 500 });
  }
}