Skip to content
Nishanth S edited this page May 8, 2026 · 5 revisions

API Documentation

Overview

Teambuilder provides a RESTful API built with Nuxt 3 server routes for managing students, projects, teams, semesters, and integrations with GitHub and Discord. The API is organized around core resources and uses standard HTTP methods (GET, POST, PUT, DELETE).

Base URL: /api/
Response Format: JSON
Status: Production
Last Updated: May 2026


Authentication & Authorization

Currently, the API does not enforce strict authentication/authorization. In production, implement:

  • OAuth 2.0 or JWT token validation
  • Role-based access control (RBAC) for admin operations
  • API key validation for service-to-service calls

Planned: Session-based auth via middleware in server/middleware/


API Response Format

All successful responses follow this structure:

{
  "data": { /* Resource or array of resources */ },
  "timestamp": "2026-05-08T12:00:00.000Z",
  "status": "success"
}

Error responses:

{
  "statusCode": 400,
  "statusMessage": "Bad Request",
  "message": "semesterId is required."
}

Resources

Teams

Represents project team assignments for a semester.

GET /api/teams?semesterId=...

Returns all teams for a semester with assigned students.

Query Parameters:

  • semesterId (required): Semester ID

Response:

{
  "teamAssignments": {
    "team-1": [
      { "id": "std-1", "name": "Alice", "major": "CS", "class": "3200", "choices": [...] },
      { "id": "std-2", "name": "Bob", "major": "SE", "class": "2200", "choices": [...] }
    ],
    "team-2": [...]
  },
  "projects": [
    { "id": "proj-1", "name": "Project A", "type": "SW", ... },
    { "id": "proj-2", "name": "Project B", "type": "HW", ... }
  ],
  "teamMeta": {
    "team-1": {
      "projectId": "proj-1",
      "projectName": "Project A",
      "meetingDay": "THURSDAY"
    },
    "team-2": {...}
  }
}

Error Cases:

  • 400: semesterId not provided

POST /api/teams/generate

Runs the CPSAT optimization algorithm to generate optimal team assignments.

Request Body:

{
  "semesterId": "sem-s25",
  "day": "THURSDAY",
  "config": {
    "min_team_size": 4,
    "max_team_size": 6,
    "prioritize_returning_students": true,
    "prioritize_3200_first_choice": true,
    "prefer_major_diversity": true,
    "match_skills": true,
    "balance_gender": true,
    "prefer_2200_early_choices": true
  }
}

Response:

{
  "teamAssignments": {
    "proj-1": [
      { "id": "std-1", "name": "Alice", ... },
      { "id": "std-2", "name": "Bob", ... }
    ],
    "proj-2": [...]
  },
  "projects": [...]
}

Behavior:

  • Fetches active students and projects for the semester
  • Runs CPSAT solver (see ALGORITHM.md)
  • Returns optimal assignments in ~0.5-2 seconds
  • Does NOT persist to database (use /api/teams/assign to save)

Error Cases:

  • 400: semesterId required or no active students/projects found

Configuration Parameters:

  • min_team_size: Minimum students per team (default: 4)
  • max_team_size: Maximum students per team (default: 6)
  • allow_overflow_if_needed: Allow exceeding max_team_size if mathematically necessary (default: true)
  • prioritize_returning_students: Give 500k bonus for returning to previous project (default: true)
  • prioritize_3200_first_choice: Apply 100x multiplier for 3200 student preferences (default: true)
  • match_skills: Bonus for skill matching (default: true)
  • balance_gender: Penalize gender isolation on teams (default: true)
  • prefer_major_diversity: Bonus for major diversity (default: true)
  • prefer_2200_early_choices: Penalties for 2200 students' late choices (default: true)

POST /api/teams/assign

Updates team member assignments after generation (e.g., manual adjustments).

Request Body:

{
  "teamId": "team-1",
  "studentIds": ["std-1", "std-2", "std-3", "std-4"]
}

Response:

{
  "id": "team-1",
  "projectId": "proj-1",
  "semesterId": "sem-s25",
  "students": [...]
}

POST /api/teams/export

Exports team assignments to a file (CSV, Excel, etc.).

Request Body:

