- Development:
http://localhost:7069 - Production:
https://api.buildtrack.com(to be configured)
All endpoints (except /api/auth/login) require JWT Bearer token in the Authorization header:
Authorization: Bearer <your_jwt_token>
{
"sub": "user-id-guid",
"email": "user@example.com",
"role": ["admin", "project_manager"],
"iat": 1234567890,
"exp": 1234571490
}- Access tokens expire in 60 minutes (configurable)
- Use refresh token to get new access token
- Refresh tokens do not expire in current implementation
Endpoint: POST /api/auth/login
Request Headers:
Content-Type: application/json
Request Body:
{
"email": "admin@buildtrack.local",
"password": "Admin123!@#"
}Success Response (200):
{
"success": true,
"message": "Login successful",
"data": {
"userId": "550e8400-e29b-41d4-a716-446655440000",
"email": "admin@buildtrack.local",
"fullName": "Administrator",
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "base64-encoded-random-token",
"expiresIn": 3600,
"roles": ["super_admin"]
}
}Error Response (401):
{
"success": false,
"message": "Invalid email or password"
}Endpoint: POST /api/auth/logout
Authentication: Required (Bearer Token)
Response (200):
{
"success": true,
"message": "Logout successful"
}Endpoint: POST /api/auth/refresh
Request Body:
{
"refreshToken": "base64-encoded-token"
}Success Response (200):
{
"success": true,
"data": {
"accessToken": "new-jwt-token",
"refreshToken": "new-refresh-token",
"expiresIn": 3600
}
}Endpoint: GET /api/users/me
Authentication: Required
Response (200):
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "admin@buildtrack.local",
"fullName": "Administrator",
"username": "admin",
"phone": "+1234567890",
"address": "123 Main St",
"avatarUrl": "https://...",
"isActive": true,
"smsOptIn": false,
"emailOptIn": true,
"createdAt": "2023-01-15T10:30:00Z",
"updatedAt": "2023-01-15T10:30:00Z",
"roles": ["super_admin"]
}
}Endpoint: GET /api/users/{id}
Authentication: Required
Parameters:
id(path): User ID in UUID format
Response (200): Same as Get Current User
Endpoint: GET /api/users?page=1&pageSize=10
Authentication: Required
Query Parameters:
page(int, default=1): Page numberpageSize(int, default=10): Items per page
Response (200):
{
"success": true,
"data": {
"data": [
{ "id": "...", "email": "user1@buildtrack.local", ... },
{ "id": "...", "email": "user2@buildtrack.local", ... }
],
"total": 25,
"page": 1,
"pageSize": 10,
"totalPages": 3
}
}Endpoint: PUT /api/users/{id}
Authentication: Required
Request Body (all fields optional):
{
"fullName": "New Name",
"username": "newusername",
"phone": "+9876543210",
"address": "456 Oak Ave",
"avatarUrl": "https://...",
"smsOptIn": true,
"emailOptIn": false,
"isActive": true
}Response (200):
{
"success": true,
"message": "User updated successfully",
"data": { ... user data ... }
}Endpoint: POST /api/users/{id}/change-password
Authentication: Required (only user can change own password)
Request Body:
{
"currentPassword": "OldPassword123!",
"newPassword": "NewPassword456!"
}Response (200):
{
"success": true,
"message": "Password changed successfully"
}Endpoint: POST /api/users/{id}/roles
Authentication: Required (admin/super_admin only)
Request Body:
{
"role": "project_manager"
}Response (200):
{
"success": true,
"message": "Role assigned successfully"
}Endpoint: GET /api/projects/{id}
Authentication: Required
Response (200):
{
"success": true,
"data": {
"id": "660e8400-e29b-41d4-a716-446655440000",
"name": "Downtown Office Building",
"code": "PRJ-2024-001",
"location": "Downtown District",
"description": "Construction of 50-story office building",
"status": "active",
"startDate": "2023-01-15T00:00:00Z",
"endDate": "2025-12-31T00:00:00Z",
"projectManagerId": "550e8400-e29b-41d4-a716-446655440000",
"projectManagerName": "John Doe",
"estimatedCost": 50000000.00,
"isHidden": false,
"createdAt": "2023-01-15T10:30:00Z",
"updatedAt": "2024-01-15T14:20:00Z"
}
}Endpoint: GET /api/projects?page=1&pageSize=10&includeHidden=false
Authentication: Required
Query Parameters:
page(int, default=1)pageSize(int, default=10)includeHidden(bool, default=false)
Response (200):
{
"success": true,
"data": {
"data": [ ... projects array ... ],
"total": 15,
"page": 1,
"pageSize": 10,
"totalPages": 2
}
}Endpoint: POST /api/projects
Authentication: Required
Request Body:
{
"name": "New Commercial Complex",
"code": "PRJ-2024-002",
"location": "Business District",
"description": "Mixed-use commercial development",
"startDate": "2024-02-01T00:00:00Z",
"endDate": "2026-06-30T00:00:00Z",
"estimatedCost": 75000000.00,
"initialMemberIds": [
"550e8400-e29b-41d4-a716-446655440001",
"550e8400-e29b-41d4-a716-446655440002"
]
}Response (201):
{
"success": true,
"message": "Project created successfully",
"data": { ... project data ... }
}Endpoint: PUT /api/projects/{id}
Authentication: Required
Request Body (all fields optional):
{
"name": "Updated Project Name",
"status": "on_hold",
"estimatedCost": 80000000.00,
"isHidden": false
}Response (200):
{
"success": true,
"message": "Project updated successfully",
"data": { ... project data ... }
}Endpoint: DELETE /api/projects/{id}
Authentication: Required
Response (200):
{
"success": true,
"message": "Project deleted successfully"
}Endpoint: GET /api/orders/{id}
Authentication: Required
Response (200):
{
"success": true,
"data": {
"id": "770e8400-e29b-41d4-a716-446655440000",
"projectId": "660e8400-e29b-41d4-a716-446655440000",
"projectName": "Downtown Office Building",
"orderNumber": "ORD-20240115153000",
"orderType": "Initial Equipment",
"status": "draft",
"supplierName": "ABC Construction Supplies",
"supplierContact": "contact@abc.com",
"totalAmount": 250000.00,
"notes": "First order for project kickoff",
"approvedAt": null,
"deliveredAt": null,
"expectedDeliveryDate": "2024-02-15T00:00:00Z",
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z",
"createdByName": "John Manager",
"lineItems": [
{
"id": "880e8400-e29b-41d4-a716-446655440000",
"skuId": "910e8400-e29b-41d4-a716-446655440000",
"skuCode": "CEMENT-50KG",
"skuName": "Portland Cement 50kg Bag",
"quantity": 500,
"unitPrice": 12.50,
"unit": "bag"
}
]
}
}Endpoint: GET /api/orders/project/{projectId}?status=draft&page=1&pageSize=10
Authentication: Required
Query Parameters:
status(string, optional): Filter by status (draft, approved, ordered, delivered, etc.)page(int, default=1)pageSize(int, default=10)
Response (200):
{
"success": true,
"data": {
"data": [ ... orders array ... ],
"total": 5,
"page": 1,
"pageSize": 10,
"totalPages": 1
}
}Endpoint: POST /api/orders
Authentication: Required
Request Body:
{
"projectId": "660e8400-e29b-41d4-a716-446655440000",
"orderType": "Materials",
"supplierName": "ABC Supplies",
"supplierContact": "contact@abc.com",
"totalAmount": 150000.00,
"notes": "Building materials for Phase 1",
"expectedDeliveryDate": "2024-02-10T00:00:00Z",
"lineItems": [
{
"skuId": "910e8400-e29b-41d4-a716-446655440000",
"quantity": 500,
"unitPrice": 12.50
},
{
"skuId": "920e8400-e29b-41d4-a716-446655440000",
"quantity": 1000,
"unitPrice": 8.75
}
]
}Response (201):
{
"success": true,
"message": "Order created successfully",
"data": { ... order data ... }
}Endpoint: PUT /api/orders/{id}
Authentication: Required
Request Body (all fields optional):
{
"supplierName": "Updated Supplier",
"totalAmount": 175000.00,
"notes": "Updated notes"
}Response (200):
{
"success": true,
"message": "Order updated successfully",
"data": { ... order data ... }
}Endpoint: POST /api/orders/{id}/approve
Authentication: Required (approver roles only)
Request Body:
{
"finalAmount": 165000.00,
"notes": "Approved for Phase 1"
}Response (200):
{
"success": true,
"message": "Order approved successfully"
}Endpoint: POST /api/orders/{id}/reject
Authentication: Required (approver roles only)
Request Body:
{
"rejectionReason": "Supplier pricing too high, requesting new quotation"
}Response (200):
{
"success": true,
"message": "Order rejected successfully"
}Endpoint: DELETE /api/orders/{id}
Authentication: Required
Response (200):
{
"success": true,
"message": "Order deleted successfully"
}{
"success": false,
"message": "Error description",
"errors": {
"field1": ["Error for field1"],
"field2": ["Error for field2"]
}
}| Status | Message | Reason |
|---|---|---|
| 400 | Bad Request | Invalid input parameters |
| 401 | Unauthorized | Missing or invalid JWT token |
| 403 | Forbidden | User doesn't have permission |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | Resource already exists (duplicate) |
| 422 | Unprocessable Entity | Validation error on field |
| 500 | Internal Server Error | Unexpected server error |
All list endpoints return:
{
"success": true,
"data": {
"data": [ ... items ... ],
"total": 100,
"page": 1,
"pageSize": 10,
"totalPages": 10
}
}Calculation: totalPages = (total + pageSize - 1) / pageSize
super_admin: Full system accessadmin: Administrative accessoffice_admin: Office managementwarehouse_admin: Warehouse/logisticsproject_manager: Project managementprocurement: Procurement specialiststorekeeper: Inventory managementsite_lead: Site supervisionproject_engineer: Engineeringchecker: Quality checkingdriver: Logistics driverreceiver: Goods receivingviewer: Read-only accessapprover: Order approvaltracking_driver: Tracking driver
| Endpoint | Required Roles | Notes |
|---|---|---|
| POST /api/auth/login | None | Public |
| GET /api/users/me | Any authenticated | Self-access |
| PUT /api/users/{id} | Any authenticated | Self-update only |
| GET /api/users | admin, super_admin | Admin only |
| POST /api/users/{id}/roles | admin, super_admin | Assign roles |
| GET /api/projects | Any authenticated | List projects user can access |
| POST /api/projects | Any authenticated | Create new project |
| POST /api/orders | Roles that can create orders | Project-scoped |
| POST /api/orders/{id}/approve | approver, admin | Approval required |
Currently not implemented. To be added:
- 100 requests per minute per user
- 1000 requests per minute per IP
Current version: v1
Future versions will be: /api/v2/...
Backward compatibility maintained for 12 months after new version release.
curl -X POST http://localhost:7069/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@buildtrack.local","password":"Admin123!@#"}'curl -X GET http://localhost:7069/api/users/me \
-H "Authorization: Bearer YOUR_JWT_TOKEN"curl -X POST http://localhost:7069/api/projects \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"Test Project","code":"TST-001",...}'Navigate to: http://localhost:7069/swagger
- Click "Authorize" button
- Paste JWT token from login response
- Use "Try it out" on any endpoint
Expected response times (under normal load):
- GET requests: < 100ms
- POST requests: < 200ms
- Database queries with pagination: < 50ms
- Complex joined queries: < 150ms
For API issues:
- Check error message in response
- Verify JWT token hasn't expired
- Check Swagger documentation
- Review backend logs:
logs/application.log