Version: 1.0.0
Base API: https://devpulse-api-delta.vercel.app
Project Repository: https://github.com/AyanSujon/DevPulse
Developer: Ayan Sujon
Website: https://www.ayansujon.com
LinkedIn: https://www.linkedin.com/in/ayansujon/
DevPulse is a RESTful backend API built for managing software issues in a collaborative development environment. It provides a structured system for reporting, tracking, updating, and resolving bugs and feature requests with role-based access control and secure authentication.
DevPulse is designed to act as a lightweight issue tracking system for development teams. It allows contributors to report issues and maintainers to manage the full lifecycle of those issues, ensuring smooth collaboration between users and project maintainers.
- JWT-based authentication system
- Secure user registration and login
- Role-based access control:
- Contributor → create and update own issues (limited access)
- Maintainer → full access (update & delete any issue)
- Base URL:
http://localhost:{PORT}/api - Port: Configured via
PORTenvironment variable - CORS Origin: Configured via
CORS_ORIGINenvironment variable - Content-Type:
application/json
- Runtime: Node.js
- Framework: Express.js
- Language: TypeScript
- Database: PostgreSQL, NeonDB
- Authentication: JSON Web Token (JWT)
- Password Security: bcrypt
- Architecture: Modular / Layered Architecture (Controller–Service–Route)
- Deployment: Vercel (Serverless Functions)
The API uses JWT (JSON Web Token) for authentication. Protected endpoints require a valid JWT token in the Authorization header.
Authorization: <JWT_TOKEN>
The JWT token contains the following information:
{
"id": 1,
"name": "John Doe",
"email": "user@example.com",
"role": "contributor",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}- Expires In: 1 day
contributor- Can create and update their own open issuesmaintainer- Can manage all issues (update, delete)
GET /
Description: Returns the health status and information about the DevPulse server.
Request:
curl http://localhost:3000/Response (200 OK):
{
"message": "DevPulse Server is listening",
"projectName": "DevPulse",
"version": "1.0.0",
"developer": "Ayan Sujon",
"website": "https://www.ayansujon.com",
"Linkedin": "https://www.linkedin.com/in/ayansujon/"
}POST /api/auth/signup
Description: Register a new user account.
Request Body:
{
"name": "John Doe",
"email": "john@example.com",
"password": "securePassword123",
"role": "contributor"
}Request Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | User's full name |
| string | Yes | User's email address | |
| password | string | Yes | User's password (will be hashed with bcrypt) |
| role | string | No | User role: contributor or maintainer |
Response (201 Created):
{
"statusCode": 201,
"success": true,
"message": "User registered successfully",
"data": {
"id": 1,
"name": "John Doe",
"email": "john@example.com",
"role": "contributor",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
}Error Response (500 Internal Server Error):
{
"statusCode": 500,
"success": false,
"message": "Error message describing the issue",
"error": {},
"data": null
}POST /api/auth/login
Description: Login to the system and receive a JWT token.
Request Body:
{
"email": "john@example.com",
"password": "securePassword123"
}Request Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| string | Yes | User's email address | |
| password | string | Yes | User's password |
Response (200 OK):
{
"statusCode": 200,
"success": true,
"message": "Login successful",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": 1,
"name": "John Doe",
"email": "john@example.com",
"role": "contributor",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
}
}Error Response (500 Internal Server Error):
{
"statusCode": 500,
"success": false,
"message": "Invalid Credentials: User not found",
"error": {},
"data": null
}POST /api/issues
Description: Create a new issue. Requires authentication with contributor or maintainer role.
Authentication: Required (JWT Token)
Request Body:
{
"title": "Login button not working",
"description": "The login button on the homepage is not responding to clicks",
"type": "bug"
}Request Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| title | string | Yes | Issue title |
| description | string | Yes | Detailed description of the issue |
| type | string | Yes | Issue type: bug or feature_request |
Response (201 Created):
{
"statusCode": 201,
"success": true,
"message": "Issue created successfully",
"data": {
"id": 1,
"title": "Login button not working",
"description": "The login button on the homepage is not responding to clicks",
"type": "bug",
"status": "open",
"reporter_id": 1,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
}Error Responses:
- 401 Unauthorized - Missing or invalid JWT token:
{
"statusCode": 401,
"success": false,
"message": "Unauthorized access!!"
}- 403 Forbidden - User doesn't have required role:
{
"statusCode": 403,
"success": false,
"message": "Forbidden access!!"
}GET /api/issues
Description: Retrieve all issues with optional filtering and sorting. No authentication required.
Query Parameters:
| Parameter | Type | Required | Description | Default |
|---|---|---|---|---|
| sort | string | No | Sort order: newest or oldest |
newest |
| type | string | No | Filter by type: bug or feature_request |
N/A |
| status | string | No | Filter by status: open, in_progress, or resolved |
N/A |
Example Requests:
# Get all issues sorted by newest (default)
GET /api/issues
# Get all bugs
GET /api/issues?type=bug
# Get all open issues sorted by oldest
GET /api/issues?sort=oldest&status=open
# Get all feature requests with open status
GET /api/issues?type=feature_request&status=open
# Get all in_progress issues sorted by oldest
GET /api/issues?sort=oldest&status=in_progressResponse (200 OK):
{
"statusCode": 200,
"success": true,
"message": "Issues fetched successfully",
"data": [
{
"id": 1,
"title": "Login button not working",
"description": "The login button on the homepage is not responding to clicks",
"type": "bug",
"status": "open",
"reporter": {
"id": 1,
"name": "John Doe",
"role": "contributor"
},
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
},
{
"id": 2,
"title": "Add dark mode support",
"description": "Users are requesting a dark mode option for better usability",
"type": "feature_request",
"status": "in_progress",
"reporter": {
"id": 2,
"name": "Jane Smith",
"role": "maintainer"
},
"created_at": "2024-01-14T09:15:00Z",
"updated_at": "2024-01-15T14:22:00Z"
}
]
}Empty Response (200 OK):
{
"statusCode": 200,
"success": true,
"message": "Issues fetched successfully",
"data": []
}GET /api/issues/:id
Description: Retrieve a single issue by its ID. No authentication required.
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | number | Yes | Issue ID |
Example Request:
GET /api/issues/1Response (200 OK):
{
"statusCode": 200,
"success": true,
"message": "Issue retrieved successfully",
"data": {
"id": 1,
"title": "Login button not working",
"description": "The login button on the homepage is not responding to clicks",
"type": "bug",
"status": "open",
"reporter": {
"id": 1,
"name": "John Doe",
"role": "contributor"
},
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
}Error Response (404 Not Found):
{
"statusCode": 404,
"success": false,
"message": "Issue not found",
"data": null
}PATCH /api/issues/:id
Description: Update an existing issue. Requires authentication with contributor or maintainer role.
Authentication: Required (JWT Token)
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | number | Yes | Issue ID |
Request Body: (all fields are optional)
{
"title": "Updated issue title",
"description": "Updated description",
"type": "feature_request",
"status": "in_progress"
}Request Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| title | string | No | Updated issue title |
| description | string | No | Updated description |
| type | string | No | Updated type: bug or feature_request |
| status | string | No | Updated status: open, in_progress, or resolved |
Access Control Rules:
- Maintainer Role: Can update any issue
- Contributor Role: Can only update their own issues AND only if the status is
open
Response (200 OK):
{
"statusCode": 200,
"success": true,
"message": "Issue updated successfully",
"data": {
"id": 1,
"title": "Updated issue title",
"description": "Updated description",
"type": "feature_request",
"status": "in_progress",
"reporter_id": 1,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T15:45:00Z"
}
}Error Responses:
- 401 Unauthorized - Missing or invalid JWT token:
{
"statusCode": 401,
"success": false,
"message": "Unauthorized access!!"
}- 403 Forbidden - User lacks permission (not owner or not open status):
{
"statusCode": 403,
"success": false,
"message": "Contributors can only update their own open issues"
}- 404 Not Found - Issue doesn't exist:
{
"statusCode": 404,
"success": false,
"message": "Issue not found",
"data": null
}DELETE /api/issues/:id
Description: Delete an existing issue. Requires authentication with maintainer role only.
Authentication: Required (JWT Token - maintainer only)
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | number | Yes | Issue ID |
Example Request:
DELETE /api/issues/1
Authorization: <JWT_TOKEN>Response (200 OK):
{
"statusCode": 200,
"success": true,
"message": "Issue deleted successfully",
"data": {}
}Error Responses:
- 401 Unauthorized - Missing or invalid JWT token:
{
"statusCode": 401,
"success": false,
"message": "Unauthorized access!!"
}- 403 Forbidden - User doesn't have
maintainerrole:
{
"statusCode": 403,
"success": false,
"message": "Forbidden access!!"
}- 404 Not Found - Issue doesn't exist:
{
"statusCode": 404,
"success": false,
"message": "Issue not found",
"data": null
}The API uses HTTP status codes to indicate the success or failure of an API request.
| Code | Status | Description |
|---|---|---|
| 200 | OK | Request succeeded |
| 201 | Created | Resource successfully created |
| 400 | Bad Request | Invalid request parameters or malformed request |
| 401 | Unauthorized | Missing or invalid authentication token |
| 403 | Forbidden | Authenticated but lacks required permissions |
| 404 | Not Found | Resource not found |
| 500 | Server Error | Internal server error |
All errors follow this standard format:
{
"statusCode": 500,
"success": false,
"message": "Error description",
"error": {},
"data": null
}{
"statusCode": 200,
"success": true,
"message": "Success message",
"data": {}
}{
"id": 1,
"title": "string",
"description": "string",
"type": "bug" | "feature_request",
"status": "open" | "in_progress" | "resolved",
"reporter": {
"id": 1,
"name": "string",
"role": "contributor" | "maintainer"
},
"created_at": "ISO 8601 timestamp",
"updated_at": "ISO 8601 timestamp"
}{
"id": 1,
"name": "string",
"email": "string",
"role": "contributor" | "maintainer",
"created_at": "ISO 8601 timestamp",
"updated_at": "ISO 8601 timestamp"
}- Register -
POST /api/auth/signupwith user details - Login -
POST /api/auth/loginto get JWT token - Use Token - Include token in
Authorizationheader for protected endpoints
- Create -
POST /api/issues(requires auth: contributor/maintainer) - List -
GET /api/issues(public, supports filtering/sorting) - View -
GET /api/issues/:id(public) - Update -
PATCH /api/issues/:id(requires auth, role-based access control) - Delete -
DELETE /api/issues/:id(requires auth: maintainer only)
# 1. Register a user
curl -X POST http://localhost:3000/api/auth/signup \
-H "Content-Type: application/json" \
-d '{
"name": "John Doe",
"email": "john@example.com",
"password": "password123",
"role": "contributor"
}'
# 2. Login to get token
curl -X POST http://localhost:3000/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "john@example.com",
"password": "password123"
}'
# Response contains token - save it for next requests
# TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
# 3. Create an issue (requires token)
curl -X POST http://localhost:3000/api/issues \
-H "Content-Type: application/json" \
-H "Authorization: $TOKEN" \
-d '{
"title": "Login button not working",
"description": "The login button is unresponsive",
"type": "bug"
}'
# 4. Get all open bugs
curl http://localhost:3000/api/issues?type=bug&status=open
# 5. Get a specific issue
curl http://localhost:3000/api/issues/1
# 6. Update an issue (requires token)
curl -X PATCH http://localhost:3000/api/issues/1 \
-H "Content-Type: application/json" \
-H "Authorization: $TOKEN" \
-d '{
"status": "in_progress"
}'
# 7. Delete an issue (requires maintainer token)
curl -X DELETE http://localhost:3000/api/issues/1 \
-H "Authorization: $TOKEN"git clone https://github.com/AyanSujon/DevPulse.git
cd DevPulsenpm installCreate a .env file in the root directory:
PORT=3000
DATABASE_URL=your_database_url
JWT_SECRET=your_secret_key
CORS_ORIGIN=*npm run devnpm run buildnpm starthttps://devpulse-api-delta.vercel.app
DevPulse is a secure, scalable issue tracking REST API that enables structured collaboration between developers and maintainers using JWT authentication, role-based permissions, and a clean modular architecture.
- All timestamps are in ISO 8601 format
- Password is automatically hashed using bcrypt before storage
- JWT tokens expire after 1 day
- CORS is configured and enabled for specified origins
- The API validates all input and returns descriptive error messages