{
  "semesterId": "sem-s25",
  "format": "csv"
}

Response: File download


POST /api/teams/index

Creates new teams for a semester.

Request Body:

{
  "semesterId": "sem-s25",
  "projectIds": ["proj-1", "proj-2", "proj-3"]
}

DELETE /api/teams/[id]

Deletes a specific team.


Students

Represents EPICS students and their project preferences.

GET /api/students?choices=true|false

Retrieves all students with optional choice/preference data.

Query Parameters:

  • choices (optional): Include student project choices if true (default: false)

Response (with choices=false):

[
  {
    "id": "std-1",
    "name": "Alice Johnson",
    "major": "CS",
    "seniority": "JUNIOR",
    "class": "3200",
    "status": "ACTIVE",
    "gender": "Female",
    "meetingDay": "THURSDAY",
    "previousProject": null,
    "skills": ["Python", "React", "AWS"]
  },
  { ... }
]

Response (with choices=true):

[
  {
    "id": "std-1",
    "name": "Alice Johnson",
    ...
    "choices": [
      { "id": "choice-1", "projectId": "proj-1", "rank": 1, "studentId": "std-1" },
      { "id": "choice-2", "projectId": "proj-3", "rank": 2, "studentId": "std-1" },
      { "id": "choice-3", "projectId": "proj-5", "rank": 3, "studentId": "std-1" }
    ]
  },
  { ... }
]

Export Type:

type StudentWithChoices = Student & {
  choices: Choice[]
}

POST /api/students

Creates a new student.

Request Body:

{
  "name": "Alice Johnson",
  "major": "CS",
  "seniority": "JUNIOR",
  "class": "3200",
  "email": "alice@university.edu",
  "gender": "Female",
  "meetingDay": "THURSDAY",
  "skills": ["Python", "React"]
}

DELETE /api/students/[id]

Deletes a student.


GET /api/students/[id]

Retrieves a single student by ID.


Projects

Represents EPICS projects offered by partners.

GET /api/projects

Retrieves all projects with their associated semesters and partner info.

Response:

[
  {
    "id": "proj-1",
    "name": "Project Alpha",
    "description": "Mobile app development",
    "type": "SW",
    "status": "ACTIVE",
    "partnerId": "partner-1",
    "partnerName": "TechCorp",
    "requiredSkills": ["React", "TypeScript"],
    "preferredMajors": ["CS", "SE"],
    "semesters": [
      { "id": "sem-s25", "name": "Spring 2025", "year": 2025, "season": "SPRING" },
      { "id": "sem-f25", "name": "Fall 2025", "year": 2025, "season": "FALL" }
    ]
  },
  { ... }
]

Export Type:

type ProjectWithSemestersAndPartner = Project & {
  semesters: Semester[],
  partnerName: string
}

GET /api/projects/recent

Retrieves recently modified projects.

Query Parameters:

  • limit (optional): Number of projects to return (default: 10)

POST /api/projects

Creates a new project.

Request Body:

{
  "name": "Project Alpha",
  "description": "Mobile app development",
  "type": "SW",
  "partnerId": "partner-1",
  "requiredSkills": ["React", "TypeScript"],
  "preferredMajors": ["CS", "SE"]
}

DELETE /api/projects/[id]

Deletes a project.


GET /api/projects/[id]

Retrieves a single project by ID.


Semesters

Represents academic semesters (Spring, Fall, Summer).

GET /api/semesters

Retrieves all semesters. Auto-creates default semesters if none exist.

Response:

[
  {
    "id": "sem-s25",
    "name": "Spring 2025",
    "year": 2025,
    "season": "SPRING",
    "status": "ACTIVE",
    "createdAt": "2025-01-15T00:00:00Z"
  },
  {
    "id": "sem-f25",
    "name": "Fall 2025",
    "year": 2025,
    "season": "FALL",
    "status": "INACTIVE",
    "createdAt": "2025-01-15T00:00:00Z"
  },
  { ... }
]

POST /api/semesters

Creates a new semester.

Request Body:

{
  "name": "Fall 2026",
  "year": 2026,
  "season": "FALL"
}

GET /api/semesters/[id]

Retrieves a single semester by ID.


