Comprehensive reference documentation for the TechIndustry REST API and server-side endpoints.
TechIndustry provides a RESTful API designed with a layered architecture (Routes → Controllers → Services → Models) powered by Express 5 and PostgreSQL (Sequelize).
- Base URL:
http://localhost:3000(Local) /https://techindustry.app(Production) - Response Format: JSON (
application/json) / Server-Rendered HTML for UI pages / PDF for certificates - Security Headers: Managed via Helmet (CSP, HSTS, X-Frame-Options)
- Content Encoding: Gzip compression supported
The platform supports a dual authentication mechanism:
-
JWT (JSON Web Tokens):
- Tokens are issued upon successful registration or login via
POST /api/auth/loginorPOST /api/auth/register. - Set automatically in an
httpOnly,secure(in production),sameSite: strictcookie namedtoken. - Can also be passed via the
Authorizationheader:Authorization: Bearer <token>. - Default token validity:
30 days.
- Tokens are issued upon successful registration or login via
-
Google OAuth 2.0 SSO:
- Web flow initialized via
GET /api/auth/google. - Callback handled at
GET /api/auth/google/callbackwith CSRF state validation.
- Web flow initialized via
-
CSRF Protection:
- Double-submit cookie CSRF tokens managed via
csurf. - Client requests mutating state (
POST,PUT,DELETE,PATCH) must supply the_csrfbody field orCSRF-Tokenheader.
- Double-submit cookie CSRF tokens managed via
-
Rate Limiting Quotas:
- Global: 1000 requests / 15 minutes per IP.
- Login: 5 attempts / 15 minutes.
- Registration: 3 attempts / 1 hour.
- Email Verification: 10 requests / 1 hour.
- Password Reset: 3 attempts / 1 hour.
- Quiz Submissions: 10 submissions / 1 minute.
- AI Mentor: 10 messages / 5 minutes cooldown with burst protection (max 5 msgs / 30s).
- Shop Purchases: 10 transactions / 1 minute.
Standard HTTP status codes are returned with a consistent JSON envelope:
{
"message": "Validation failed on input fields",
"errors": [
{
"field": "email",
"message": "Invalid email address"
}
]
}Common status codes:
200 OK: Request succeeded.201 Created: Resource successfully created.400 Bad Request: Validation failure or missing parameters.401 Unauthorized: Missing or invalid authentication token.403 Forbidden: Insufficient permissions or CSRF token mismatch.404 Not Found: Resource not found.429 Too Many Requests: Rate limit exceeded.500 Internal Server Error: Server exception.
POST /api/auth/request-email-verification- Auth: Public
- Body:
{ "email": "user@example.com", "first_name": "John" } - Response
200 OK:{ "message": "Verification code sent to your email", "email": "user@example.com" }
POST /api/auth/verify-email-code- Auth: Public
- Body:
{ "email": "user@example.com", "code": "123456" } - Response
200 OK:{ "message": "Email successfully verified", "verified": true }
POST /api/auth/register- Auth: Public (Rate Limited)
- Content-Type:
multipart/form-dataorapplication/json - Body:
{ "username": "johndoe", "email": "john@example.com", "password": "Password123!", "first_name": "John", "last_name": "Doe", "phone": "+380991234567", "emailVerified": "true" } - Files:
avatar(Optional, max 5MB image) - Response
201 Created:{ "message": "Registration successful", "username": "johndoe", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6..." }
POST /api/auth/login- Auth: Public (Rate Limited)
- Body:
{ "login": "johndoe", "password": "Password123!" } - Response
200 OK:{ "message": "Authentication successful", "username": "johndoe", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6..." }
POST /api/auth/logout- Auth: Public
- Response
200 OK:{ "message": "Logged out successfully", "redirect": "/" }
POST /api/auth/check-availability- Auth: Public
- Body:
{ "username": "johndoe", "email": "john@example.com", "phone": "+380991234567" } - Response
200 OK:{ "available": true }
POST /api/auth/request-reset- Auth: Public (Rate Limited)
- Body:
{ "emailOrPhone": "john@example.com" } - Response
200 OK:{ "message": "Password reset code sent to your email", "codeSent": true }
POST /api/auth/verify-reset-code- Auth: Public
- Body:
{ "emailOrPhone": "john@example.com", "code": "654321" } - Response
200 OK:{ "message": "Code verified successfully", "verified": true }
POST /api/auth/reset-password- Auth: Public
- Body:
{ "emailOrPhone": "john@example.com", "code": "654321", "newPassword": "NewStrongPassword123!" } - Response
200 OK:{ "message": "Password updated successfully", "success": true }
POST /api/auth/update-profile- Auth: Required
- Body:
{ "username": "johndoe_updated", "email": "newjohn@example.com", "first_name": "John", "last_name": "Doe", "about": "Full-stack developer and cloud enthusiast", "github_link": "https://github.com/johndoe" } - Response: Redirect to
/settingsor200 OK.
POST /api/auth/change-password- Auth: Required
- Body:
{ "oldPassword": "CurrentPassword123!", "newPassword": "BrandNewPassword123!" }
POST /api/auth/upload-avatar- Auth: Required
- Content-Type:
multipart/form-data - Files:
avatar(Image file max 5MB)
POST /api/auth/delete-avatar- Auth: Required
POST /api/auth/delete-account- Auth: Required
- Body:
{ "confirmation": "DELETE" } - Response
200 OK:{ "message": "Account deleted successfully", "redirect": "/" }
GET /api/courses- Auth: Public
- Response
200 OK: Returns catalog of courses with module counts, hours, and learner progress.
GET /api/courses/:slug- Auth: Public
- Parameters:
slug(e.g.,python-for-data,react-next,csharp-dotnet) - Response
200 OK: Detailed course structure including modules and lesson metadata.
GET /api/courses/lessons/:lessonId- Auth: Public
- Parameters:
lessonId(Integer ID) - Response
200 OK:{ "id": 15, "title": "Asynchronous Programming with async/await", "content": "# Markdown formatted lesson content...", "module_id": 4, "order": 16 }
GET /api/progress- Auth: Required
- Response
200 OK:[ { "id": 1, "user_id": 42, "course_id": 2, "status": "in_progress", "completed_lessons": [1, 2, 3, 4], "completed_quizzes": ["react-next:01-basics"], "started_at": "2026-03-01T10:00:00.000Z", "last_accessed": "2026-03-16T14:30:00.000Z" } ]
POST /api/progress/start- Auth: Required
- Body:
{ "courseSlug": "csharp-dotnet" } - Response
200 OK:{ "message": "Course started", "progress": { "user_id": 42, "course_id": 1, "status": "in_progress", "completed_lessons": [], "completed_quizzes": [] } }
POST /api/progress/lesson- Auth: Required
- Body:
{ "lessonId": 7, "completed": true } - Response
200 OK:{ "message": "Progress updated", "progress": { "completed_lessons": [1, 2, 3, 7], "status": "in_progress" }, "rewards": { "xpGained": 50, "coinsGained": 10, "newCoinsBalance": 260, "leveledUp": false, "newLevel": 4, "newBadges": [] } }
POST /quiz/:slug/:moduleId/submit- Auth: Required (Rate Limited)
- Parameters:
slug: Course slug (e.g.react-next)moduleId: Module ID (e.g.01-react-fundamentals)
- Body:
{ "answers": { "q1": "1", "q2": ["0", "2"], "q3": "const [state, setState] = useState(0);" } } - Response
200 OK:{ "passed": true, "percent": 100, "correctCount": 5, "totalQuestions": 5, "message": "Congratulations! Quiz passed successfully.", "gamification": { "xpGained": 150, "coinsGained": 30, "newCoinsBalance": 290, "leveledUp": true, "newLevel": 5, "newBadges": [ { "id": "perfect_quiz", "name": "Perfectionist", "description": "Passed quiz with 100% score" } ] }, "isRepeat": false }
GET /api/certificates/check/:courseId- Auth: Required
- Parameters:
courseId(Integer ID) - Response
200 OK:{ "available": true, "status": "completed", "completedLessons": 20, "totalLessons": 20, "progressPercent": 100 }
GET /api/certificates/download/:courseId- Auth: Required
- Parameters:
courseId(Integer ID) - Response
200 OK:Content-Type: application/pdfwithContent-Disposition: inline; filename=certificate-{courseId}.pdf.
GET /api/ai/status- Auth: Public / Session-based
- Response
200 OK:{ "count": 3, "limit": 10, "resetTime": null }
POST /api/ai/chat- Auth: Public / Session-based (Strict Anti-Spam & Rate Limits)
- Body:
{ "message": "Explain how async/await works in Node.js", "history": [ { "role": "user", "parts": [{ "text": "Hello!" }] }, { "role": "model", "parts": [{ "text": "Hello! How can I help you with IT or the TechIndustry platform today?" }] } ] } - Response
200 OK:{ "response": "async/await is syntactic sugar built on top of JavaScript Promises...", "status": { "count": 4, "limit": 10, "resetTime": null } }
GET /api/shop/data- Auth: Required
- Response
200 OK:{ "success": true, "userCoins": 450, "items": [ { "id": 1, "title": "Neon Cyberpunk Frame", "item_type": "avatar_frame", "price": 150, "is_owned": true, "is_equipped": true } ], "purchases": [] }
POST /api/shop/purchase- Auth: Required (Rate Limited)
- Body:
{ "itemId": 1 } - Response
200 OK:{ "success": true, "message": "Item purchased successfully!", "newBalance": 300 }
POST /api/shop/equip- Auth: Required
- Body:
{ "itemId": 1 } - Response
200 OK:{ "success": true, "message": "Item equipped!" }
POST /api/shop/unequip- Auth: Required
- Body:
{ "itemId": 1 } - Response
200 OK:{ "success": true, "message": "Item unequipped!" }
GET /api/roadmaps/:id- Auth: Public
- Parameters:
id(e.g.frontend,backend,devops,full-stack) - Response
200 OK: Structured tree of roadmap nodes, topics, and external learning links.