Ankur Halder Portfolio API Documentation
Version 1.4.0
Generated on: Sat Aug 30 05:46:01 UTC 2025
Welcome to the developer documentation for the Ankur Halder Portfolio API. This document will provide all the information you need to interact with the API.
Getting Started
This guide will walk you through the basics of using the API, including authentication and making your first request.
Base URL
All API endpoints are relative to the following base URL:
/api/v1Authentication
Most endpoints in this API are protected and require authentication. The API uses **JSON Web Tokens (JWT)** for authentication. To authenticate, you need to follow these steps: 1. **Log in:** Send a `POST` request to the `/users/login` endpoint with your email and password. 2. **Receive Token:** If your credentials are correct, the API will return a JWT in the response body. 3. **Send Token:** For all subsequent requests to protected endpoints, you must include this token in the `Authorization` header with the `Bearer` scheme.
Authorization: Bearer <YOUR_JWT_TOKEN>Authentication API
This section covers endpoints related to user authentication, including signup, login, logout, and password management.
User Signup
/users/signupRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
name | String | Yes | The user's full name. |
email | String | Yes | The user's email address. |
password | String | Yes | The user's password. |
passwordConfirm | String | Yes | Confirmation of the password. |
Sample Request
curl -X POST '/users/signup' \
-H 'Content-Type: application/json' \
-d '{
"name": "string",
"email": "string",
"password": "string",
"passwordConfirm": "string"
}'Success Response (201 Created)
{
"status": "success",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"data": {
"user": {
"role": "user",
"active": true,
"_id": "60d5f2f5c7b3c3b3c3b3c3b3",
"name": "Ankur Halder",
"email": "test@example.com",
"createdAt": "2023-01-01T00:00:00.000Z",
"updatedAt": "2023-01-01T00:00:00.000Z"
}
}
}Error Response (400 Bad Request (Validation Error))
{
"status": "fail",
"message": "Invalid input: Password confirmation does not match password (in body for parameter 'passwordConfirm')."
}Error Response (400 Bad Request (Duplicate Email))
If the email address is already registered.
{
"status": "fail",
"message": "This email address is already in use."
}User Login
/users/loginRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
email | String | Yes | The user's email address. |
password | String | Yes | The user's password. |
Sample Request
curl -X POST '/users/login' \
-H 'Content-Type: application/json' \
-d '{
"email": "string",
"password": "string"
}'Success Response (200 OK)
{
"status": "success",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"data": {
"user": {
"_id": "60d5f2f5c7b3c3b3c3b3c3b3",
"name": "Ankur Halder",
"email": "test@example.com",
"role": "user"
}
}
}Error Response (401 Unauthorized)
{
"status": "fail",
"message": "Incorrect email or password"
}User Logout
/users/logoutSample Request
curl -X POST '/users/logout' \
-H 'Authorization: Bearer <YOUR_JWT_TOKEN>'Success Response (200 OK)
{
"status": "success"
}Forgot Password
/users/forgotPasswordRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
email | String | Yes | The user's email address. |
Sample Request
curl -X POST '/users/forgotPassword' \
-H 'Content-Type: application/json' \
-d '{
"email": "string"
}'Success Response (200 OK)
This endpoint always returns a success message to prevent user enumeration, even if the email does not exist.
{
"status": "success",
"message": "If an account with that email exists, a password reset link has been sent."
}Reset Password
/users/resetPassword/:tokenRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
password | String | Yes | The new password. |
passwordConfirm | String | Yes | Confirmation of the new password. |
Sample Request
curl -X PATCH '/users/resetPassword/:token' \
-H 'Content-Type: application/json' \
-d '{
"password": "string",
"passwordConfirm": "string"
}'Success Response (200 OK)
Returns a new JWT and the user object.
{
"status": "success",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"data": {
"user": { ... }
}
}Error Response (400 Bad Request)
{
"status": "fail",
"message": "Token is invalid or has expired."
}User Management API
This section describes the endpoints for managing the profile of the currently authenticated user. All endpoints in this section require authentication.
Get My Profile
/users/meSample Request
curl -X GET '/users/me' \
-H 'Authorization: Bearer <YOUR_JWT_TOKEN>'Success Response (200 OK)
{
"status": "success",
"data": {
"user": {
"role": "user",
"active": true,
"_id": "60d5f2f5c7b3c3b3c3b3c3b3",
"name": "Ankur Halder",
"email": "test@example.com",
"createdAt": "2023-01-01T00:00:00.000Z",
"updatedAt": "2023-01-01T00:00:00.000Z"
}
}
}Error Response (401 Unauthorized)
If the token is missing, invalid, or expired.
{
"status": "fail",
"message": "You are not logged in! Please log in to get access."
}Update My Profile
/users/updateMeUpdates the name and/or email for the currently logged-in user. **Note:** You cannot update your password using this endpoint. Please use the `/users/updateMyPassword` endpoint instead.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | String | No | The user's new name. |
email | String | No | The user's new email address. |
Sample Request
curl -X PATCH '/users/updateMe' \
-H 'Authorization: Bearer <YOUR_JWT_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{
"name": "string",
"email": "string"
}'Success Response (200 OK)
{
"status": "success",
"data": {
"user": {
"_id": "60d5f2f5c7b3c3b3c3b3c3b3",
"name": "Ankur H.",
"email": "ankur.h@example.com",
...
}
}
}Error Response (400 Bad Request)
If you try to update the password via this route.
{
"status": "fail",
"message": "This route is not for password updates. Please use /updateMyPassword."
}Deactivate My Account
/users/deleteMeDeactivates the account of the currently logged-in user. This is a soft delete.
Sample Request
curl -X DELETE '/users/deleteMe' \
-H 'Authorization: Bearer <YOUR_JWT_TOKEN>'Success Response (204 No Content)
The server will respond with a `204 No Content` status and an empty body.
Update My Password
/users/updateMyPasswordUpdates the password for the currently logged-in user.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
passwordCurrent | String | Yes | The user's current password. |
password | String | Yes | The new password. |
passwordConfirm | String | Yes | Confirmation of the new password. |
Sample Request
curl -X PATCH '/users/updateMyPassword' \
-H 'Authorization: Bearer <YOUR_JWT_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{
"passwordCurrent": "string",
"password": "string",
"passwordConfirm": "string"
}'Success Response (200 OK)
Returns a new JWT and the user object.
{
"status": "success",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"data": {
"user": { ... }
}
}Error Response (401 Unauthorized)
If the `passwordCurrent` is incorrect.
{
"status": "fail",
"message": "Your current password is incorrect."
}Email API
This section covers endpoints related to email functionality, such as the contact form.
Submit Contact Form
/email/contactSubmits the main contact form, potentially with file attachments. This endpoint performs AI analysis on the message content and sends confirmation emails.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | String | Yes | The sender's name. |
email | String | Yes | The sender's email address. |
subject | String | Yes | The subject of the message. |
message | String | Yes | The body of the message. |
attachments | File[] | No | File attachments for the message. |
honeypot | String | No | A hidden field used for spam detection. If this field is filled out, the submission is treated as spam and silently discarded. |
Sample Request
curl -X POST '/email/contact' \
-H 'Content-Type: application/json' \
-d '{
"name": "string",
"email": "string",
"subject": "string",
"message": "string",
"attachments": "value",
"honeypot": "string"
}'Success Response (200 OK)
{
"success": true,
"message": "Message and file(s) received (Ref: AH-1672531200000-abcdef12). Thank you!",
"referenceId": "AH-1672531200000-abcdef12"
}Error Response (400 Bad Request (Validation Error))
{
"status": "fail",
"message": "Invalid input: Message is required (in body for parameter 'message')."
}Error Response (400 Bad Request (Invalid File Type))
{
"status": "fail",
"message": "File type image/gif not allowed. Allowed types: image/jpeg, image/png, ..."
}Error Response (503 Service Unavailable)
If the email service is not configured on the server.
{
"status": "error",
"message": "Email service is not configured. Cannot process request."
}Generate Draft Reply (Admin)
/email/:id/draft-replyGenerates an AI-powered draft reply for a previously received email.
Sample Request
curl -X POST '/email/:id/draft-reply' \
-H 'Authorization: Bearer <YOUR_JWT_TOKEN>'Success Response (200 OK)
{
"status": "success",
"data": {
"draftReply": "Dear John Doe,\n\nThank you for your inquiry about the project...",
"usedModel": "gemini-1.5-flash"
}
}Error Response (404 Not Found)
{
"status": "fail",
"message": "No email submission found with that ID."
}Endorsement API
This section covers endpoints for fetching and submitting skill and project endorsements.
Get All Endorsements
/endorsementsRetrieves a map of all skill and project endorsements with their current counts.
Sample Request
curl -X GET '/endorsements'Success Response (200 OK)
{
"status": "success",
"data": {
"skills": {
"javascript": 15,
"nodejs": 25,
"react": 22
},
"projects": {
"portfolio-backend": 10,
"some-other-project": 5
}
}
}Add an Endorsement
/endorsementsIncrements the endorsement count for a specific skill or project.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
type | String | Yes | The type of item being endorsed. |
id | String | Yes | The ID of the skill or project (e.g., `nodejs`). |
Sample Request
curl -X POST '/endorsements' \
-H 'Content-Type: application/json' \
-d '{
"type": "string",
"id": "string"
}'Success Response (200 OK)
{
"status": "success",
"data": {
"type": "skill",
"id": "nodejs",
"endorsements": 26
}
}Error Response (400 Bad Request)
{
"status": "fail",
"message": "Invalid input: Endorsement type must be 'skill' or 'project' (in body for parameter 'type')."
}Portfolio API
This section describes the CRUD API for managing portfolio projects and skills. Public endpoints are available to read the data, while write operations are restricted to administrators.
Get All Projects
/portfolio/projectsRetrieves a list of all portfolio projects.
Sample Request
curl -X GET '/portfolio/projects'Success Response (200 OK)
The response is an array of project objects. Each project includes HATEOAS links.
{
"status": "success",
"data": [
{
"_id": "60d5f2f5c7b3c3b3c3b3c3b3",
"title": "My Awesome Project",
"description": "...",
"tags": [ ... ],
"links": [
{ "rel": "self", "href": "/api/v1/portfolio/projects/60d5f2f5c7b3c3b3c3b3c3b3" },
{ "rel": "endorse", "href": "/api/v1/endorsements" }
]
}
]
}Get All Skills
/portfolio/skillsRetrieves a list of all skills, with associated projects.
Sample Request
curl -X GET '/portfolio/skills'Success Response (200 OK)
The response is an array of skill objects. Each skill includes a list of projects that use that skill.
{
"status": "success",
"data": [
{
"_id": "60d5f2f5c7b3c3b3c3b3c3b4",
"title": "Node.js",
"category": "Backend",
"projects": [
{ "id": "project1", "title": "My Awesome Project" }
],
"links": [ ... ]
}
]
}Admin Project & Skill Endpoints
The following endpoints are for administrative purposes and require an admin-level JWT for authentication. - `POST /portfolio/projects`: Create a new project. - `PATCH /portfolio/projects/:id`: Update a project. - `DELETE /portfolio/projects/:id`: Delete a project. - `POST /portfolio/skills`: Create a new skill. - `PATCH /portfolio/skills/:id`: Update a skill. - `DELETE /portfolio/skills/:id`: Delete a skill.
Sample Request
curl -X POST ''Project Stats API
This API provides statistics for GitHub projects.
Get All Project Stats
/project-statsRetrieves a map of all project statistics.
Sample Request
curl -X GET '/project-stats'Success Response (200 OK)
The response is a map where keys are project IDs and values are the stats objects.
{
"status": "success",
"data": {
"portfolio-backend": {
"_id": "60d5f2f5c7b3c3b3c3b3c3b5",
"projectId": "portfolio-backend",
"stars": 123,
"forks": 45,
"watchers": 67,
"lastUpdatedAt": "2023-01-01T00:00:00.000Z"
}
}
}Trigger Stats Update
/project-stats/updateTriggers a background job to update the project statistics from GitHub. This is a protected endpoint intended for automated use.
Sample Request
curl -X POST '/project-stats/update'Success Response (200 OK)
{
"status": "success",
"message": "GitHub project stats update job has completed.",
"report": {
"processed": ["repo1", "repo2"],
"failed": ["repo3"],
"errors": [ ... ]
}
}Error Response (401 Unauthorized)
{
"status": "fail",
"message": "Unauthorized: Invalid API Key"
}Get Private Repo Stats (Admin)
/project-stats/private-statsThis endpoint is intended to retrieve stats for private repositories. This feature is not yet implemented. The endpoint will return a `501 Not Implemented` error.
Sample Request
curl -X GET '/project-stats/private-stats' \
-H 'Authorization: Bearer <YOUR_JWT_TOKEN>'Error Response (501 Not Implemented)
{
"status": "error",
"message": "This feature has not been implemented yet."
}Public AI API
This API provides access to various AI-powered features. All features are accessed through a single endpoint, and the desired feature is specified by a `useCaseId`.
General AI Request Endpoint
/public-ai/requestSample Request
curl -X POST '/public-ai/request'Success Response (200 OK)
{
"status": "success",
"data": {
"content": "<AI-generated response content>"
}
}Error Response (400 Bad Request (Invalid Payload))
If the payload does not match the schema for the given `useCaseId`.
Error Response (400 Bad Request (Malicious Input))
If the input is flagged by the AI security service.
Error Response (404 Not Found)
If the `useCaseId` does not exist or is disabled.
Error Response (429 Too Many Requests)
If the user's request budget is exceeded.
Health Check API
This section describes the API for monitoring the health of the application and its dependencies.
Get Health Status
/healthThis endpoint checks the status of the MongoDB database, the Redis cache, and the AI provider gateway. It returns a `200 OK` status if all services are operational and a `503 Service Unavailable` if any service is down.
Sample Request
curl -X GET '/health'Success Response (200 OK)
{
"status": "ok",
"timestamp": "2023-01-01T12:00:00.000Z",
"checks": {
"database": {
"status": "up"
},
"cache": {
"status": "up"
},
"ai_gateway": {
"status": "operational",
"details": "At least one Tier 1 model is healthy."
}
}
}Error Response (503 Service Unavailable)
{
"status": "error",
"timestamp": "2023-01-01T12:01:00.000Z",
"checks": {
"database": {
"status": "up"
},
"cache": {
"status": "down",
"error": "Could not connect to Redis."
},
"ai_gateway": {
"status": "operational",
"details": "At least one Tier 1 model is healthy."
}
}
}Admin API & Endpoints
This section covers endpoints that are restricted to users with the `admin` role.
Admin Web Interface
The application includes a web-based administrative interface. The routes below are for rendering HTML pages for this interface and are not part of the JSON API. - `GET /admin/login`: Renders the admin login page. - `GET /admin`: Renders the main admin dashboard. Requires admin authentication.
Sample Request
curl -X GET ''Get Email Analytics (Admin)
/analytics/emailsRetrieves email analytics data. This endpoint supports filtering, sorting, field limiting, and pagination.
Sample Request
curl -X GET '/analytics/emails' \
-H 'Authorization: Bearer <YOUR_JWT_TOKEN>'Success Response (200 OK)
{
"status": "success",
"results": 1,
"data": [
{
"_id": "60d5f2f5c7b3c3b3c3b3c3b6",
"date": "2023-01-01T00:00:00.000Z",
"totalEmails": 50,
"totalSpam": 5,
"averageSentiment": 0.8,
"intents": {
"job_inquiry": 10,
"project_proposal": 20,
"general_question": 15
}
}
]
}