Users

Represents system users (typically advisors, admins).

GET /api/users?id=...

Retrieves user information.

Query Parameters:

  • id (required): User ID

Response:

{
  "id": "user-1",
  "email": "admin@university.edu",
  "name": "Admin User",
  "role": "ADMIN",
  "createdAt": "2025-01-15T00:00:00Z"
}

POST /api/users

Creates a new user.

Request Body:

{
  "email": "admin@university.edu",
  "name": "Admin User",
  "password": "hashedPassword",
  "role": "ADMIN"
}

PUT /api/users/[id]

Updates user information.

Request Body:

{
  "name": "Updated Name",
  "role": "ADVISOR"
}

DELETE /api/users/[id]

Deletes a user.


Demographics

Retrieves demographic data and analytics.

GET /api/demographic?Course=...&Year=...&Semester=...&Ethnicity=...&Gender=...

Retrieves demographic statistics filtered by multiple criteria.

Query Parameters:

  • Course (required): CSV list of course names (e.g., "CS,SE,EE")
  • Year (required): CSV list of years (min 2 required, e.g., "2024,2025")
  • Semester (required): CSV list of semesters ("Spring,Fall,Summer")
  • Ethnicity (optional): CSV list of ethnicities ("African American,Asian,Hispanic,White,Other")
  • Gender (optional): CSV list of genders ("Male,Female")
  • Continuous (optional): Boolean - if true, ignore semester filter and use all three (default: false)
  • Yaxis (optional): Y-axis metric for charts

Response:

[
  {
    "Name": "CS",
    "Course": "Computer Science",
    "Total": 150,
    "Male": 95,
    "Female": 52,
    "Asian": 40,
    "White": 75,
    "Hispanic": 20,
    "African American": 10,
    "International": 5
  },
  { ... }
]

Status: Under development - endpoint returns incomplete data. See TODO in server/api/demographic.get.ts


POST /api/demographic

Submits or updates demographic data.


GitHub Integration

Manages GitHub repository creation and connection for project teams.

GET /api/github/status

Gets the current GitHub integration status.

Response:

{
  "success": true,
  "data": {
    "connected": true,
    "organization": "epics-org",
    "lastSync": "2026-05-08T12:00:00Z"
  },
  "timestamp": "2026-05-08T12:00:00Z"
}

POST /api/github/connect

Connects to GitHub via OAuth.

Request Body:

{
  "authCode": "oauth_code_from_github"
}

POST /api/github/disconnect

Disconnects from GitHub.


POST /api/github/create-repos

Creates GitHub repositories for teams.

Request Body:

{
  "semesterId": "sem-s25",
  "teamIds": ["team-1", "team-2", "team-3"]
}

Response:

{
  "created": [
    { "teamId": "team-1", "repoUrl": "https://github.com/epics-org/team-1", "success": true },
    { "teamId": "team-2", "repoUrl": "https://github.com/epics-org/team-2", "success": true }
  ],
  "failed": [
    { "teamId": "team-3", "error": "Repository already exists", "success": false }
  ]
}

Discord Integration

Manages Discord bot operations and server setup.

GET /api/discord/status

Gets Discord bot status and uptime.

Response:

{
  "success": true,
  "data": {
    "status": "RUNNING",
    "uptime": 3600000,
    "uptimeFormatted": "1h 0m",
    "error": null
  },
  "timestamp": "2026-05-08T12:00:00Z"
}

POST /api/discord/start

Starts the Discord bot.

Response:

{
  "success": true,
  "message": "Discord bot started successfully"
}

POST /api/discord/stop

Stops the Discord bot.


POST /api/discord/restart

Restarts the Discord bot.


POST /api/discord/update-channels

Updates Discord channels for teams (creates/renames).

Request Body:

{
  "semesterId": "sem-s25",
  "teamIds": ["team-1", "team-2"]
}

DELETE /api/discord/delete-channels

Deletes Discord channels for teams.


POST /api/discord/delete-roles

Deletes Discord roles for teams.


POST /api/discord/assign-project-roles

Assigns project-specific Discord roles to students.

Request Body:

{
  "projectId": "proj-1",
  "memberIds": ["member-1", "member-2"]
}

