Get your Portfolio Hub API up and running, create your first user account, and make authenticated API requests.
Prerequisites
Before you begin, ensure you have the following installed on your system:
Java 21 (JDK) Required to run the Spring Boot application
Maven 3.9+ Build tool for managing dependencies
MySQL 8.0+ Database for storing portfolio data
Git Version control for cloning the repository
You can verify your installations by running: java -version
mvn -version
mysql --version
Step 1: Clone and Setup
Clone the repository
Clone the Portfolio Hub API repository to your local machine: git clone https://github.com/LavenderEdit/Portfolio.git
cd Portfolio
Create MySQL database
Create a new MySQL database for the application: CREATE DATABASE studiostkoh .portafolio;
EXIT;
Flyway will automatically create all required tables when you first run the application.
Configure environment variables
Set up the required environment variables. Create a .env file or export them directly: # Database Configuration
export MYSQL_HOST = localhost
export MYSQL_PORT = 3306
export MYSQL_DATABASE = studiostkoh . portafolio
export MYSQL_USER = your_username
export MYSQL_PASSWORD = your_password
# JWT Configuration
export JWT_TOKEN = your_secret_key_at_least_256_bits_long_for_security
export JWT_EXPIRATION_TIME = 60
# CORS Configuration
export CORS_ALLOWED_ORIGINS = http :// localhost : 3000
The JWT_TOKEN must be a strong, random string. Never use a simple password or commit this value to version control.
Step 2: Run the Application
Start the Portfolio Hub API server:
You should see output similar to:
Started PortfolioApplication in 5.432 seconds (process running for 5.891)
The API is now running at http://localhost:8080
Step 3: Register Your First User
Create a new user account using the /api/auth/register endpoint:
cURL
JavaScript (Fetch)
Python (Requests)
curl -X POST http://localhost:8080/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"fullName": "John Doe",
"email": "[email protected] ",
"password": "securePassword123"
}'
Request Requirements
The RegisterRequest accepts the following fields:
Field Type Validation Description fullNamestring 3-120 characters, required User’s full name emailstring Valid email, max 150 characters, required User’s email address passwordstring Min 8 characters, max 100, required Account password
Successful Response
{
"success" : true ,
"message" : "Usuario registrado exitosamente" ,
"data" : {
"token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
},
"timestamp" : "2026-03-09T10:15:30.123Z"
}
The API automatically creates a profile for each new user and returns a JWT token that you can use immediately.
Step 4: Login to Your Account
Authenticate with your credentials to obtain a JWT token:
cURL
JavaScript (Fetch)
Python (Requests)
curl -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected] ",
"password": "securePassword123"
}'
Successful Response
{
"success" : true ,
"message" : "Login exitoso" ,
"data" : {
"token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
},
"timestamp" : "2026-03-09T10:20:45.456Z"
}
Store the JWT token securely. You’ll need to include it in the Authorization header for all authenticated requests.
Step 5: Make Your First Authenticated Request
Use the JWT token to access protected endpoints. Let’s fetch your profile:
cURL
JavaScript (Fetch)
Python (Requests)
curl -X GET http://localhost:8080/api/me/profile \
-H "Authorization: Bearer YOUR_JWT_TOKEN_HERE"
Successful Response
{
"success" : true ,
"message" : "Perfil obtenido exitosamente" ,
"data" : {
"id" : 1 ,
"fullName" : "John Doe" ,
"slug" : "john-doe" ,
"tagline" : null ,
"bio" : null ,
"avatarUrl" : null ,
"resumeUrl" : null ,
"contactEmail" : null
},
"timestamp" : "2026-03-09T10:25:30.789Z"
}
Step 6: Update Your Profile
Now let’s update your profile with additional information:
cURL
JavaScript (Fetch)
Python (Requests)
curl -X PUT http://localhost:8080/api/me/profile \
-H "Authorization: Bearer YOUR_JWT_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{
"tagline": "Full Stack Developer",
"bio": "Passionate software engineer with 5+ years of experience",
"location": "San Francisco, CA"
}'
Successful Response
{
"success" : true ,
"message" : "Perfil actualizado exitosamente" ,
"data" : {
"id" : 1 ,
"fullName" : "John Doe" ,
"slug" : "john-doe" ,
"tagline" : "Full Stack Developer" ,
"bio" : "Passionate software engineer with 5+ years of experience" ,
"location" : "San Francisco, CA" ,
"avatarUrl" : null ,
"resumeUrl" : null ,
"contactEmail" : null
},
"timestamp" : "2026-03-09T10:30:15.234Z"
}
Next Steps
Congratulations! You’ve successfully set up Portfolio Hub API and made your first authenticated requests. Here’s what you can explore next:
Authentication Learn about JWT tokens, security, and session management
API Reference Explore all available endpoints and their usage
Managing Portfolios Add projects, experiences, education, and skills
File Uploads Upload avatars, resumes, and project images to Google Drive
Common Issues
Connection refused to MySQL
Ensure MySQL is running and accessible on the configured host and port: mysql -h localhost -u your_username -p
Check that the MYSQL_HOST, MYSQL_PORT, MYSQL_USER, and MYSQL_PASSWORD environment variables are correctly set.
JWT tokens expire based on the JWT_EXPIRATION_TIME setting (default: 60 minutes). If you receive a 401 Unauthorized error, login again to get a fresh token.
If you encounter Flyway migration issues, ensure your database schema is empty on first run. Flyway will create all necessary tables automatically. To reset the database: DROP DATABASE studiostkoh . portafolio ;
CREATE DATABASE studiostkoh .portafolio;
If port 8080 is already in use, you can change the server port by adding: Or add to application.properties:
API Response Structure
All Portfolio Hub API endpoints return responses in a consistent format:
{
success : boolean ; // Indicates if the request was successful
message : string ; // Human-readable message
data : T | null ; // Response data (type varies by endpoint)
timestamp : string ; // ISO 8601 timestamp
}
Success Response Example
{
"success" : true ,
"message" : "Perfil obtenido exitosamente" ,
"data" : { /* ... */ },
"timestamp" : "2026-03-09T10:15:30.123Z"
}
Error Response Example
{
"success" : false ,
"message" : "Email already in use" ,
"data" : null ,
"timestamp" : "2026-03-09T10:15:30.123Z"
}
Always check the success field before processing the data to ensure your request completed successfully.