Files
schulos/docs/CRITICAL_APIS_TO_BUILD.md
T

11 KiB

Critical APIs to Build - Priority List

Phase 3: API Implementation (Ready for Your Team)

All endpoints follow the standardized middleware pattern defined in src/lib/route-middleware.ts and src/lib/api-response.ts.


Priority 1: CRITICAL (Must Have for MVP)

1. Notifications Hub APIs

POST /api/v1/notifications/send

Purpose: Create and send notification to user(s)

// Request
{
  schoolId: string;
  userId?: string;              // Single user
  userIds?: string[];           // Multiple users
  category: 'assessment' | 'behavior' | 'communication' | 'wellness' | 'system' | 'announcement';
  priority: 'low' | 'normal' | 'high' | 'critical';
  title: string;
  message: string;
  actionUrl?: string;
  actionLabel?: string;
  sourceType?: string;
  sourceId?: string;
  expiresAt?: Date;
}

// Response
{
  success: true;
  data: {
    id: string;
    createdAt: Date;
    sentTo: number;
  }
}

Logic:

  • Validate user/school relationship
  • Create notification_hub entries
  • Trigger real-time update via WebSocket
  • Log via audit system
  • Check user notification preferences before sending

Location: /src/app/api/v1/notifications/send/route.ts


GET /api/v1/notifications/hub?limit=20&offset=0

Purpose: Get user's notifications

// Response
{
  success: true;
  data: {
    notifications: [
      {
        id: string;
        category: string;
        priority: string;
        title: string;
        message: string;
        isRead: boolean;
        isDismissed: boolean;
        createdAt: Date;
        actionUrl?: string;
      }
    ];
    unreadCount: number;
    total: number;
  }
}

Location: /src/app/api/v1/notifications/hub/route.ts


PUT /api/v1/notifications/{id}/read

Purpose: Mark notification as read

// Response
{
  success: true;
  data: {
    id: string;
    isRead: true;
    readAt: Date;
  }
}

Location: /src/app/api/v1/notifications/[id]/read/route.ts


2. Dashboard Widget APIs

POST /api/v1/dashboard/widgets

Purpose: Create widget

// Request
{
  schoolId: string;
  userId: string;
  widgetType: string;
  size: 'small' | 'medium' | 'large' | 'full_width';
  config?: Record<string, any>;
  refreshInterval?: number;
}

// Response
{
  success: true;
  data: {
    id: string;
    position: number;
    widgetType: string;
    createdAt: Date;
  }
}

Logic:

  • Find next available position
  • Use getDefaultConfig(widgetType) if config not provided
  • Validate widget type exists
  • Create dashboard_widget record

Location: /src/app/api/v1/dashboard/widgets/route.ts


GET /api/v1/dashboard/widgets

Purpose: Get user's widgets

// Response
{
  success: true;
  data: [
    {
      id: string;
      widgetType: string;
      title: string;
      position: number;
      size: string;
      config: Record<string, any>;
      cacheData?: any;
      lastRefresh?: Date;
    }
  ];
}

Location: /src/app/api/v1/dashboard/widgets/route.ts


PUT /api/v1/dashboard/widgets/{id}

Purpose: Update widget (position, config, size)

// Request
{
  position?: number;
  size?: string;
  config?: Record<string, any>;
  title?: string;
}

// Response
{
  success: true;
  data: { /* updated widget */ }
}

Location: /src/app/api/v1/dashboard/widgets/[id]/route.ts


DELETE /api/v1/dashboard/widgets/{id}

Purpose: Remove widget from dashboard

// Response
{
  success: true;
  data: { id: string }
}

Location: /src/app/api/v1/dashboard/widgets/[id]/route.ts


3. Signage APIs

POST /api/v1/signage/messages

Purpose: Create emergency message

// Request
{
  schoolId: string;
  signageId?: string;              // Broadcast to specific device or all
  title: string;
  content: string;
  messageType: 'emergency' | 'notification' | 'schedule' | 'announcement' | 'alert';
  priority: 'low' | 'normal' | 'high' | 'critical';
  displayDuration?: number;        // seconds
  soundAlert?: boolean;
  soundFile?: string;
  startTime?: Date;
  endTime?: Date;
}

// Response
{
  success: true;
  data: {
    id: string;
    messageId: string;
    broadcastTo: number;            // devices affected
    priority: string;
  }
}

Logic:

  • Create signage_message record
  • If signageId: send to that device
  • Else: broadcast to all active signages via WebSocket
  • Log via audit system
  • Create signage_audit_log entry

Location: /src/app/api/v1/signage/messages/route.ts


GET /api/v1/signage/devices

Purpose: Get school's signage devices

// Response
{
  success: true;
  data: [
    {
      id: string;
      displayName: string;
      location: string;
      isActive: boolean;
      signageType: string;
      lastHeartbeat?: Date;
      currentMessage?: {
        id: string;
        title: string;
        priority: string;
      };
    }
  ];
}

Location: /src/app/api/v1/signage/devices/route.ts


POST /api/v1/signage/devices

Purpose: Register new signage device

// Request
{
  schoolId: string;
  displayName: string;
  location: string;
  signageType: string;
  resolution: string;
  ipAddress?: string;
}

// Response
{
  success: true;
  data: { id: string; apiToken: string }
}

Location: /src/app/api/v1/signage/devices/route.ts


4. Exam Session APIs

POST /api/v1/exam-sessions/start

Purpose: Begin exam session for student