GET /api/discord/project-roles

Retrieves Discord roles associated with projects.

Response:

[
  {
    "projectId": "proj-1",
    "projectName": "Project Alpha",
    "roleId": "discord-role-1",
    "roleName": "Team-Alpha",
    "members": 4
  },
  { ... }
]

GET /api/discord/diagnostics

Runs diagnostics on Discord integration.

Response:

{
  "botConnected": true,
  "guildsCount": 1,
  "channelsCount": 15,
  "rolesCount": 30,
  "errors": [],
  "warnings": [
    "Role 'Advisor' not found",
    "Channel 'general' is missing from guild"
  ]
}

Partners

Manages partner organizations.

GET /api/partners

Retrieves all partners.

Response:

[
  {
    "id": "partner-1",
    "name": "TechCorp Inc",
    "email": "contact@techcorp.com",
    "phone": "555-0123",
    "projectCount": 3
  },
  { ... }
]

POST /api/partners

Creates a new partner.


Bids

Manages project bids and proposals.

GET /api/bids

Retrieves all bids.


POST /api/bids

Creates a new bid.


Database

Utility endpoints for database management.

GET /api/database/seed

Seeds database with sample data (development only).


POST /api/database/reset

Resets database to initial state (development only).


Common Patterns

Filtering & Querying

Most GET endpoints support query parameters for filtering:

GET /api/students?status=ACTIVE&major=CS
GET /api/projects?type=SW&partnerName=TechCorp
GET /api/teams?semesterId=sem-s25

Pagination

(Planned) Most list endpoints will support:

GET /api/students?page=1&limit=20&sort=name&order=asc

Error Handling

All errors return appropriate HTTP status codes:

Status Meaning
200 Success
400 Bad Request (missing/invalid params)
404 Not Found (resource doesn't exist)
409 Conflict (duplicate, constraint violation)
500 Internal Server Error

Workflow Examples

Complete Team Generation Workflow

// 1. Get semesters
const semesters = await fetch('/api/semesters').then(r => r.json());
const semesterId = semesters[0].id;

// 2. Get students and projects
const students = await fetch(`/api/students?choices=true`).then(r => r.json());
const projects = await fetch(`/api/projects`).then(r => r.json());

// 3. Generate teams using CPSAT algorithm
const result = await fetch('/api/teams/generate', {
  method: 'POST',
  body: JSON.stringify({
    semesterId,
    config: {
      min_team_size: 4,
      max_team_size: 6,
      prioritize_3200_first_choice: true
    }
  })
}).then(r => r.json());

// 4. Review assignments (can make manual adjustments)
const teams = result.teamAssignments;

// 5. Assign students to teams
for (const [projectId, studentIds] of Object.entries(teams)) {
  const team = await getTeamForProject(projectId, semesterId);
  await fetch(`/api/teams/assign`, {
    method: 'POST',
    body: JSON.stringify({
      teamId: team.id,
      studentIds
    })
  });
}

// 6. Create GitHub repos and Discord channels
await fetch('/api/github/create-repos', {
  method: 'POST',
  body: JSON.stringify({ semesterId })
});

await fetch('/api/discord/update-channels', {
  method: 'POST',
  body: JSON.stringify({ semesterId })
});

Development

Adding New Endpoints

  1. Create file in server/api/ with Nuxt naming convention:

    • GET: resource.get.ts or resource/[id].ts
    • POST: resource.post.ts
    • PUT: resource.put.ts
    • DELETE: resource.delete.ts
  2. Export default handler:

export default defineEventHandler(async (event) => {
  // Implementation
});
  1. Access request data:
const { query } = getQuery(event);              // GET params
const body = await readBody(event);             // POST body
const { id } = event.context.params;            // Route params
  1. Access database:
const result = await event.context.client.student.findMany();

Security Considerations

  • Implement authentication (JWT/OAuth)
  • Add authorization checks for admin endpoints
  • Validate all input data (types, lengths, formats)
  • Implement rate limiting
  • Add CORS policy
  • Sanitize database inputs (SQL injection prevention via Prisma)
  • Use HTTPS in production
  • Implement audit logging for sensitive operations

References


Clone this wiki locally