The Unitru Academic backend API surface is intentionally minimal. Rather than exposing a family of REST data endpoints, the server collapses every operation — authentication, SUV navigation, data extraction, and result delivery — into a single WebSocket connection. The only HTTP endpoint that exists is a health probe. This design keeps the protocol simple: open one connection, send one message, and receive a stream of progress events followed by a single richly-typed payload when extraction is complete.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Andr21Da16/UNITRU-ACADEMIC/llms.txt
Use this file to discover all available pages before exploring further.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /health | Liveness check — returns {"status": "ok"} |
WebSocket | /ws | All operations: authentication, extraction, and results delivery |
Base URL
The backend URL is configured at build time through theNEXT_PUBLIC_BACKEND_WS_URL environment variable. The frontend client reads this variable and falls back to the local default when it is absent.
- Local Development
- Production (Railway)
ws://localhost:8000/ws.WebSocket Connection Lifecycle
The protocol is strictly sequential. There are no multiplexed channels or request IDs — the server handles one extraction per WebSocket connection.Open the connection
The client opens a WebSocket to
ws[s]://host/ws. The server accepts the handshake immediately and allocates a dedicated headless-browser session (Playwright) for this connection.Send credentials
The client sends exactly one JSON message with the student’s SUV credentials:If either field is missing, the server immediately emits an
error event and no browser work begins.Receive progress events
The server navigates the SUV portal (opens the URL, loads the login page, downloads and solves the CAPTCHA via Tesseract OCR, submits credentials) and emits a series of progress events such as
opening_suv, solving_captcha, and authentication_success. Each event has an empty data object unless specified otherwise.Receive extraction events
After a successful login, the server extracts each academic section in turn — profile, academic record, enrollment, attendance, grades, and optimized schedules — emitting a pair of
extracting_* / *_success events for each section.Receive dashboard_ready
Once all sections have been processed, the server emits a single
dashboard_ready event whose data field contains the complete DashboardReport payload. See Data Models for the full schema.Error handling
If a non-recoverable error occurs at any point, the server emits an
error event with {"message": string, "category": string} and the session is torn down. Individual extraction sections that fail emit a *_failed event but do not terminate the session — extraction continues with the next section.Message Format
All messages travel as JSON text frames. Every message, in both directions, follows a consistent envelope:The event name. See WebSocket Events for a complete list.
Event-specific payload. For most progress events this is an empty object
{}. For dashboard_ready it is the full DashboardReport. For error it contains message and category strings.Using the Frontend Client
The frontend ships a ready-madeconnectAndFetch function in frontend/infrastructure/websocket/websocket_client.ts that wraps the raw WebSocket API and routes incoming events to typed callbacks.
Callback interface
| Callback | When it fires | Argument |
|---|---|---|
onEvent | Any event other than dashboard_ready or error | (eventName, dataObject) |
onDashboardReport | dashboard_ready received | Typed DashboardReport object |
onError | error event or WebSocket-level failure | Human-readable error string |
onClose | WebSocket connection closes | (none) |
Health Check
The/health endpoint is a simple liveness probe with no authentication requirement. Use it to verify the backend is reachable before opening a WebSocket connection.
CORS
Allowed origins are configured server-side via theALLOWED_ORIGINS environment variable (comma-separated list). The default allows http://localhost:3000. In production, set ALLOWED_ORIGINS to your deployed frontend URL to prevent unauthorized cross-origin connections.
Credentials are sent only once over the WebSocket connection in the very first message and are never persisted, logged, or stored anywhere by the backend. The headless browser session is ephemeral and is destroyed as soon as the connection closes.