Skip to main content

Manager API Overview

The manager-api-node is the backend REST API for the Cheeko platform, built with Node.js/Express. All endpoints share the base path /toy.

Tech Stack

ComponentTechnology
RuntimeNode.js 20+
FrameworkExpress.js
DatabaseDigitalOcean Managed PostgreSQL via Prisma ORM
Auth (admin)Custom token lookup (sys_user_token table, Prisma)
Auth (mobile)Firebase ID tokens (firebase-admin SDK)
Base path/toy
Port8002
API docs/toy/doc.html (Swagger UI)

Middleware Stack

Middleware is applied in the following order in src/app.js:

MiddlewareFilePurpose
helmetexpressSets secure HTTP headers (CORS resource policy: cross-origin)
corsexpressAllows configurable origins; defaults to localhost:8080 and localhost:3000. Reads CORS_ORIGINS env var.
trust proxyexpressEnables correct IP identification behind nginx/load balancer
Rate limiterexpress-rate-limit5000 req / 15 min window per IP; returns 429 with { code: 429, msg: "..." }
express.jsonexpressParses JSON bodies up to 10 MB
express.urlencodedexpressParses URL-encoded bodies up to 10 MB
XSS filtersrc/middleware/xssFilter.jsSanitizes request body/query to strip XSS payloads
Request IDsrc/middleware/requestId.jsAttaches a unique X-Request-ID to every request
Morgan loggermorganHTTP access logging; dev format in development, compact format in production
Routessrc/routes/index.jsAll API routes under /toy
404 handlersrc/middleware/errorHandler.jsReturns { code: 404, msg: "..." } for unknown routes
Global error handlersrc/middleware/errorHandler.jsReturns { code: 500, msg: "..." } for unhandled errors

Authentication

Two dedicated middleware files handle authentication:

src/middleware/auth.js — Custom token + service key auth

Tokens are stored in the sys_user_token database table (Prisma). Exported middleware:

ExportBehavior
requireAuthVerifies Bearer <token> against sys_user_token. Attaches req.user.
requireAdminLike requireAuth but also checks user.role === 'admin' or super_admin === 1. Accepts service key as bypass.
requireServiceKeyVerifies X-Service-Key header equals SERVICE_SECRET_KEY env var. Sets req.isServiceAuth = true.
requireDualAuthAccepts either a valid Bearer token or a valid service key.
optionalAuthTries both methods; attaches req.user or req.isServiceAuth if valid, but never rejects.
requireSuperAdminMust be chained after requireAuth; checks super_admin === 1.

src/middleware/flexAuth.js — Firebase + custom token (dual mobile/admin)

Used on routes that serve both the Flutter mobile app and the web admin dashboard.

ClientToken typeFlow
Flutter appFirebase ID tokenadmin.auth().verifyIdToken(token) → finds or creates sys_user row → sets req.firebaseUser, req.mobileUser, req.user
Admin web dashboardCustom JWTFalls back to verifyCustomToken → sets req.user

If neither check succeeds, returns 401 Unauthorized.

Route Overview

All routes are mounted under the /toy context path.

Mount pathModule fileDescription
/toy/userauth.routes.jsLogin, registration, user management
/toy/devicedevice.routes.jsESP32 device registration, binding, mode control, OTA
/toy/agentagent.routes.jsAI agent config, prompts, character switching, chat history
/toy/contentcontent.routes.jsMusic, stories, content library, file upload
/toy/admin/rfidrfid.routes.jsRFID card mappings, packs, RAG lookup
/toy/api/mobilemobile.routes.js, profile.routes.jsFirebase-backed mobile endpoints (kid profiles, etc.)
/toy/modelsmodel.routes.jsAI model management
/toy/analyticsanalytics.routes.jsGame sessions, media playback, usage stats
/toy/systemsystem.routes.jsSystem settings
/toy/adminadmin.routes.jsAdmin utilities
/toy/configconfig.routes.jsRuntime configuration
/toy/usageusage.routes.jsUsage tracking
/toy/quotaquota.routes.jsQuestion, token, time, and game-session quota endpoints
/toy/subscriptionsubscription.routes.jsSubscription plans, unified quota checks, and AI Card time quota
/toy/otaota.routes.jsOTA firmware check (device-facing)
/toy/otaMagotaMag.routes.jsOTA firmware management (admin)
/toy/admin/serverserver.routes.jsServer management
/toy/admin/paramsparams.routes.jsSystem parameters
/toy/admin/dictdict.routes.jsData dictionary
/toy/ttsVoicettsVoice.routes.jsTTS voice configuration
/toy/admin/email-reportsemailReport.routes.jsEmail report scheduling

Subscription and AI Card Quota

The aicard_subscription branch adds a prepaid AI Card time quota system under /toy/subscription. AI Card quota is keyed by physical RFID card (rfid_uid) rather than user or device, and active voice sessions consume connected seconds from the card's monthly balance.

See AI Card Subscription for the endpoint reference, quota flow, database objects, MQTT messages, and admin dashboard behavior.

Health Endpoints

MethodPathAuthDescription
GET/healthNoneApp health (uptime, timestamp)
GET/toy/healthNoneAPI health with environment info
GET/toy/health/dbNoneTests Prisma → DigitalOcean PostgreSQL connection
GET/toy/pub-configNonePublic feature flags (rfid, analytics, rag, memory)

Standard Response Envelope

All API responses use the same envelope:

{
"code": 0,
"msg": "success",
"data": { ... }
}

Error responses set code to a non-zero value (e.g. 400, 401, 403, 404, 500) and data to null.

Running the API

cd main/manager-api-node
npm install

# Development (auto-reload)
npm run dev

# Production
npm start

# Tests
npm test
npm run test:coverage

Required Environment Variables

PORT=8002
NODE_ENV=development

# Primary database
DATABASE_URL=postgresql://user:pass@host:5432/dbname?sslmode=require

# Supabase (legacy admin auth only)
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key

# Service-to-service auth (LiveKit agents, MQTT gateway)
SERVICE_SECRET_KEY=your-service-secret

# Firebase (mobile app auth)
FIREBASE_SERVICE_ACCOUNT_KEY=<base64 or path>

# Vector search
QDRANT_URL=https://your-cluster.qdrant.io
QDRANT_API_KEY=your-qdrant-api-key

# Memory/personalization
MEM0_API_KEY=your-mem0-api-key