# 08 — API Surface · Unified Platform (2026-09-18)

**Method:** static extraction from the live tree (all `*.ts` route files, every registration variable — `router.`, `facultySwapRouter.`, `swapRouter.` …), mount table from `server/index.ts`, then a normalized cross-reference against every frontend `api.*`/`fetch` call (script `_api-xref.json`).

## Totals
- **263 server routes** across **26 mounted routers** (all imports mounted — no orphaned routers).
- v1 mounts: `/crm /me /scl /reimb /roster /swap /faculty-swap /eval /eoy /eval-tracker /eval-campaigns /auth /grand-rounds /vapi /twilio /admin /notifications /progress /coverage /staff-schedule /or-schedule` + non-v1 public: `/public-schedule /public-call-editor /attending-swap /replay /redesign-decisions`.
- Health: `/api/health` (+`/ready`,`/live`) — the real, deep probes (5 pools + migrations). `/api/ready|live` still 308 (Aug aliases lost — see 34).
- Docs: `/api/docs` (Swagger UI) + `/api/docs.json`; swagger-contract test enforces coverage.
- Legacy `/api/*` → 308 → `/api/v1/*` shim (expected, benign).

## Frontend ↔ server cross-reference
- **117 frontend API calls** extracted → **112 matched**, 5 unmatched — each adjudicated:

| # | Call | Verdict |
|---|---|---|
| 1 | `DELETE /api/v1/admin/reimb/transaction/:id` (ResidentReimbProfile delete button) | **REAL — dead call.** No DELETE route exists anywhere (admin.ts has only PUT `/reimb/transaction/:id`). The UI delete-transaction action **cannot succeed**; it surfaces the error toast. → **P1** RB-1 finding |
| 2 | `GET /api/v1/eval/submit` (EvalForm) | Scanner artifact — actual call is `fetch(..., {method:'POST'})`; route exists |
| 3 | `GET /api/v1/eval-campaigns/:id/remind` | Scanner artifact — real call is POST; route exists |
| 4 | `GET /api/v1/reimb/export/csv?...` | Scanner artifact — truncation on template literal; route exists |
| 5 | `POST /api/v1/admin/scl/rotation/:id/move-${direction}` | Scanner artifact — `direction` ∈ {'up','down'}; both routes exist |

**Net: 1 dead user-facing API call found (delete-transaction).**

## Reverse direction — endpoints with no in-app caller
52 candidates by string-scan; after adjudication:
- **External/system consumers (expected, not dead):** `/health*`, `/docs.json`, `/twilio/*` (call line), `/vapi/*`, `/public-schedule/*` + `/public-call-editor` (standalone public pages), `/attending-swap/*` (standalone page), `/replay/session` + `/redesign-decisions/*` (Decision Studio), `/roster/call-schedule/print` (opened as document), `POST /roster/swaps/execute-full-day` (called by `scripts/swap_engine.py`), seed endpoints (admin tooling).
- **Likely-dead (no caller in src/public/scripts; verify external consumers before deleting):**
  `GET /roster/swap-requests` · `GET /roster/colleagues` · `GET /coverage/team-list` + `POST` + `DELETE /coverage/team-list/:id` · `GET /admin/scl/upcoming-shifts` · `GET /admin/scl/float-shifts` · `GET /admin/roster/upcoming-shifts` · `GET /reimb/trash` · `GET /admin/reimb/trash` · `GET /reimb/last-submission` → `P3 backlog (cleanup)`, consistent with the retired swap-request flow (`App.tsx` comments) and the Sep-17 coverage rebuild.

## Auth coverage spot-checks (new-wave)
- `/admin/reimb/reporting` + `/export`: `requireAdmin` ✓ · `/faculty-swap/*`: `requireFacultyOrAdmin` + `requireAdmin` on revert ✓ · public routers: documented token gates + rate limits ✓ (see 03).
