2025-11-30 18:54:34 +07:00
|
|
|
# Hackathon Backoffice API Contract
|
|
|
|
|
|
2025-11-30 18:57:04 +07:00
|
|
|
## GET /api/v1/admin/dashboard
|
2025-11-30 18:54:34 +07:00
|
|
|
|
|
|
|
|
### Purpose
|
|
|
|
|
|
|
|
|
|
Single endpoint delivering aggregated metrics for the IMPHNEN x Kolosal.ai Hackathon dashboard.
|
|
|
|
|
|
|
|
|
|
### Authentication & Authorization
|
|
|
|
|
|
|
|
|
|
- Requires admin (backoffice) scope: e.g. `role=admin`
|
|
|
|
|
- 401 if unauthenticated, 403 if authenticated but lacking required scope.
|
|
|
|
|
|
|
|
|
|
### Examples
|
|
|
|
|
|
|
|
|
|
```
|
2025-11-30 18:57:04 +07:00
|
|
|
GET /api/v1/admin/dashboard
|
2025-11-30 18:54:34 +07:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Response Schema
|
|
|
|
|
|
|
|
|
|
```jsonc
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"total_participants": 1261,
|
|
|
|
|
"total_teams": 206,
|
|
|
|
|
"total_submissions": 0 // Total project submitted
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Field Types
|
|
|
|
|
|
|
|
|
|
| Path | Type | Notes |
|
|
|
|
|
| ------------------------- | ------- | --------------------- |
|
|
|
|
|
| `data.total_participants` | integer | >= 0 |
|
|
|
|
|
| `data.total_teams` | integer | >= 0 |
|
|
|
|
|
| `data.total_submissions` | integer | <= `data.total_teams` |
|
|
|
|
|
|
|
|
|
|
### Errors
|
|
|
|
|
|
|
|
|
|
| Status | Code | Message | Notes |
|
|
|
|
|
| ------ | ---------------- | ----------------------------- | --------------------- |
|
|
|
|
|
| 401 | `unauthorized` | `authentication required` | Missing/invalid token |
|
|
|
|
|
| 403 | `forbidden` | `insufficient permissions` | Lacks required scope |
|
|
|
|
|
| 429 | `rate_limited` | `too many dashboard requests` | Rate limiting |
|
|
|
|
|
| 500 | `internal_error` | `unexpected server error` | Unhandled exception |
|
|
|
|
|
|
2025-12-01 11:41:56 +07:00
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## GET /api/v1/admin/users
|
|
|
|
|
|
|
|
|
|
### Purpose
|
|
|
|
|
|
|
|
|
|
Retrieve paginated list of hackathon participants with filtering, searching, and sorting capabilities for backoffice user management.
|
|
|
|
|
|
|
|
|
|
### Authentication & Authorization
|
|
|
|
|
|
|
|
|
|
- Requires admin (backoffice) scope: e.g. `role=admin`
|
|
|
|
|
- 401 if unauthenticated, 403 if authenticated but lacking required scope.
|
|
|
|
|
|
|
|
|
|
### Query Parameters
|
|
|
|
|
|
|
|
|
|
| Parameter | Type | Required | Default | Description |
|
|
|
|
|
| ------------ | ------- | -------- | ------------ | ------------------------------------------------------------- |
|
|
|
|
|
| `page` | integer | No | 1 | Page number (1-based) |
|
2025-12-02 18:11:34 +07:00
|
|
|
| `limit` | integer | No | 10 | Items per page (1-100) |
|
2025-12-01 11:41:56 +07:00
|
|
|
| `search` | string | No | - | Search by name or location (case-insensitive) |
|
|
|
|
|
| `status` | string | No | `all` | Filter by status: `all`, `active`, `inactive` |
|
|
|
|
|
| `location` | string | No | `all` | Filter by location or `all` |
|
|
|
|
|
| `skills` | string | No | - | Comma-separated skill filters |
|
|
|
|
|
| `sort_by` | string | No | `created_at` | Sort field: `fullname`, `location`, `is_active`, `created_at` |
|
|
|
|
|
| `sort_order` | string | No | `desc` | Sort order: `asc`, `desc` |
|
|
|
|
|
|
|
|
|
|
### Examples
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
GET /api/v1/admin/users
|
|
|
|
|
GET /api/v1/admin/users?page=2&limit=10
|
|
|
|
|
GET /api/v1/admin/users?search=john&status=active
|
|
|
|
|
GET /api/v1/admin/users?location=Jakarta&skills=Frontend Developer,UI/UX Designer
|
|
|
|
|
GET /api/v1/admin/users?sort_by=fullname&sort_order=asc
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Response Schema
|
|
|
|
|
|
|
|
|
|
```jsonc
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"users": [
|
|
|
|
|
{
|
|
|
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
|
|
|
"avatar": "https://example.com/avatars/user1.jpg", // Optional
|
|
|
|
|
"fullname": "Budi Santoso",
|
|
|
|
|
"bio": "Passionate developer with 5+ years experience", // Optional
|
|
|
|
|
"location": "Jakarta",
|
|
|
|
|
"is_active": true,
|
2025-12-02 18:11:34 +07:00
|
|
|
"skills": ["Frontend Developer", "UI/UX Designer"], // Optional
|
2025-12-01 11:41:56 +07:00
|
|
|
"created_at": "2024-11-15T08:30:00Z",
|
|
|
|
|
"updated_at": "2024-11-30T14:22:00Z"
|
|
|
|
|
}
|
|
|
|
|
// ... more users
|
|
|
|
|
],
|
|
|
|
|
"pagination": {
|
|
|
|
|
"current_page": 1,
|
|
|
|
|
"total_pages": 15,
|
|
|
|
|
"total_items": 287,
|
|
|
|
|
"items_per_page": 20,
|
|
|
|
|
"has_next": true,
|
|
|
|
|
"has_prev": false
|
|
|
|
|
},
|
|
|
|
|
"filters": {
|
|
|
|
|
"available_locations": ["Jakarta", "Bandung", "Surabaya", "Medan", "Yogyakarta"],
|
|
|
|
|
"available_skills": ["Frontend Developer", "Backend Developer", "Full Stack Developer", "DevOps Engineer", "UI/UX Designer", "Product Manager", "Data Scientist", "Mobile Developer"]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Field Types
|
|
|
|
|
|
|
|
|
|
| Path | Type | Notes |
|
|
|
|
|
| ------------------------- | ------- | ------------------------------ |
|
|
|
|
|
| `data.users[].id` | string | UUID format |
|
|
|
|
|
| `data.users[].avatar` | string | URL, nullable |
|
2025-12-02 18:11:34 +07:00
|
|
|
| `data.users[].fullname` | string | Required |
|
2025-12-01 11:41:56 +07:00
|
|
|
| `data.users[].bio` | string | Optional, max 500 chars |
|
|
|
|
|
| `data.users[].location` | string | Required, from predefined list |
|
|
|
|
|
| `data.users[].is_active` | boolean | Account status |
|
|
|
|
|
| `data.users[].skills` | array | Array of skill strings |
|
|
|
|
|
| `data.users[].created_at` | string | ISO 8601 timestamp |
|
|
|
|
|
| `data.users[].updated_at` | string | ISO 8601 timestamp |
|
|
|
|
|
| `data.pagination.*` | integer | Pagination metadata |
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## GET /api/v1/admin/users/{user_id}
|
|
|
|
|
|
|
|
|
|
### Purpose
|
|
|
|
|
|
|
|
|
|
Retrieve detailed information for a specific user by ID.
|
|
|
|
|
|
|
|
|
|
### Authentication & Authorization
|
|
|
|
|
|
|
|
|
|
- Requires admin (backoffice) scope: e.g. `role=admin`
|
|
|
|
|
|
|
|
|
|
### Path Parameters
|
|
|
|
|
|
|
|
|
|
| Parameter | Type | Required | Description |
|
|
|
|
|
| --------- | ------ | -------- | ----------- |
|
|
|
|
|
| `user_id` | string | Yes | User UUID |
|
|
|
|
|
|
|
|
|
|
### Examples
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
GET /api/v1/admin/users/550e8400-e29b-41d4-a716-446655440000
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Response Schema
|
|
|
|
|
|
|
|
|
|
```jsonc
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
|
|
|
"avatar": "https://example.com/avatars/user1.jpg",
|
|
|
|
|
"fullname": "Budi Santoso",
|
|
|
|
|
"bio": "Passionate developer with 5+ years experience",
|
|
|
|
|
"location": "Jakarta",
|
|
|
|
|
"is_active": true,
|
|
|
|
|
"skills": ["Frontend Developer", "UI/UX Designer"],
|
|
|
|
|
"created_at": "2024-11-15T08:30:00Z",
|
|
|
|
|
"updated_at": "2024-11-30T14:22:00Z"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## POST /api/v1/admin/users
|
|
|
|
|
|
|
|
|
|
### Purpose
|
|
|
|
|
|
|
|
|
|
Create a new user account in the hackathon system.
|
|
|
|
|
|
|
|
|
|
### Authentication & Authorization
|
|
|
|
|
|
|
|
|
|
- Requires admin (backoffice) scope: e.g. `role=admin`
|
|
|
|
|
|
|
|
|
|
### Request Body Schema
|
|
|
|
|
|
|
|
|
|
```jsonc
|
|
|
|
|
{
|
|
|
|
|
"fullname": "Jane Doe", // Required, 1-100 chars
|
|
|
|
|
"bio": "Experienced developer", // Optional, max 500 chars
|
|
|
|
|
"location": "Jakarta", // Required, from predefined list
|
|
|
|
|
"is_active": true, // Required, boolean
|
|
|
|
|
"skills": ["Backend Developer"], // Optional, array of valid skills
|
2025-12-02 18:11:34 +07:00
|
|
|
"avatar": "https://example.com/images/..." // Optional, URL
|
2025-12-01 11:41:56 +07:00
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Examples
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
POST /api/v1/admin/users
|
|
|
|
|
Content-Type: application/json
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
"fullname": "Jane Doe",
|
|
|
|
|
"bio": "Experienced developer passionate about AI and machine learning",
|
|
|
|
|
"location": "Jakarta",
|
|
|
|
|
"is_active": true,
|
|
|
|
|
"skills": ["Backend Developer", "Data Scientist"],
|
2025-12-02 18:11:34 +07:00
|
|
|
"avatar": "https://example.com/images/..."
|
2025-12-01 11:41:56 +07:00
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Response Schema
|
|
|
|
|
|
|
|
|
|
```jsonc
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"id": "550e8400-e29b-41d4-a716-446655440001",
|
|
|
|
|
"avatar": "https://example.com/avatars/generated_url.jpg",
|
|
|
|
|
"fullname": "Jane Doe",
|
|
|
|
|
"bio": "Experienced developer passionate about AI and machine learning",
|
|
|
|
|
"location": "Jakarta",
|
|
|
|
|
"is_active": true,
|
|
|
|
|
"skills": ["Backend Developer", "Data Scientist"],
|
|
|
|
|
"created_at": "2024-12-01T10:30:00Z",
|
|
|
|
|
"updated_at": "2024-12-01T10:30:00Z"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## PUT /api/v1/admin/users/{user_id}
|
|
|
|
|
|
|
|
|
|
### Purpose
|
|
|
|
|
|
|
|
|
|
Update an existing user's profile information.
|
|
|
|
|
|
|
|
|
|
### Authentication & Authorization
|
|
|
|
|
|
|
|
|
|
- Requires admin (backoffice) scope: e.g. `role=admin`
|
|
|
|
|
|
|
|
|
|
### Path Parameters
|
|
|
|
|
|
|
|
|
|
| Parameter | Type | Required | Description |
|
|
|
|
|
| --------- | ------ | -------- | ----------- |
|
|
|
|
|
| `user_id` | string | Yes | User UUID |
|
|
|
|
|
|
|
|
|
|
### Request Body Schema
|
|
|
|
|
|
|
|
|
|
```jsonc
|
|
|
|
|
{
|
|
|
|
|
"fullname": "Jane Smith", // Optional, 1-100 chars
|
|
|
|
|
"bio": "Senior developer", // Optional, max 500 chars, null to clear
|
|
|
|
|
"location": "Bandung", // Optional, from predefined list
|
|
|
|
|
"is_active": false, // Optional, boolean
|
|
|
|
|
"skills": ["Full Stack Developer"], // Optional, array of valid skills
|
2025-12-02 18:11:34 +07:00
|
|
|
"avatar": "https://example.com/images/..." // Optional, URL, null to remove
|
2025-12-01 11:41:56 +07:00
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Examples
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
PUT /api/v1/admin/users/550e8400-e29b-41d4-a716-446655440000
|
|
|
|
|
Content-Type: application/json
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
"fullname": "Jane Smith",
|
|
|
|
|
"location": "Bandung",
|
|
|
|
|
"is_active": false,
|
|
|
|
|
"skills": ["Full Stack Developer", "Product Manager"]
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Response Schema
|
|
|
|
|
|
|
|
|
|
```jsonc
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
|
|
|
"avatar": "https://example.com/avatars/user1.jpg",
|
|
|
|
|
"fullname": "Jane Smith",
|
|
|
|
|
"bio": "Experienced developer passionate about AI and machine learning",
|
|
|
|
|
"location": "Bandung",
|
|
|
|
|
"is_active": false,
|
|
|
|
|
"skills": ["Full Stack Developer", "Product Manager"],
|
|
|
|
|
"created_at": "2024-11-15T08:30:00Z",
|
|
|
|
|
"updated_at": "2024-12-01T10:45:00Z"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## DELETE /api/v1/admin/users/{user_id}
|
|
|
|
|
|
|
|
|
|
### Purpose
|
|
|
|
|
|
2025-12-02 18:11:34 +07:00
|
|
|
(Soft) Delete a user account from the hackathon system.
|
2025-12-01 11:41:56 +07:00
|
|
|
|
|
|
|
|
### Authentication & Authorization
|
|
|
|
|
|
|
|
|
|
- Requires admin (backoffice) scope: e.g. `role=admin`
|
|
|
|
|
|
|
|
|
|
### Path Parameters
|
|
|
|
|
|
|
|
|
|
| Parameter | Type | Required | Description |
|
|
|
|
|
| --------- | ------ | -------- | ----------- |
|
|
|
|
|
| `user_id` | string | Yes | User UUID |
|
|
|
|
|
|
|
|
|
|
### Examples
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
DELETE /api/v1/admin/users/550e8400-e29b-41d4-a716-446655440000
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Response Schema
|
|
|
|
|
|
|
|
|
|
```jsonc
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"message": "User successfully deleted",
|
|
|
|
|
"deleted_user_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
|
|
|
"deleted_at": "2024-12-01T10:50:00Z"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Common Error Responses
|
|
|
|
|
|
|
|
|
|
### User Management Endpoints
|
|
|
|
|
|
|
|
|
|
| Status | Code | Message | Notes |
|
|
|
|
|
| ------ | --------------------- | -------------------------------- | ---------------------------- |
|
|
|
|
|
| 400 | `validation_error` | `Invalid request data` | Field validation failures |
|
|
|
|
|
| 401 | `unauthorized` | `Authentication required` | Missing/invalid token |
|
|
|
|
|
| 403 | `forbidden` | `Insufficient permissions` | Lacks required scope |
|
|
|
|
|
| 404 | `user_not_found` | `User not found` | Invalid user ID |
|
|
|
|
|
| 409 | `user_already_exists` | `User with email already exists` | Duplicate user creation |
|
|
|
|
|
| 413 | `payload_too_large` | `Avatar file too large` | Avatar exceeds size limit |
|
|
|
|
|
| 422 | `invalid_skill` | `Invalid skill specified` | Skill not in allowed list |
|
|
|
|
|
| 422 | `invalid_location` | `Invalid location specified` | Location not in allowed list |
|
|
|
|
|
| 429 | `rate_limited` | `Too many requests` | Rate limiting |
|
|
|
|
|
| 500 | `internal_error` | `Unexpected server error` | Unhandled exception |
|
|
|
|
|
|
|
|
|
|
### Validation Error Details
|
|
|
|
|
|
|
|
|
|
```jsonc
|
|
|
|
|
{
|
|
|
|
|
"error": {
|
|
|
|
|
"code": "validation_error",
|
|
|
|
|
"message": "Invalid request data",
|
|
|
|
|
"details": [
|
|
|
|
|
{
|
|
|
|
|
"field": "fullname",
|
|
|
|
|
"code": "required",
|
|
|
|
|
"message": "Full name is required"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"field": "location",
|
|
|
|
|
"code": "invalid_choice",
|
|
|
|
|
"message": "Location must be one of: Jakarta, Bandung, Surabaya, Medan, Yogyakarta"
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2025-11-30 18:54:34 +07:00
|
|
|
## Rate Limiting
|
|
|
|
|
|
2025-12-01 11:41:56 +07:00
|
|
|
- **Dashboard**: 30 requests / minute / admin user
|
|
|
|
|
- **User Management**: 100 requests / minute / admin user
|
|
|
|
|
- **File Upload**: 10 avatar uploads / minute / admin user
|
|
|
|
|
- Return 429 with `Retry-After` header
|
|
|
|
|
|
|
|
|
|
## Avatar Handling
|
|
|
|
|
|
|
|
|
|
- **Supported formats**: JPEG, PNG, WebP
|
|
|
|
|
- **Max file size**: 5MB
|
|
|
|
|
- **Recommended dimensions**: 400x400px
|
|
|
|
|
- **Storage**: Uploaded avatars are processed and stored with generated URLs
|
|
|
|
|
- **URL response**: Always return publicly accessible HTTPS URLs
|
2025-11-30 18:54:34 +07:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-12-02 23:14:40 +07:00
|
|
|
## GET /api/v1/admin/teams
|
|
|
|
|
|
|
|
|
|
### Purpose
|
|
|
|
|
|
|
|
|
|
Retrieve paginated list of hackathon teams with filtering, searching, and sorting capabilities for backoffice team management.
|
|
|
|
|
|
|
|
|
|
### Authentication & Authorization
|
|
|
|
|
|
|
|
|
|
- Requires admin (backoffice) scope: e.g. `role=admin`
|
|
|
|
|
- 401 if unauthenticated, 403 if authenticated but lacking required scope.
|
|
|
|
|
|
|
|
|
|
### Query Parameters
|
|
|
|
|
|
|
|
|
|
| Parameter | Type | Required | Default | Description |
|
|
|
|
|
| -------------- | ------- | -------- | ------------ | ---------------------------------------------------------------------------------------- |
|
|
|
|
|
| `page` | integer | No | 1 | Page number (1-based) |
|
|
|
|
|
| `limit` | integer | No | 10 | Items per page (1-100) |
|
|
|
|
|
| `search` | string | No | - | Search by team name, city, or leader name (case-insensitive) |
|
|
|
|
|
| `visibility` | string | No | `all` | Filter by visibility: `all`, `public`, `private` |
|
|
|
|
|
| `city` | string | No | `all` | Filter by city or `all` |
|
|
|
|
|
| `submission` | string | No | `all` | Filter by submission status: `all`, `submitted`, `not_submitted` |
|
|
|
|
|
| `member_count` | string | No | `all` | Filter by member count: `all`, `1`, `2`, `3`, `4`, `5` |
|
|
|
|
|
| `sort_by` | string | No | `created_at` | Sort field: `name`, `city`, `visibility`, `member_count`, `has_submission`, `created_at` |
|
|
|
|
|
| `sort_order` | string | No | `desc` | Sort order: `asc`, `desc` |
|
|
|
|
|
|
|
|
|
|
### Examples
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
GET /api/v1/admin/teams
|
|
|
|
|
GET /api/v1/admin/teams?page=2&limit=10
|
|
|
|
|
GET /api/v1/admin/teams?search=innovators&visibility=public
|
|
|
|
|
GET /api/v1/admin/teams?city=Jakarta&submission=submitted&member_count=3
|
|
|
|
|
GET /api/v1/admin/teams?sort_by=name&sort_order=asc
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Response Schema
|
|
|
|
|
|
|
|
|
|
```jsonc
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"teams": [
|
|
|
|
|
{
|
|
|
|
|
"id": "team-001",
|
|
|
|
|
"name": "Team Innovators",
|
|
|
|
|
"description": "Building innovative solutions for modern problems", // Optional
|
|
|
|
|
"city": "Jakarta",
|
|
|
|
|
"banner": "https://example.com/banners/team1.jpg", // Optional
|
|
|
|
|
"logo": "https://example.com/logos/team1.jpg", // Optional
|
|
|
|
|
"visibility": "public", // "public" | "private"
|
|
|
|
|
"member_count": 3,
|
|
|
|
|
"has_submission": true,
|
|
|
|
|
"created_at": "2024-11-15T08:30:00Z",
|
|
|
|
|
"updated_at": "2024-11-30T14:22:00Z",
|
|
|
|
|
"leader_id": "leader-team-001",
|
|
|
|
|
"members": [
|
|
|
|
|
{
|
|
|
|
|
"id": "member-team-001-0",
|
|
|
|
|
"joined_at": "2024-11-15T08:30:00Z",
|
|
|
|
|
"role": "leader", // "leader" | "member"
|
|
|
|
|
"status": "accepted", // "pending" | "accepted" | "rejected"
|
|
|
|
|
"team_id": "team-001",
|
|
|
|
|
"user_id": "leader-team-001",
|
|
|
|
|
"user": {
|
|
|
|
|
"id": "leader-team-001",
|
|
|
|
|
"avatar": "https://ui-avatars.com/api/?name=John+Doe", // Optional
|
|
|
|
|
"bio": "Passionate developer with 5+ years experience", // Optional
|
|
|
|
|
"created_at": "2024-10-01T08:30:00Z",
|
|
|
|
|
"email": "john.doe@example.com",
|
|
|
|
|
"fullname": "John Doe",
|
|
|
|
|
"is_active": true,
|
|
|
|
|
"location": "Jakarta",
|
|
|
|
|
"phone_number": "+6281234567890", // Optional
|
|
|
|
|
"skills": ["Frontend Developer", "UI/UX Designer"],
|
|
|
|
|
"updated_at": "2024-11-30T14:22:00Z"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// ... more members
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
// ... more teams
|
|
|
|
|
],
|
|
|
|
|
"pagination": {
|
|
|
|
|
"current_page": 1,
|
|
|
|
|
"total_pages": 15,
|
|
|
|
|
"total_items": 147,
|
|
|
|
|
"items_per_page": 10,
|
|
|
|
|
"has_next": true,
|
|
|
|
|
"has_prev": false
|
|
|
|
|
},
|
|
|
|
|
"filters": {
|
|
|
|
|
"available_cities": ["Jakarta", "Bandung", "Surabaya", "Medan", "Yogyakarta"],
|
|
|
|
|
"available_skills": ["Frontend Developer", "Backend Developer", "Full Stack Developer", "DevOps Engineer", "UI/UX Designer", "Product Manager", "Data Scientist", "Mobile Developer"]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## GET /api/v1/admin/teams/{team_id}
|
|
|
|
|
|
|
|
|
|
### Purpose
|
|
|
|
|
|
|
|
|
|
Retrieve detailed information for a specific team by ID.
|
|
|
|
|
|
|
|
|
|
### Authentication & Authorization
|
|
|
|
|
|
|
|
|
|
- Requires admin (backoffice) scope: e.g. `role=admin`
|
|
|
|
|
|
|
|
|
|
### Path Parameters
|
|
|
|
|
|
|
|
|
|
| Parameter | Type | Required | Description |
|
|
|
|
|
| --------- | ------ | -------- | ----------- |
|
|
|
|
|
| `team_id` | string | Yes | Team ID |
|
|
|
|
|
|
|
|
|
|
### Examples
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
GET /api/v1/admin/teams/team-001
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Response Schema
|
|
|
|
|
|
|
|
|
|
```jsonc
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"id": "team-001",
|
|
|
|
|
"name": "Team Innovators",
|
|
|
|
|
"description": "Building innovative solutions for modern problems",
|
|
|
|
|
"city": "Jakarta",
|
|
|
|
|
"banner": "https://example.com/banners/team1.jpg",
|
|
|
|
|
"logo": "https://example.com/logos/team1.jpg",
|
|
|
|
|
"visibility": "public",
|
|
|
|
|
"member_count": 3,
|
|
|
|
|
"has_submission": true,
|
|
|
|
|
"created_at": "2024-11-15T08:30:00Z",
|
|
|
|
|
"updated_at": "2024-11-30T14:22:00Z",
|
|
|
|
|
"leader_id": "leader-team-001",
|
|
|
|
|
"members": [
|
|
|
|
|
{
|
|
|
|
|
"id": "member-team-001-0",
|
|
|
|
|
"joined_at": "2024-11-15T08:30:00Z",
|
|
|
|
|
"role": "leader",
|
|
|
|
|
"status": "accepted",
|
|
|
|
|
"team_id": "team-001",
|
|
|
|
|
"user_id": "leader-team-001",
|
|
|
|
|
"user": {
|
|
|
|
|
"id": "leader-team-001",
|
|
|
|
|
"avatar": "https://ui-avatars.com/api/?name=John+Doe",
|
|
|
|
|
"bio": "Passionate developer with 5+ years experience",
|
|
|
|
|
"created_at": "2024-10-01T08:30:00Z",
|
|
|
|
|
"email": "john.doe@example.com",
|
|
|
|
|
"fullname": "John Doe",
|
|
|
|
|
"is_active": true,
|
|
|
|
|
"location": "Jakarta",
|
|
|
|
|
"phone_number": "+6281234567890",
|
|
|
|
|
"skills": ["Frontend Developer", "UI/UX Designer"],
|
|
|
|
|
"updated_at": "2024-11-30T14:22:00Z"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// ... all team members
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## POST /api/v1/admin/teams
|
|
|
|
|
|
|
|
|
|
### Purpose
|
|
|
|
|
|
|
|
|
|
Create a new team in the hackathon system.
|
|
|
|
|
|
|
|
|
|
### Authentication & Authorization
|
|
|
|
|
|
|
|
|
|
- Requires admin (backoffice) scope: e.g. `role=admin`
|
|
|
|
|
|
|
|
|
|
### Request Body Schema
|
|
|
|
|
|
|
|
|
|
```jsonc
|
|
|
|
|
{
|
|
|
|
|
"name": "Team New Innovators", // Required, 1-100 chars
|
|
|
|
|
"description": "Building next-gen solutions", // Optional, max 500 chars
|
|
|
|
|
"city": "Jakarta", // Required, from predefined list
|
|
|
|
|
"visibility": "public", // Required, "public" | "private"
|
|
|
|
|
"leader_id": "user-123", // Required, existing user ID
|
|
|
|
|
"banner": "https://example.com/banners/new.jpg", // Optional, URL
|
|
|
|
|
"logo": "https://example.com/logos/new.jpg" // Optional, URL
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Response Schema
|
|
|
|
|
|
|
|
|
|
```jsonc
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"id": "team-new-001",
|
|
|
|
|
"name": "Team New Innovators",
|
|
|
|
|
"description": "Building next-gen solutions",
|
|
|
|
|
"city": "Jakarta",
|
|
|
|
|
"banner": "https://example.com/banners/new.jpg",
|
|
|
|
|
"logo": "https://example.com/logos/new.jpg",
|
|
|
|
|
"visibility": "public",
|
|
|
|
|
"member_count": 1,
|
|
|
|
|
"has_submission": false,
|
|
|
|
|
"created_at": "2024-12-02T10:30:00Z",
|
|
|
|
|
"updated_at": "2024-12-02T10:30:00Z",
|
|
|
|
|
"leader_id": "user-123",
|
|
|
|
|
"members": [
|
|
|
|
|
{
|
|
|
|
|
"id": "member-new-001-0",
|
|
|
|
|
"joined_at": "2024-12-02T10:30:00Z",
|
|
|
|
|
"role": "leader",
|
|
|
|
|
"status": "accepted",
|
|
|
|
|
"team_id": "team-new-001",
|
|
|
|
|
"user_id": "user-123",
|
|
|
|
|
"user": {
|
|
|
|
|
"id": "user-123",
|
|
|
|
|
"fullname": "John Doe",
|
|
|
|
|
"email": "john.doe@example.com",
|
|
|
|
|
"location": "Jakarta",
|
|
|
|
|
"is_active": true,
|
|
|
|
|
"skills": ["Frontend Developer"],
|
|
|
|
|
"created_at": "2024-10-01T08:30:00Z",
|
|
|
|
|
"updated_at": "2024-12-02T10:30:00Z"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## PUT /api/v1/admin/teams/{team_id}
|
|
|
|
|
|
|
|
|
|
### Purpose
|
|
|
|
|
|
|
|
|
|
Update an existing team's information.
|
|
|
|
|
|
|
|
|
|
### Authentication & Authorization
|
|
|
|
|
|
|
|
|
|
- Requires admin (backoffice) scope: e.g. `role=admin`
|
|
|
|
|
|
|
|
|
|
### Path Parameters
|
|
|
|
|
|
|
|
|
|
| Parameter | Type | Required | Description |
|
|
|
|
|
| --------- | ------ | -------- | ----------- |
|
|
|
|
|
| `team_id` | string | Yes | Team ID |
|
|
|
|
|
|
|
|
|
|
### Request Body Schema
|
|
|
|
|
|
|
|
|
|
```jsonc
|
|
|
|
|
{
|
|
|
|
|
"name": "Team Updated Name", // Optional, 1-100 chars
|
|
|
|
|
"description": "Updated description", // Optional, max 500 chars, null to clear
|
|
|
|
|
"city": "Bandung", // Optional, from predefined list
|
|
|
|
|
"visibility": "private", // Optional, "public" | "private"
|
|
|
|
|
"banner": "https://example.com/banners/updated.jpg", // Optional, URL, null to remove
|
|
|
|
|
"logo": "https://example.com/logos/updated.jpg" // Optional, URL, null to remove
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Response Schema
|
|
|
|
|
|
|
|
|
|
Same as GET /api/v1/admin/teams/{team_id} with updated values.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## DELETE /api/v1/admin/teams/{team_id}
|
|
|
|
|
|
|
|
|
|
### Purpose
|
|
|
|
|
|
|
|
|
|
Delete a team from the hackathon system.
|
|
|
|
|
|
|
|
|
|
### Authentication & Authorization
|
|
|
|
|
|
|
|
|
|
- Requires admin (backoffice) scope: e.g. `role=admin`
|
|
|
|
|
|
|
|
|
|
### Path Parameters
|
|
|
|
|
|
|
|
|
|
| Parameter | Type | Required | Description |
|
|
|
|
|
| --------- | ------ | -------- | ----------- |
|
|
|
|
|
| `team_id` | string | Yes | Team ID |
|
|
|
|
|
|
|
|
|
|
### Response Schema
|
|
|
|
|
|
|
|
|
|
```jsonc
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"message": "Team successfully deleted",
|
|
|
|
|
"deleted_team_id": "team-001",
|
|
|
|
|
"deleted_at": "2024-12-02T10:50:00Z"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## GET /api/v1/admin/teams/{team_id}/submission
|
|
|
|
|
|
|
|
|
|
### Purpose
|
|
|
|
|
|
|
|
|
|
Retrieve submission details for a specific team.
|
|
|
|
|
|
|
|
|
|
### Authentication & Authorization
|
|
|
|
|
|
|
|
|
|
- Requires admin (backoffice) scope: e.g. `role=admin`
|
|
|
|
|
|
|
|
|
|
### Path Parameters
|
|
|
|
|
|
|
|
|
|
| Parameter | Type | Required | Description |
|
|
|
|
|
| --------- | ------ | -------- | ----------- |
|
|
|
|
|
| `team_id` | string | Yes | Team ID |
|
|
|
|
|
|
|
|
|
|
### Response Schema
|
|
|
|
|
|
|
|
|
|
```jsonc
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"team_id": "team-001",
|
|
|
|
|
"team_name": "Team Innovators",
|
|
|
|
|
"project_name": "EcoTrack - Smart Waste Management",
|
|
|
|
|
"project_description": "An AI-powered waste management solution that helps cities optimize collection routes and reduce environmental impact.",
|
|
|
|
|
"repository_url": "https://github.com/team-innovators/ecotrack",
|
|
|
|
|
"demo_url": "https://ecotrack-demo.vercel.app",
|
|
|
|
|
"presentation_url": "https://docs.google.com/presentation/d/team-innovators-pitch/edit",
|
|
|
|
|
"submitted_at": "2024-12-01T15:30:00Z",
|
|
|
|
|
"updated_at": "2024-12-01T16:45:00Z"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Common Error Responses
|
|
|
|
|
|
|
|
|
|
### Team Management Endpoints
|
|
|
|
|
|
|
|
|
|
| Status | Code | Message | Notes |
|
|
|
|
|
| ------ | ---------------------- | ------------------------------- | -------------------------- |
|
|
|
|
|
| 400 | `validation_error` | `Invalid request data` | Field validation failures |
|
|
|
|
|
| 401 | `unauthorized` | `Authentication required` | Missing/invalid token |
|
|
|
|
|
| 403 | `forbidden` | `Insufficient permissions` | Lacks required scope |
|
|
|
|
|
| 404 | `team_not_found` | `Team not found` | Invalid team ID |
|
|
|
|
|
| 404 | `submission_not_found` | `Team submission not found` | Team has no submission |
|
|
|
|
|
| 409 | `team_already_exists` | `Team with name already exists` | Duplicate team name |
|
|
|
|
|
| 413 | `payload_too_large` | `Banner/logo file too large` | Image exceeds size limit |
|
|
|
|
|
| 422 | `invalid_city` | `Invalid city specified` | City not in allowed list |
|
|
|
|
|
| 422 | `invalid_leader` | `Invalid leader user ID` | Leader user does not exist |
|
|
|
|
|
| 429 | `rate_limited` | `Too many requests` | Rate limiting |
|
|
|
|
|
| 500 | `internal_error` | `Unexpected server error` | Unhandled exception |
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2025-11-30 18:54:34 +07:00
|
|
|
**Revision History**
|
|
|
|
|
|
|
|
|
|
- v1.0.0 (2025-11-30): Initial contract drafted.
|
2025-12-02 18:11:34 +07:00
|
|
|
- v2.0.0 (2025-12-01): Added user management endpoints with filtering, pagination, CRUD operations, and avatar handling.
|
2025-12-02 23:14:40 +07:00
|
|
|
- v3.0.0 (2025-12-02): Added team management endpoints based on backoffice implementation with team members, submissions, and comprehensive filtering.
|