API Documentation

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/v1

Authentication

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

POST/users/signup

Request Body

FieldTypeRequiredDescription
nameStringYesThe user's full name.
emailStringYesThe user's email address.
passwordStringYesThe user's password.
passwordConfirmStringYesConfirmation 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

POST/users/login

Request Body

FieldTypeRequiredDescription
emailStringYesThe user's email address.
passwordStringYesThe 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

POST/users/logout

Sample Request

curl -X POST '/users/logout' \
  -H 'Authorization: Bearer <YOUR_JWT_TOKEN>'

Success Response (200 OK)

{
  "status": "success"
}

Forgot Password

POST/users/forgotPassword

Request Body

FieldTypeRequiredDescription
emailStringYesThe 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

PATCH/users/resetPassword/:token

Request Body

FieldTypeRequiredDescription
passwordStringYesThe new password.
passwordConfirmStringYesConfirmation 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

GET/users/me

Sample 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

PATCH/users/updateMe

Updates 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

FieldTypeRequiredDescription
nameStringNoThe user's new name.
emailStringNoThe 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

DELETE/users/deleteMe

Deactivates 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

PATCH/users/updateMyPassword

Updates the password for the currently logged-in user.

Request Body

FieldTypeRequiredDescription
passwordCurrentStringYesThe user's current password.
passwordStringYesThe new password.
passwordConfirmStringYesConfirmation 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

POST/email/contact

Submits the main contact form, potentially with file attachments. This endpoint performs AI analysis on the message content and sends confirmation emails.

Request Body

FieldTypeRequiredDescription
nameStringYesThe sender's name.
emailStringYesThe sender's email address.
subjectStringYesThe subject of the message.
messageStringYesThe body of the message.
attachmentsFile[]NoFile attachments for the message.
honeypotStringNoA 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)

POST/email/:id/draft-reply

Generates 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

GET/endorsements

Retrieves 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

POST/endorsements

Increments the endorsement count for a specific skill or project.

Request Body

FieldTypeRequiredDescription
typeStringYesThe type of item being endorsed.
idStringYesThe 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

GET/portfolio/projects

Retrieves 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

GET/portfolio/skills

Retrieves 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

POST

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

GET/project-stats

Retrieves 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

POST/project-stats/update

Triggers 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)

GET/project-stats/private-stats

This 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

POST/public-ai/request

Sample 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

GET/health

This 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

GET

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)

GET/analytics/emails

Retrieves 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
      }
    }
  ]
}