Skip to content

API Routes

The full, authoritative API reference is the OpenAPI document Fastify generates from the Zod schemas at runtime — open http://localhost:3000/documentation (Swagger UI). This page summarizes the route map and the conventions every endpoint follows.

Conventions

  • Prefix: every route lives under /api. Inside the codebase, routes/index.ts registers apiRoutes with prefix: "/api".
  • JSON only. Responses are JSON; the only exception is GET /api/files/:id/raw, which streams the underlying binary.
  • Plural noun resources. A typical resource exposes GET /api/<resource>, POST /api/<resource>, GET /api/<resource>/:id, PUT /api/<resource>/:id, DELETE /api/<resource>/:id.
  • Validation via Zod. Every body, querystring and response is validated. Invalid input returns 400 with a Zod error body; missing or expired auth returns 401.
  • Error shape: { "error": "..." } for client errors. Server errors come from Fastify's default formatter.
  • Auth header: Authorization: Bearer <accessToken>. The default token lifetime is 15 minutes — use /api/auth/refresh to rotate.

Public routes (no token)

These are the only paths the global onRequest hook lets through:

MethodPathPurpose
POST/api/auth/loginUsername/email + password login.
POST/api/auth/registerCreate a user. Requires the verification code from /auth/register/send-code.
POST/api/auth/register/send-codeEmail a 6-digit code (5-minute TTL).
POST/api/auth/refreshExchange a refresh token for a new access + refresh pair.
POST/api/auth/forgot-password/send-codeEmail a password-reset code.
POST/api/auth/forgot-password/resetReset password with the code.
GET/api/auth/oauth/providersList configured OAuth providers.
GET/POST/api/auth/oauth/wechat/..., /api/auth/oauth/feishu/...OAuth start/callback.
POST/api/auth/oauth/bind, /api/auth/oauth/register-and-bindLink an OAuth identity to an account.
GET/api/dashboardPublic read-only dashboard payload (used by apps/web).

Everything else is protected.

Route map

/api/auth/*

MethodPathSummary
POST/auth/loginLogin with username and password
POST/auth/registerRegister a new user
POST/auth/register/send-codeSend registration verification code
POST/auth/refreshRefresh access token (rotates refresh token)
POST/auth/logoutInvalidate the current refresh token
POST/auth/forgot-password/send-codeSend password-reset code
POST/auth/forgot-password/resetReset password with code
GET/auth/meCurrent user

/api/auth/oauth/*

MethodPathSummary
GET/auth/oauth/providersAvailable OAuth providers
GET/auth/oauth/:provider/authorizeBegin authorization (returns provider redirect URL)
GET/POST/auth/oauth/:provider/callbackProvider callback
POST/auth/oauth/bindLink to an existing account
POST/auth/oauth/register-and-bindCreate an account from a provider profile

/api/users/*

User CRUD, role and avatar management. All endpoints are protected.

/api/dashboard/*

MethodPathNotes
GET/dashboardPublic — full dashboard payload for the public web portal.
GET/dashboard/alertsRecent alerts.
GET/dashboard/settingsPer-user dashboard configuration.
PUT/dashboard/settingsUpdate per-user dashboard configuration.

/api/overview/*

GET /overview/stats — KPI cards. GET /overview/energy/weekly — chart data.

/api/energy/*

GET /energy/areas and PUT /energy/areas — per-area summary cards.

/api/alerts/*, /api/faults/*, /api/maintenance/*

CRUD endpoints over the matching tables. /faults/stats returns the snapshot row.

/api/reports/*

Report plans CRUD and report templates listing.

/api/configs

GET and PUT for the single-row platform configuration.

/api/three-d-config

3D scene configuration (camera preset, ambient intensity, hotspots, labels). Backs the 3D Configuration page in admin and the Babylon scene in web.

/api/files/*

MethodPathNotes
GET/filesList uploads.
POST/filesMultipart upload, max 100 MB per file.
GET/files/:idMetadata only.
GET/files/:id/rawStream the binary.
DELETE/files/:idRemove.

/api/models/*

Equivalent to /files but specialized for 3D model uploads. Files land in uploads/models/ and are exposed at /static/models/<filename>.

/api/iot/*

Proxy layer for the upstream IoT gateway. Inputs and outputs match the upstream contract; EcoCtrl handles token refresh transparently using the iot_tokens row.

PathDescription
/iot/tokenReturns the cached access token.
/iot/codes/valuesRead current point values.
/iot/codes/historyHistorical values for a point.
/iot/codes/set, /iot/codes/force-setWrite back.
/iot/alarms, /iot/alarm-configsAlarm history and configuration.

/api/system/*

GET /system/backup-schedule, PUT /system/backup-schedule.

Swagger auto-login

/documentation includes a small inline script that:

  1. Captures the response of POST /auth/login and POST /auth/refresh.
  2. Stores the access and refresh tokens in localStorage.
  3. Calls Swagger's authActions.authorize to apply the bearer token automatically.
  4. Auto-fills the refresh token body on subsequent /auth/refresh calls.

Practically: log in once via the Swagger UI's "Try it out" on /auth/login, then every other endpoint is unlocked.

Adding a new route

  1. Create packages/server/src/routes/<resource>.ts exporting an async function (fastify) => { ... }.
  2. Define request/response Zod schemas inline or in a dedicated module.
  3. Implement the handler — call into repositories/<resource>.ts, never Drizzle directly.
  4. Register the file in routes/index.ts with the desired prefix.
  5. If the route should bypass auth, add it to publicPaths in the same file. Otherwise it inherits the JWT gate.

Adding a route automatically adds it to the OpenAPI document — no manual maintenance.

Released under the MIT License.