Prerequisites
Before you begin, ensure you have:
Node.js (v14 or higher)
MongoDB Atlas account (or local MongoDB instance)
A code editor
Terminal/command line access
Installation
Clone and install dependencies
Clone the repository and install the required npm packages: git clone https://github.com/Marcosdaag/stockapi.git
cd stockapi
npm install
The following dependencies will be installed:
express - Web framework
mongoose - MongoDB ODM
jsonwebtoken - JWT authentication
bcryptjs - Password hashing
dotenv - Environment variables
resend - Email service
cors - Cross-origin resource sharing
body-parser - Request parsing
Configure environment variables
Create a .env file in the root directory with the following variables: # Server Configuration
PORT = 3000
# MongoDB Connection
MONGO_URI = mongodb+srv://username:[email protected] /stockapi
# JWT Authentication
JWT_SECRET = your_super_secret_jwt_key_here
# Email Configuration (Resend)
RESEND_API_KEY = re_your_resend_api_key
APP_NAME = StockAPI
EMAIL_USER = [email protected]
EMAIL_PASS = your_email_password
Never commit your .env file to version control. Keep your credentials secure.
Set up MongoDB connection
The API connects to MongoDB using the MONGO_URI environment variable. From index.js:15: mongoose . connect ( process . env . MONGO_URI )
. then (() => {
console . log ( "✅ Conexión a MongoDB Atlas establecida correctamente" );
app . listen ( port , () => {
console . log ( `✅ Servidor funcionando en el puerto ${ port } ` );
});
})
. catch (( error ) => console . error ( "❌ Error al conectar a MongoDB Atlas:" , error ));
Make sure your MongoDB Atlas cluster:
Has network access configured (whitelist your IP or allow all)
Has a database user created with read/write permissions
Has the correct connection string in your .env file
Start the server
Launch the API server: Production
Development (with nodemon)
You should see: ✅ Conexión a MongoDB Atlas establecida correctamente
✅ Servidor funcionando en el puerto 3000
Making Your First API Call
Most endpoints require authentication. We’ll start with the public endpoints, then show you how to authenticate.
1. List All Products (Public Endpoint)
This endpoint doesn’t require authentication:
curl http://localhost:3000/products
Response:
{
"products" : [
{
"_id" : "507f1f77bcf86cd799439011" ,
"brand" : "Coca-Cola" ,
"name" : "Coca Cola 2L" ,
"stock" : 50 ,
"price" : 2.5 ,
"normalizedName" : "coca cola 2l"
},
{
"_id" : "507f1f77bcf86cd799439012" ,
"brand" : "Pepsi" ,
"name" : "Pepsi 1.5L" ,
"stock" : 30 ,
"price" : 2.0 ,
"normalizedName" : "pepsi 1.5l"
}
]
}
2. Authenticate and Get JWT Token
You’ll need to create a user first using the internal user creation script. Users are not created via API for security reasons.
Once you have a user account, authenticate:
curl -X POST http://localhost:3000/login \
-H "Content-Type: application/json" \
-d '{
"username": "your_username",
"password": "your_password"
}'
Response (from authController.js:29-33):
{
"message" : "Login exitoso" ,
"token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ,
"user" : {
"username" : "your_username" ,
"role" : "vendedor"
}
}
Tokens expire after 4 hours (authController.js:26). You’ll need to login again when they expire.
3. Create a New Product (Protected)
Use the JWT token from step 2 in the Authorization header:
curl -X POST http://localhost:3000/products \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN_HERE" \
-d '{
"brand": "Fanta",
"name": "Fanta Orange 2L",
"stock": 40,
"price": 2.3
}'
Response (from productController.js:15):
{
"message" : "✅ Producto nuevo agregado con exito" ,
"product" : {
"_id" : "507f1f77bcf86cd799439013" ,
"brand" : "Fanta" ,
"name" : "Fanta Orange 2L" ,
"stock" : 40 ,
"price" : 2.3 ,
"normalizedName" : "fanta orange 2l"
}
}
4. Create an Order (Auto-Deducts Stock)
Orders automatically reduce product stock:
curl -X POST http://localhost:3000/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN_HERE" \
-d '{
"products": [
{
"product": "507f1f77bcf86cd799439011",
"quantity": 3,
"customName": "Coca Cola 2L"
},
{
"product": "507f1f77bcf86cd799439012",
"quantity": 2
}
],
"total": 11.5
}'
Response (from orderController.js:12):
{
"message" : "✅ Orden creada con éxito" ,
"order" : {
"_id" : "507f1f77bcf86cd799439020" ,
"products" : [
{
"product" : "507f1f77bcf86cd799439011" ,
"quantity" : 3 ,
"customName" : "Coca Cola 2L"
},
{
"product" : "507f1f77bcf86cd799439012" ,
"quantity" : 2
}
],
"total" : 11.5 ,
"createdAt" : "2026-03-05T10:30:00.000Z" ,
"updatedAt" : "2026-03-05T10:30:00.000Z"
}
}
If there’s insufficient stock, you’ll receive a 400 error: "❌ Stock insuficiente" (orderController.js:14)
5. Search Products
Search for products by name or brand:
curl "http://localhost:3000/search?q=coca" \
-H "Authorization: Bearer YOUR_JWT_TOKEN_HERE"
Response:
{
"products" : [
{
"_id" : "507f1f77bcf86cd799439011" ,
"brand" : "Coca-Cola" ,
"name" : "Coca Cola 2L" ,
"stock" : 47 ,
"price" : 2.5 ,
"normalizedName" : "coca cola 2l"
}
]
}
All protected endpoints require the JWT token in the Authorization header (middlewares/jwtMiddleware.js:10):
Authorization: Bearer <your_jwt_token>
If the token is missing, expired, or invalid, you’ll receive:
401 : "No se proporcionó token" or "Token inválido"
403 : "Token expirado o inválido"
Using Docker
Alternatively, run StockAPI using Docker:
# Pull the image from GitHub Packages
docker pull ghcr.io/marcosdaag/stockapi:latest
# Run the container
docker run -p 3000:3000 \
-e MONGO_URI="your_mongodb_uri" \
-e JWT_SECRET="your_jwt_secret" \
ghcr.io/marcosdaag/stockapi:latest
Next Steps
API Reference Explore all available endpoints and their parameters
Authentication Learn more about JWT tokens and user roles
Environment Setup Configure environment variables and dependencies
Docker Deployment Deploy with Docker containers