// Request
{
  schoolId: string;
  assessmentId: string;
  studentId: string;
  lockdownEnabled?: boolean;
  cameraMonitor?: boolean;
  screenShare?: boolean;
}

// Response
{
  success: true;
  data: {
    sessionId: string;
    startTime: Date;
    endTime: Date;
    timeAllowed: number;           // minutes
    token: string;                 // JWT for session verification
    lockdownToken?: string;        // For kiosk mode
  }
}

Logic:

  • Validate student is enrolled in course
  • Create exam_session record
  • Generate JWT with session data + exp
  • If lockdownEnabled: generate kiosk token (restricted permissions)
  • Start real-time monitoring via WebSocket
  • Log audit trail

Location: /src/app/api/v1/exam-sessions/start/route.ts


GET /api/v1/exam-sessions/{sessionId}/events

Purpose: Stream exam monitoring events

// Query Params
?limit=50&type=all|warning|critical

// Response (streamed)
{
  success: true;
  data: {
    events: [
      {
        id: string;
        eventType: 'tab_switch' | 'copy_paste' | 'window_blur' | 'camera_detected_none' | 'suspicious_movement' | 'time_warning';
        severity: 'info' | 'warning' | 'critical';
        timestamp: Date;
        description?: string;
      }
    ];
    securityRisk: 0-100;           // Computed score
    warnings: Exam
Warning[];
  }
}

Logic:

  • Retrieve exam_events for session
  • Filter by type if provided
  • Compute security risk score:
    • tab_switch: +15
    • copy_paste: +25
    • window_blur: +10
    • suspicious_movement: +35
    • Max capped at 100
  • Include active exam_warnings

Location: /src/app/api/v1/exam-sessions/[sessionId]/events/route.ts


POST /api/v1/exam-sessions/{sessionId}/submit

Purpose: Submit exam for grading

// Request
{
  studentId: string;
  answers: [
    { questionId: string; answer: string }
  ]
}

// Response
{
  success: true;
  data: {
    sessionId: string;
    submittedAt: Date;
    status: 'submitted';
    securityFlags: number;
  }
}

Location: /src/app/api/v1/exam-sessions/[sessionId]/submit/route.ts


Priority 2: IMPORTANT (Build in Week 2)

5. Dashboard Layout API

POST   /api/v1/dashboard/layouts
GET    /api/v1/dashboard/layouts/{id}
PUT    /api/v1/dashboard/layouts/{id}
DELETE /api/v1/dashboard/layouts/{id}

6. Signage Scheduling

POST   /api/v1/signage/schedules
GET    /api/v1/signage/schedules
PUT    /api/v1/signage/schedules/{id}
DELETE /api/v1/signage/schedules/{id}

7. Exam Proctoring (Teacher)

GET    /api/v1/exam-proctoring/sessions?classId=xxx
POST   /api/v1/exam-proctoring/{sessionId}/pause
POST   /api/v1/exam-proctoring/{sessionId}/resume
POST   /api/v1/exam-proctoring/{sessionId}/flag-warning

8. Notification Preferences

GET    /api/v1/notifications/preferences
PUT    /api/v1/notifications/preferences

Implementation Template

Use this template for each API (follows middleware pattern):

// /src/app/api/v1/[module]/[action]/route.ts
import { NextRequest } from 'next/server';
import { withAuth, withAudit, withRateLimit } from '@/lib/route-middleware';
import { apiResponse, apiError } from '@/lib/api-response';
import { db } from '@/lib/db';
import { logComplianceAudit } from '@/lib/audit';

export async function POST(request: NextRequest) {
  return withAuth(async (user) => {
    return withAudit(async () => {
      try {
        const body = await request.json();

        // Validate input
        if (!body.schoolId) {
          return apiError('School ID required', 400);
        }

        // Verify user access to school
        const school = await db.school.findUnique({
          where: { id: body.schoolId },
        });

        if (!school) {
          return apiError('School not found', 404);
        }

        // Business logic
        const result = await db.yourModel.create({
          data: { /* ... */ },
        });

        // Audit log
        await logComplianceAudit({
          userId: user.id,
          schoolId: body.schoolId,
          action: 'YOUR_ACTION',
          entityType: 'YourModel',
          entityId: result.id,
        });

        return apiResponse({
          success: true,
          data: result,
        });
      } catch (error) {
        console.error('[v0] API error:', error);
        return apiError('Operation failed', 500);
      }
    }, request);
  }, request);
}

WebSocket Events (Real-Time)

For real-time notifications, exams, and signage updates:

// Server sends:
{
  type: 'notification.created' | 'exam.event' | 'signage.updated';
  data: { /* event data */ };
  timestamp: Date;
}

// Client subscribes:
const ws = new WebSocket('wss://api.domain/ws');
ws.send(JSON.stringify({
  action: 'subscribe',
  channels: ['notifications', 'exam:sessionId', 'signage:schoolId']
}));

Testing Checklist

For each API:

  • ✅ Valid request succeeds with 200
  • ✅ Invalid input returns 400
  • ✅ Unauthorized returns 401
  • ✅ Forbidden returns 403
  • ✅ Not found returns 404
  • ✅ Audit log created
  • ✅ Real-time updates triggered
  • ✅ Performance <200ms

Estimated Effort

Priority 1: 3-4 days (10 endpoints)
Priority 2: 3-4 days (8+ endpoints)
Total: 6-8 days for complete API layer

All infrastructure is ready. Just implement the business logic following the templates above.