requireAdminActor (level ≥ 4) except where noted. Limits: Errors and rate limits.
GET /api/users
Level ≥ 4. Super Admin sees every user. Principals see the same school with level: { $lt: 5 } (Super Admins at that school are omitted).
PUT /api/users
Level ≥ 4. Body: { "userId", "name?", "level?", "schoolName?", "title?", "isActive?" }.
canManageTarget must pass: no self-edit. Super Admin may update any other account, including other Super Admins, and may assign levels 1–5. Principals only manage levels 1–3 at their school.
DELETE /api/users
Level ≥ 4. JSON body { "userId": "..." }. Same canManageTarget rules; cannot delete yourself.
POST /api/users/create
Level ≥ 4. Limit 20 / 60s.
string
required
Display name.
string
required
Stored lowercase. Sign-in still requires
@schools.nyc.gov.number
required
1–5. Super Admin may create Super Admins. Level 4 callers cannot create 4 or 5.
string
required
Principals cannot set a different school than their own.
string
Optional job title.
boolean
Default
true. Inactive users fail the NextAuth signIn callback.POST /api/users/bulk-import
Super Admin. { "users": [ { "name", "email", "level", "schoolName" } ] }. Limit 5 / 60s.
POST /api/users/bulk
Level ≥ 4. { "userIds": [], "action": "..." }. Limit 10 / 60s. Only ids that pass bulkTargetFilter (not self; same school and level ≤ 3 for principals). Super Admin may include other Super Admins.
GET /api/users/audit-logs
Level ≥ 4. Filtered AuditLog query (plus legacy User.activityLog rows). Super Admin sees the district. Principals are scoped to emails on their school roster.
Query: action, userEmail, targetType, startDate, endDate, limit (max 1000), skip.
Prefer /admin/logs in the UI (level 5). How-to: Audit logs and admin tables.
Plan assignment is not this route. Use the share UI (POST /api/admin/forms/share) or PUT /api/users for level / school / active. The old PUT /api/users/[id]/permissions handler was removed.
GET POST /api/notifications
Plan owner review pings (notificationSent on FormSubmission). POST marks a notification read. Not a general inbox.