Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/LavenderEdit/Portfolio/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Portfolio Hub API uses JWT (JSON Web Tokens) for authentication. After registering or logging in, you’ll receive a token that must be included in the Authorization header for protected endpoints.

Authentication Flow

1

Register or Login

Obtain a JWT token by registering a new account or logging in with existing credentials.
2

Include Token in Requests

Add the token to the Authorization header as a Bearer token for all authenticated requests.
3

Token Validation

The API validates the token on each request and extracts user information.
4

Token Expiration

Tokens expire after a configured duration. You’ll need to login again to obtain a fresh token.

Registering a New Account

Create a new user account to receive a JWT token.

Endpoint

POST /api/auth/register

Request Body

fullName
string
required
User’s full name (3-120 characters)
email
string
required
Valid email address (max 150 characters). Must be unique.
password
string
required
Password (8-100 characters)

Example Request

curl -X POST https://your-domain.com/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "fullName": "John Doe",
    "email": "john.doe@example.com",
    "password": "securePassword123"
  }'

Example Response

{
  "success": true,
  "message": "Usuario registrado exitosamente",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9maWxlSWQiOjEsInVzZXJJZCI6MSwic3ViIjoiam9obi5kb2VAZXhhbXBsZS5jb20iLCJpYXQiOjE3MDk5ODQ2MDAsImV4cCI6MTcwOTk4ODIwMH0.signature"
  },
  "timestamp": "2026-03-09T14:30:00.000Z"
}
Upon successful registration, a profile is automatically created with a unique slug based on the full name.

Error Responses

{
  "success": false,
  "message": "El correo ya está en uso. Por favor intente otro.",
  "data": null,
  "timestamp": "2026-03-09T14:30:00.000Z"
}

Logging In

Authenticate with existing credentials to receive a JWT token.

Endpoint

POST /api/auth/login

Request Body

email
string
required
Valid email address
password
string
required
Account password

Example Request

curl -X POST https://your-domain.com/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "john.doe@example.com",
    "password": "securePassword123"
  }'

Example Response

{
  "success": true,
  "message": "Login exitoso",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9maWxlSWQiOjEsInVzZXJJZCI6MSwic3ViIjoiam9obi5kb2VAZXhhbXBsZS5jb20iLCJpYXQiOjE3MDk5ODQ2MDAsImV4cCI6MTcwOTk4ODIwMH0.signature"
  },
  "timestamp": "2026-03-09T14:30:00.000Z"
}

Error Response

401 Unauthorized - Invalid Credentials
{
  "success": false,
  "message": "Credenciales inválidas",
  "data": null,
  "timestamp": "2026-03-09T14:30:00.000Z"
}

Using the JWT Token

Once you have a token, include it in the Authorization header for all authenticated requests.

Authorization Header Format

Authorization: Bearer <your_jwt_token>

Example Authenticated Request

curl -X GET https://your-domain.com/api/me/profile \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Always include the word “Bearer” followed by a space before the token. The token must start at character position 7 in the header value.

JWT Token Structure

The JWT token includes the following claims:

Standard Claims

sub
string
Subject - the user’s email address
iat
number
Issued At - Unix timestamp when the token was created
exp
number
Expiration - Unix timestamp when the token expires

Custom Claims

profileId
number
The user’s profile ID for quick profile access
userId
number
The user’s unique identifier

Example Decoded Token

{
  "profileId": 1,
  "userId": 1,
  "sub": "john.doe@example.com",
  "iat": 1709984600,
  "exp": 1709988200
}

Token Expiration

JWT tokens have a limited lifetime configured by the server administrator via the JWT_EXPIRATION_TIME environment variable (in minutes).
The default expiration time is configured server-side. When your token expires, you’ll receive a 401 Unauthorized response and need to login again.

Handling Expired Tokens

When a token expires, requests will fail with:
401 Unauthorized
{
  "success": false,
  "message": "Authentication failed",
  "data": null,
  "timestamp": "2026-03-09T14:30:00.000Z"
}
Best Practice: Implement automatic re-authentication in your client application when receiving 401 responses.

Token Security

The API uses HMAC-SHA256 for token signing, ensuring tokens cannot be tampered with.

Security Configuration

  • Algorithm: HMAC with SHA-256 (HS256)
  • Secret Key: Configured via JWT_SECRET_KEY environment variable
  • Session Management: Stateless (no server-side sessions)

Security Best Practices

Never expose your JWT token in:
  • URL parameters
  • Browser console logs
  • Client-side storage (use secure, httpOnly cookies instead)
  • Version control systems
  • Error messages
Do:
  • Store tokens securely (e.g., in-memory or secure storage)
  • Use HTTPS to prevent token interception
  • Implement token refresh logic before expiration
  • Clear tokens on logout
  • Validate tokens on every request

Protected Endpoints

User Endpoints (/api/me/**)

Require valid JWT token with any authenticated user:
  • GET /api/me/profile - Get current user’s profile
  • PUT /api/me/profile - Update current user’s profile
  • PUT /api/me/settings/contact-email - Update contact email
  • All resource management endpoints (projects, skills, experience, etc.)

Admin Endpoints (/api/admin/**)

Require JWT token with ROLE_ADMIN authority:
  • Administrative functions for managing global resources
Admin endpoints require the user account to have ROLE_ADMIN authority. Regular users with valid tokens will receive a 403 Forbidden response.

Accessing User Information

When authenticated, the API automatically extracts user information from the token:
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
Long profileId = userDetails.getProfileId();
Long userId = userDetails.getUserId();
String email = userDetails.getUsername();
You don’t need to manually include user IDs in requests - the API extracts them from your token.

Troubleshooting

Common Authentication Errors

IssueCauseSolution
401 UnauthorizedMissing or invalid tokenEnsure token is included with “Bearer ” prefix
401 UnauthorizedExpired tokenLogin again to get a fresh token
403 ForbiddenInsufficient permissionsVerify user has required role (e.g., ROLE_ADMIN)
400 Bad RequestMalformed headerCheck Authorization header format

Testing Authentication

You can test your authentication using tools like cURL or Postman:
# 1. Login and capture token
TOKEN=$(curl -X POST https://your-domain.com/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com","password":"password"}' \
  | jq -r '.data.token')

# 2. Use token in authenticated request
curl -X GET https://your-domain.com/api/me/profile \
  -H "Authorization: Bearer $TOKEN"

Build docs developers (and LLMs) love