JupiterAPI is a Node.js/Express API wrapper for ESN Jupiter data. It exposes normalized endpoints for users, events, statistics, and CSV exports, with optional authenticated write endpoints for Hercules/Firestore workflows.
Jupiter data is often difficult to consume directly for dashboards, automations, and exports. This service provides:
- Stable JSON endpoints with normalized fields
- Academic-year aware event filtering
- Statistics endpoints for section-level reporting
- Google Contacts CSV export
- Optional JWT-protected write proxy for Hercules data in Firestore
- Express 5 API with API key protection for read endpoints
- AWS Cognito integration for upstream Jupiter authentication
- In-memory caching for Jupiter reads and computed stats
- JWT verification using Cognito JWKS
- Optional role-gated write routes under
/hercules
npm install
cp .env.example .env
# edit .env with real credentials
npm startDefault server URL: http://localhost:3002
Health check:
curl http://localhost:3002/healthAWS_COGNITO_REGIONAWS_COGNITO_USER_POOL_IDAWS_COGNITO_CLIENT_IDCOGNITO_USERNAMECOGNITO_PASSWORDJUPITER_API_BASE_URL
API_KEY(read API protection)ALLOWED_ORIGINSRATE_LIMIT_WINDOW_MSRATE_LIMIT_MAX_REQUESTS
BOARD_MEMBER_IDSGOOGLE_APPLICATION_CREDENTIALS
See .env.example for the full template.
GET /healthGET /metrics
GET /usersGET /users?kind=ERASMUSGET /users/search?q=nameGET /users/:id
GET /section
GET /eventsGET /events?erasmusOnly=falseGET /events/archivedGET /events/:idGET /events/:id/subscriptionsGET /events/:id/subscriptions/:userId
GET /national-events
GET /requests
GET /treasury/cash-flow?since=YYYY-MM-DD&to=YYYY-MM-DD
GET /stats/nationalityGET /stats/field-of-studyGET /stats/overviewGET /stats/citiesGET /stats/comprehensive
GET /export/google-contacts
POST /auth/loginPOST /auth/refreshPOST /auth/verifyGET /auth/mePOST /auth/logout
Routes under /hercules/* require:
- Valid Cognito JWT (
Authorization: Bearer ...) - User
subpresent inBOARD_MEMBER_IDS - Firebase Admin SDK credentials for Firestore access
curl -H "X-Api-Key: $API_KEY" "http://localhost:3002/users?kind=ERASMUS"- Never commit
.env, service-account JSON files, or credentials. - Prefer long random
API_KEYvalues and rotate keys regularly. - Use immutable Cognito
subIDs for authorization (BOARD_MEMBER_IDS). - Restrict CORS origins to trusted frontends in production.
If you discover a vulnerability, open a private security report to maintainers instead of a public issue.
src/
index.js App bootstrap + route mounting (zero business logic)
config.js Sole env reader; fail-fast validation
jupiter.js Jupiter API client + Cognito auth + caches
googleContacts.js Google Contacts CSV building/streaming
normalizers.js User/event/subscription normalization
formatting.js Date/phone/academic-year helpers
nationality.js Nationality + country-code mapping
fieldsOfStudy.js Field labels + UniMore campus mapping
eventLocation.js Modena/Reggio Emilia inference rules
middleware/ apiKeyAuth, rateLimiter, jwtAuth, validation, asyncHandler
routes/ One file per URL prefix (users, events, stats, auth, hercules, ...)
test/
unit/ Characterization tests for pure modules
routes/ HTTP suites with mocked Jupiter/Cognito/Firestore
helpers/ mockModule, fixtures, cognitoStub, fakeFirestore
docs/
openapi.yaml OpenAPI 3.0 spec
ARCHITECTURE.md Domains, dependency direction, flows, decisions
FEATURES.md Feature-to-module map with test pointers
- AGENTS.md — repo map and architectural rules for humans and AI agents
- docs/ARCHITECTURE.md — how the pieces fit together
- docs/FEATURES.md — every feature, its owner module, and its tests
- docs/openapi.yaml — API reference
- Node.js
- Express
- Axios
- amazon-cognito-identity-js
- jsonwebtoken
- firebase-admin
- csv-stringify
MIT