-
Notifications
You must be signed in to change notification settings - Fork 0
API Docs (new)
GET /auth/googleInitiates Google OAuth2 authentication flow.
Response:
- Redirects to Google consent screen
GET /google/callbackHandles Google OAuth2 callback.
Response:
- Redirects to
/update-profilefor new users - Redirects to
/profilefor existing users
GET /auth/githubInitiates GitHub OAuth2 authentication flow.
Response:
- Redirects to GitHub consent screen
GET /github/callbackHandles GitHub OAuth2 callback.
Response:
- Redirects to
/update-profilefor new users - Redirects to
/profilefor existing users
GET /logoutDestroys the user's session.
Response:
- Redirects to home page
GET /clubsQuery Parameters:
-
page(optional): Page number (default: 1) -
limit(optional): Items per page (default: 10, max: 50) -
sort(optional): Sort fields (e.g.,-createdAt,name) -
fields(optional): Fields to include (e.g.,name,description,logo) -
include(optional): Relations to include (e.g.,supervisor,members) -
search(optional): Search term -
status[eq](optional): Filter by status -
type[eq](optional): Filter by type
Response:
{
"data": {
"clubs": [
{
"id": 1,
"name": "Programming Club",
"description": "A club for programming enthusiasts",
"logo": "https://example.com/logo.png",
"type": "specialized",
"status": "active",
"foundingDate": "2024-01-01",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 1,
"pages": 1
}
}
}GET /clubs/:clubIdPath Parameters:
-
clubId: Club ID
Query Parameters:
-
fields(optional): Fields to include -
include(optional): Relations to include
Response:
{
"data": {
"id": 1,
"name": "Programming Club",
"description": "A club for programming enthusiasts",
"logo": "https://example.com/logo.png",
"type": "specialized",
"status": "active",
"foundingDate": "2024-01-01",
"supervisor": {
"id": 1,
"name": "Dr. John Doe"
},
"members": [
{
"id": 1,
"displayName": "Jane Smith",
"role": "member"
}
],
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}POST /clubsRequest Body:
{
"name": "Programming Club",
"description": "A club for programming enthusiasts",
"logo": "https://example.com/logo.png",
"supervisorId": 1,
"type": "specialized",
"foundingDate": "2024-01-01"
}Validation Rules:
-
name: String, min length 3, max length 100, unique -
description: String, max length 500 -
logo: URL string, max length 4096 -
supervisorId: Positive integer -
type: Enum ["general", "specialized"] -
foundingDate: Optional date
Response:
{
"data": {
"id": 1,
"name": "Programming Club",
"description": "A club for programming enthusiasts",
"logo": "https://example.com/logo.png",
"type": "specialized",
"status": "active",
"foundingDate": "2024-01-01",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}PUT /clubs/:clubIdPath Parameters:
-
clubId: Club ID
Request Body:
{
"name": "Updated Club Name",
"description": "Updated description",
"logo": "https://example.com/new-logo.png",
"type": "general",
"status": "inactive"
}Validation Rules:
- Same as create club, but all fields are optional
Response:
{
"data": {
"id": 1,
"name": "Updated Club Name",
"description": "Updated description",
"logo": "https://example.com/new-logo.png",
"type": "general",
"status": "inactive",
"updatedAt": "2024-01-02T00:00:00Z"
}
}DELETE /clubs/:clubIdPath Parameters:
-
clubId: Club ID
Response:
{
"data": {
"id": 1,
"name": "Programming Club",
"isArchived": true,
"archivedAt": "2024-01-02T00:00:00Z",
"updatedAt": "2024-01-02T00:00:00Z"
}
}Note: This endpoint performs a soft delete by setting isArchived to true. Archived records are automatically deleted after 1 year by a system cleanup job.
GET /clubs/:clubId/membershipsPath Parameters:
-
clubId: Club ID
Query Parameters:
-
page(optional): Page number (default: 1) -
limit(optional): Items per page (default: 10, max: 50) -
sort(optional): Sort fields (e.g.,-joinedAt,role) -
fields(optional): Fields to include -
include(optional): Relations to include -
status[eq](optional): Filter by status -
role[eq](optional): Filter by role -
isArchived[eq](optional): Filter by archive status
Response:
{
"data": {
"memberships": [
{
"id": 1,
"userId": 1,
"clubId": 1,
"role": "member",
"status": "active",
"tag": "2023-2",
"joinedAt": "2024-01-01T00:00:00Z",
"user": {
"id": 1,
"displayName": "Jane Smith",
"profileImage": "https://example.com/profile.jpg"
}
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 1,
"pages": 1
}
}
}GET /clubs/:clubId/memberships/:membershipIdPath Parameters:
-
clubId: Club ID -
membershipId: Membership ID
Query Parameters:
-
fields(optional): Fields to include -
include(optional): Relations to include
Response:
{
"data": {
"id": 1,
"userId": 1,
"clubId": 1,
"role": "member",
"status": "active",
"tag": "2023-2",
"joinedAt": "2024-01-01T00:00:00Z",
"user": {
"id": 1,
"displayName": "Jane Smith",
"profileImage": "https://example.com/profile.jpg"
}
}
}POST /clubs/:clubId/membershipsPath Parameters:
-
clubId: Club ID
Request Body:
{
"userId": 1,
"role": "member",
"tag": "مدير المصممين"
}Validation Rules:
-
userId: Positive integer -
role: Enum ["clubAdmin", "hr", "member"] -
tag: String, max length 50 (optional)
Response:
{
"data": {
"id": 1,
"userId": 1,
"clubId": 1,
"role": "member",
"status": "pending",
"tag": "مدير كبير",
"joinedAt": "2024-01-01T00:00:00Z"
}
}Note: This endpoint requires club admin privileges and creates a membership with "pending" status by default.
POST /clubs/:clubId/memberships/mePath Parameters:
-
clubId: Club ID
Response:
{
"data": {
"id": 1,
"userId": 1,
"clubId": 1,
"role": "member",
"status": "pending",
"joinedAt": "2024-01-01T00:00:00Z"
}
}Note: This creates a membership application that must be reviewed by club administrators.
PUT /clubs/:clubId/memberships/:membershipIdPath Parameters:
-
clubId: Club ID -
membershipId: Membership ID
Request Body:
{
"role": "hr",
"status": "active",
"tag": "مدير المهمات الصعبة"
}Validation Rules:
-
role: Enum ["clubAdmin", "hr", "member"] -
status: Enum ["active", "inactive", "pending", "denied"] -
tag: String, max length 50 (optional)
Response:
{
"data": {
"id": 1,
"userId": 1,
"clubId": 1,
"role": "hr",
"status": "active",
"tag": "مدير المهمات الصعبة",
"updatedAt": "2024-01-02T00:00:00Z"
}
}Note: Club administrators use this endpoint to accept or deny membership applications by updating the status.
DELETE /clubs/:clubId/memberships/mePath Parameters:
-
clubId: Club ID
Response:
{
"data": {
"id": 1,
"userId": 1,
"clubId": 1,
"role": "member",
"status": "inactive",
"updatedAt": "2024-01-02T00:00:00Z"
}
}DELETE /clubs/:clubId/memberships/:membershipIdPath Parameters:
-
clubId: Club ID -
membershipId: Membership ID
Response:
{
"data": {
"id": 1,
"userId": 1,
"clubId": 1,
"isArchived": true,
"archivedAt": "2024-01-02T00:00:00Z"
}
}Note: This endpoint performs a soft delete by setting isArchived to true. Archived memberships are automatically deleted after 1 year by a system cleanup job.
PUT /clubs/:clubId/memberships/inactivePath Parameters:
-
clubId: Club ID
Response:
{
"data": {
"archivedCount": 15,
"archivedMemberships": [
{
"id": 1,
"userId": 1,
"clubId": 1,
"role": "member",
"status": "inactive",
"isArchived": true,
"archivedAt": "2024-01-02T00:00:00Z",
"volunteerHours": 45
}
]
}
}Note: Archived memberships are automatically deleted after 1 year by a system cleanup job.
GET /eventsQuery Parameters:
-
page(optional): Page number (default: 1) -
limit(optional): Items per page (default: 10, max: 50) -
sort(optional): Sort fields (e.g.,-eventStart,name) -
fields(optional): Fields to include -
include(optional): Relations to include -
search(optional): Search term -
category[eq](optional): Filter by category -
clubId[eq](optional): Filter by club ID -
eventStart[gte](optional): Filter by start date -
eventEnd[lte](optional): Filter by end date
Response:
{
"data": {
"events": [
{
"id": 1,
"name": "Web Development Workshop",
"description": "Learn web development basics",
"poster": "https://example.com/poster.png",
"location": "Room 101",
"registrationStart": "2024-01-01T00:00:00Z",
"registrationEnd": "2024-01-15T00:00:00Z",
"eventStart": "2024-01-20T00:00:00Z",
"eventEnd": "2024-01-21T00:00:00Z",
"seatsAvailable": 50,
"category": "workshop",
"clubId": 1
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 1,
"pages": 1
}
}
}GET /events/:eventIdPath Parameters:
-
eventId: Event ID
Query Parameters:
-
fields(optional): Fields to include -
include(optional): Relations to include
Response:
{
"data": {
"id": 1,
"name": "Web Development Workshop",
"description": "Learn web development basics",
"poster": "https://example.com/poster.png",
"location": "Room 101",
"registrationStart": "2024-01-01T00:00:00Z",
"registrationEnd": "2024-01-15T00:00:00Z",
"eventStart": "2024-01-20T00:00:00Z",
"eventEnd": "2024-01-21T00:00:00Z",
"seatsAvailable": 50,
"category": "workshop",
"club": {
"id": 1,
"name": "Programming Club"
},
"registrations": [
{
"id": 1,
"user": {
"id": 1,
"displayName": "Jane Smith"
},
"status": "accepted"
}
]
}
}POST /clubs/:clubId/eventsPath Parameters:
-
clubId: Club ID
Request Body:
{
"name": "Web Development Workshop",
"description": "Learn web development basics",
"poster": "https://example.com/poster.png",
"location": "Room 101",
"registrationStart": "2024-01-01T00:00:00Z",
"registrationEnd": "2024-01-15T00:00:00Z",
"eventStart": "2024-01-20T00:00:00Z",
"eventEnd": "2024-01-21T00:00:00Z",
"seatsAvailable": 50,
"category": "workshop"
}Validation Rules:
-
name: String, min length 3, max length 100 -
description: String, max length 1000 -
poster: URL string, max length 4096 -
location: String, min length 3, max length 255 -
registrationStart: Date -
registrationEnd: Date (must be after registrationStart) -
eventStart: Date (must be after registrationEnd) -
eventEnd: Date (must be after eventStart) -
seatsAvailable: Integer, min 1, max 10000 -
category: Enum ["bootcamp", "workshop", "meeting", "hackathon", "seminar", "conference", "networking"]
Response:
{
"data": {
"id": 1,
"name": "Web Development Workshop",
"description": "Learn web development basics",
"poster": "https://example.com/poster.png",
"location": "Room 101",
"registrationStart": "2024-01-01T00:00:00Z",
"registrationEnd": "2024-01-15T00:00:00Z",
"eventStart": "2024-01-20T00:00:00Z",
"eventEnd": "2024-01-21T00:00:00Z",
"seatsAvailable": 50,
"category": "workshop",
"clubId": 1,
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}PUT /events/:eventIdPath Parameters:
-
eventId: Event ID
Request Body:
{
"name": "Updated Workshop Name",
"description": "Updated description",
"poster": "https://example.com/new-poster.png",
"location": "Room 102",
"seatsAvailable": 60
}Validation Rules:
- Same as create event, but all fields are optional
Response:
{
"data": {
"id": 1,
"name": "Updated Workshop Name",
"description": "Updated description",
"poster": "https://example.com/new-poster.png",
"location": "Room 102",
"seatsAvailable": 60,
"updatedAt": "2024-01-02T00:00:00Z"
}
}POST /events/:eventId/registrationsPath Parameters:
-
eventId: Event ID
Response:
{
"data": {
"id": 1,
"userId": 1,
"eventId": 1,
"status": "pending",
"createdAt": "2024-01-01T00:00:00Z"
}
}GET /events/registrations/meQuery Parameters:
-
page(optional): Page number (default: 1) -
limit(optional): Items per page (default: 10, max: 50) -
status[eq](optional): Filter by status -
include(optional): Relations to include
Response:
{
"data": {
"registrations": [
{
"id": 1,
"eventId": 1,
"status": "pending",
"createdAt": "2024-01-01T00:00:00Z",
"event": {
"id": 1,
"name": "Web Development Workshop",
"eventStart": "2024-01-20T00:00:00Z"
}
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 1,
"pages": 1
}
}
}GET /events/:eventId/registrationsPath Parameters:
-
eventId: Event ID
Query Parameters:
-
page(optional): Page number (default: 1) -
limit(optional): Items per page (default: 10, max: 50) -
status[eq](optional): Filter by status -
include(optional): Relations to include
Response:
{
"data": {
"registrations": [
{
"id": 1,
"userId": 1,
"status": "pending",
"createdAt": "2024-01-01T00:00:00Z",
"user": {
"id": 1,
"displayName": "Jane Smith",
"profileImage": "https://example.com/profile.jpg"
}
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 1,
"pages": 1
}
}
}PUT /events/:eventId/registrations/:registrationIdPath Parameters:
-
eventId: Event ID -
registrationId: Registration ID
Request Body:
{
"status": "accepted"
}Validation Rules:
-
status: Enum ["pending", "accepted", "rejected"]
Response:
{
"data": {
"id": 1,
"userId": 1,
"eventId": 1,
"status": "accepted",
"updatedAt": "2024-01-02T00:00:00Z"
}
}DELETE /events/:eventId/registrations/mePath Parameters:
-
eventId: Event ID
Response:
{
"data": {
"message": "Successfully canceled event registration"
}
}GET /tasksQuery Parameters:
-
page(optional): Page number (default: 1) -
limit(optional): Items per page (default: 10, max: 50) -
sort(optional): Sort fields (e.g.,-createdAt,title) -
fields(optional): Fields to include -
include(optional): Relations to include -
search(optional): Search term -
status[eq](optional): Filter by status -
category[eq](optional): Filter by category -
clubMembershipId[eq](optional): Filter by club membership ID
Response:
{
"data": {
"tasks": [
{
"id": 1,
"title": "Website Development",
"description": "Develop club website",
"volunteeredSeconds": 7200,
"category": "club_programs_projects",
"status": "pending",
"attachment": "https://example.com/attachment.pdf",
"reviewComment": null,
"clubMembership": {
"id": 1,
"user": {
"id": 1,
"displayName": "Jane Smith"
}
},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 1,
"pages": 1
}
}
}GET /tasks/:taskIdPath Parameters:
-
taskId: Task ID
Query Parameters:
-
fields(optional): Fields to include -
include(optional): Relations to include
Response:
{
"data": {
"id": 1,
"title": "Website Development",
"description": "Develop club website",
"volunteeredSeconds": 7200,
"category": "club_programs_projects",
"status": "pending",
"attachment": "https://example.com/attachment.pdf",
"reviewComment": null,
"clubMembership": {
"id": 1,
"user": {
"id": 1,
"displayName": "Jane Smith"
}
},
"createdByUser": {
"id": 1,
"displayName": "John Doe"
},
"updatedByUser": {
"id": 1,
"displayName": "John Doe"
},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}POST /tasksRequest Body:
{
"clubMembershipId": 1,
"title": "Website Development",
"description": "Develop club website",
"volunteeredSeconds": 7200,
"category": "club_programs_projects",
"attachment": "https://example.com/attachment.pdf"
}Validation Rules:
-
clubMembershipId: Positive integer -
title: String, min length 1, max length 100 -
description: String, min length 1, max length 500 -
volunteeredSeconds: Integer, min 0 -
category: Enum ["club_programs_projects", "uni_collab", "external_collab", "club_initiatives", "internal_activities", "community_contributions"] -
attachment: URL string, max length 4096 (optional)
Response:
{
"data": {
"id": 1,
"title": "Website Development",
"description": "Develop club website",
"volunteeredSeconds": 7200,
"category": "club_programs_projects",
"status": "pending",
"attachment": "https://example.com/attachment.pdf",
"reviewComment": null,
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}PUT /tasks/:taskIdPath Parameters:
-
taskId: Task ID
Request Body:
{
"title": "Updated Website Development",
"description": "Updated description",
"volunteeredSeconds": 9000,
"category": "club_initiatives",
"attachment": "https://example.com/new-attachment.pdf",
"status": "accepted",
"reviewComment": "Great work! Approved."
}Validation Rules:
- Same as create task, but all fields are optional
-
status: Enum ["accepted", "changes_requested", "denied", "pending"] -
reviewComment: String, max length 500 (optional)
Response:
{
"data": {
"id": 1,
"title": "Updated Website Development",
"description": "Updated description",
"volunteeredSeconds": 9000,
"category": "club_initiatives",
"status": "accepted",
"attachment": "https://example.com/new-attachment.pdf",
"reviewComment": "Great work! Approved.",
"updatedAt": "2024-01-02T00:00:00Z"
}
}DELETE /tasks/:taskIdPath Parameters:
-
taskId: Task ID
Response:
{
"data": {
"id": 1,
"isArchived": true,
"archivedAt": "2024-01-02T00:00:00Z"
}
}Note: This endpoint performs a soft delete by setting isArchived to true. Archived tasks are automatically deleted after 1 year by a system cleanup job.
PUT /profileRequest Body:
{
"displayName": "John Doe",
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"uniId": "123456789",
"nationalId": "1234567890",
"phoneNumber": "1234567890",
"profileImage": "https://example.com/profile.jpg"
}Validation Rules:
-
displayName: String, min length 2 -
firstName: String, min length 2 -
lastName: String (optional) -
email: Valid email address, unique -
uniId: String, length 9 (optional) -
nationalId: String, length 10, digits only -
phoneNumber: String, length 10, digits only -
profileImage: URL string
Response:
{
"data": {
"id": 1,
"displayName": "John Doe",
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"uniId": "123456789",
"nationalId": "1234567890",
"phoneNumber": "1234567890",
"profileImage": "https://example.com/profile.jpg",
"updatedAt": "2024-01-02T00:00:00Z"
}
}DELETE /profileResponse:
{
"data": {
"message": "Account successfully deleted"
}
}-
page: Page number (default: 1) -
limit: Items per page (default: 10, max: 50)
-
sort: Comma-separated fields with optional-prefix for descending order- Example:
-createdAt,name
- Example:
-
fields: Comma-separated list of fields to include- Example:
name,description,logo
- Example:
-
include: Comma-separated list of relations to include- Example:
supervisor,members
- Example:
-
field[operator]=valueformat - Operators:
-
eq: Equal to -
neq: Not equal to -
gt: Greater than -
gte: Greater than or equal to -
lt: Less than -
lte: Less than or equal to -
in: In array (comma-separated values) -
nin: Not in array (comma-separated values) -
like: Pattern matching -
ilike: Case-insensitive pattern matching
-
-
search: Search term for text fields
The API uses standard HTTP status codes to indicate the success or failure of requests:
-
200 OK: Request succeeded -
201 Created: Resource created successfully -
204 No Content: Request succeeded but no content returned -
400 Bad Request: Invalid request parameters -
401 Unauthorized: Authentication required -
403 Forbidden: Insufficient permissions -
404 Not Found: Resource not found -
409 Conflict: Resource conflict (e.g., already exists) -
500 Internal Server Error: Server error
All error responses follow this format:
{
"error": {
"code": "ERROR_CODE",
"message": "Human readable error message",
"details": {
// Optional additional error details
}
}
}-
INVALID_REQUEST: Invalid request parameters or malformed request -
UNAUTHORIZED: Authentication required or invalid credentials -
FORBIDDEN: User lacks required permissions -
NOT_FOUND: Requested resource not found -
CONFLICT: Resource conflict (e.g., already exists) -
VALIDATION_ERROR: Input validation failed -
INTERNAL_ERROR: Internal server error
The system includes an automated cleanup job that permanently deletes archived records after they have been archived for 1 year. This applies to:
- Archived clubs
- Archived memberships
- Archived events
The cleanup job runs daily and only affects records that have been archived for more than 365 days.