Skip to main content
All routes on this page require a session. Listing and mutations use 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.
Duplicate email → error.

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.