--- type: API Endpoint title: Admin routes description: Employee CRUD (add/soft-delete), org-wide and per-employee stats, and CSV export — all requireAdmin. resource: backend/src/routes/admin.ts tags: [api, admin] timestamp: 2026-08-12T00:00:00Z --- # Admin routes Mounted at `/api/admin`. Every route requires `requireAuth` + `requireAdmin` (role resolved from `ADMIN_EMAILS`, see [Auth flow](/docs/architecture/auth-flow.md)). # Examples ``` GET /api/admin/employees 200 -> { "employees": Employee[] } // includes inactive (soft-deleted) rows ``` ``` POST /api/admin/employees Body: { "email": string, "name"?: string } 201 -> { "employee": Employee } ``` Upserts by email — see [employees](/docs/data-model/employees.md) for the reactivate-on-re-add behavior. ``` DELETE /api/admin/employees/:id 204 on success, 404 if not found. ``` Soft delete only (`active = 0`) — never removes the row or its attendance history. ``` GET /api/admin/stats?month=YYYY-MM 200 -> { "range": { "from": string, "to": string }, "totals": { "totalWorkedMs": number, "totalBreakMs": number, "shiftCount": number }, "employees": [{ "employee": Employee, "totalWorkedMs": number, "totalBreakMs": number, "shiftCount": number }] } ``` Same calendar-month default as the employee's own stats endpoint. ``` GET /api/admin/stats/:id?month=YYYY-MM 200 -> { "employee": Employee, "range": {...}, "sessions": Session[], "totalWorkedMs": number, "totalBreakMs": number, "shiftCount": number } 404 -> employee not found ``` ``` GET /api/admin/stats/:id/export?month=YYYY-MM 200, Content-Type: text/csv; charset=utf-8 Content-Disposition: attachment; filename="_.csv" ``` Columns: `Datum, Příchod, Odchod, Pauza (h:mm), Odpracováno (h:mm)`, one row per shift, sorted chronologically (`backend/src/util/csv.ts`). Prefixed with a UTF-8 BOM so Excel renders the Czech diacritics correctly. Downloaded from the frontend as a plain `` — the session cookie rides along automatically since it's a same-origin GET. # Related - [employees](/docs/data-model/employees.md) - [attendance_events](/docs/data-model/attendance-events.md) - [Attendance routes](./attendance-routes.md) - [Frontend stores](/docs/frontend/stores.md) — `adminStore` owns the selected month and drives both the summary table and the per-employee chart off it