-
Notifications
You must be signed in to change notification settings - Fork 3
APIs
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
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/
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."
}Represents project team assignments for a semester.
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:semesterIdnot provided
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/assignto save)
Error Cases:
-
400:semesterIdrequired 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)
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": [...]
}Exports team assignments to a file (CSV, Excel, etc.).
Request Body:
{
"semesterId": "sem-s25",
"format": "csv"
}Response: File download
Creates new teams for a semester.
Request Body:
{
"semesterId": "sem-s25",
"projectIds": ["proj-1", "proj-2", "proj-3"]
}Deletes a specific team.
Represents EPICS students and their project preferences.
Retrieves all students with optional choice/preference data.
Query Parameters:
-
choices(optional): Include student project choices iftrue(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[]
}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"]
}Deletes a student.
Retrieves a single student by ID.
Represents EPICS projects offered by partners.
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
}Retrieves recently modified projects.
Query Parameters:
-
limit(optional): Number of projects to return (default: 10)
Creates a new project.
Request Body:
{
"name": "Project Alpha",
"description": "Mobile app development",
"type": "SW",
"partnerId": "partner-1",
"requiredSkills": ["React", "TypeScript"],
"preferredMajors": ["CS", "SE"]
}Deletes a project.
Retrieves a single project by ID.
Represents academic semesters (Spring, Fall, Summer).
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"
},
{ ... }
]Creates a new semester.
Request Body:
{
"name": "Fall 2026",
"year": 2026,
"season": "FALL"
}Retrieves a single semester by ID.
Represents system users (typically advisors, admins).
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"
}Creates a new user.
Request Body:
{
"email": "admin@university.edu",
"name": "Admin User",
"password": "hashedPassword",
"role": "ADMIN"
}Updates user information.
Request Body:
{
"name": "Updated Name",
"role": "ADVISOR"
}Deletes a user.
Retrieves demographic data and analytics.
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 - iftrue, 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
Submits or updates demographic data.
Manages GitHub repository creation and connection for project teams.
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"
}Connects to GitHub via OAuth.
Request Body:
{
"authCode": "oauth_code_from_github"
}Disconnects from GitHub.
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 }
]
}Manages Discord bot operations and server setup.
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"
}Starts the Discord bot.
Response:
{
"success": true,
"message": "Discord bot started successfully"
}Stops the Discord bot.
Restarts the Discord bot.
Updates Discord channels for teams (creates/renames).
Request Body:
{
"semesterId": "sem-s25",
"teamIds": ["team-1", "team-2"]
}Deletes Discord channels for teams.
Deletes Discord roles for teams.
Assigns project-specific Discord roles to students.
Request Body:
{
"projectId": "proj-1",
"memberIds": ["member-1", "member-2"]
}Retrieves Discord roles associated with projects.
Response:
[
{
"projectId": "proj-1",
"projectName": "Project Alpha",
"roleId": "discord-role-1",
"roleName": "Team-Alpha",
"members": 4
},
{ ... }
]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"
]
}Manages partner organizations.
Retrieves all partners.
Response:
[
{
"id": "partner-1",
"name": "TechCorp Inc",
"email": "contact@techcorp.com",
"phone": "555-0123",
"projectCount": 3
},
{ ... }
]Creates a new partner.
Manages project bids and proposals.
Retrieves all bids.
Creates a new bid.
Utility endpoints for database management.
Seeds database with sample data (development only).
Resets database to initial state (development only).
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
(Planned) Most list endpoints will support:
GET /api/students?page=1&limit=20&sort=name&order=asc
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 |
// 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 })
});-
Create file in
server/api/with Nuxt naming convention:-
GET:resource.get.tsorresource/[id].ts -
POST:resource.post.ts -
PUT:resource.put.ts -
DELETE:resource.delete.ts
-
-
Export default handler:
export default defineEventHandler(async (event) => {
// Implementation
});- Access request data:
const { query } = getQuery(event); // GET params
const body = await readBody(event); // POST body
const { id } = event.context.params; // Route params- Access database:
const result = await event.context.client.student.findMany();- 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
- Framework: Nuxt 3 Server Routes
- Database: Prisma (see prisma/schema.prisma)
- Algorithm: ALGORITHM - Team generation via CPSAT
- Services: server/services/
Wiki
Website Functionality
Demographics Workflows
Project Plans
- [S25] Team Formation Plan
- [S25] Demographics Plan
- [F24] Team Formation Plan
- [F24] GitHub/Discord Plan
- [F24] Demographics Plan
Resources