Overview
Projects represent specific software products or services delivered to clients. Each project is associated with a client and has at least one license. The project endpoint allows you to create both the project and its initial license in a single transaction.
Create Project with License
Create a new project and generate its first license automatically.
Endpoint
POST /projects/createProject
This endpoint requires authentication. Include a valid JWT token in the Authorization header.
Authentication
Include the JWT token in the Authorization header:
Authorization: Bearer <your-jwt-token>
Request Body
MongoDB ObjectId of the client this project belongs to
License duration in months (1-12)
Array of services included in the license (e.g., [“Hosting”, “Domain”]). Must include at least one service.
Example Request
curl -X POST https://your-keybox-server.com/projects/createProject \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-d '{
"clientId": "60f7b3b3e6b3a72e8c8e4a1a",
"projectName": "E-commerce Website",
"duration": 12,
"services": ["Hosting", "Domain"]
}'
Response
The created project object
The created license object
MongoDB ObjectId of the project
Client ID this project belongs to
When the project was created
When the project was last updated
MongoDB ObjectId of the license
The generated license key
License duration in months
When the license was created
When the license will expire
Array of included services
License status (“PENDING” initially)
User ID who created the license
Example Response
{
"message" : "Project and License created successfully" ,
"project" : {
"_id" : "60f7b3b3e6b3a72e8c8e4a1b" ,
"name" : "E-commerce Website" ,
"client" : "60f7b3b3e6b3a72e8c8e4a1a" ,
"createdAt" : "2024-01-01T00:00:00.000Z" ,
"updatedAt" : "2024-01-01T00:00:00.000Z"
},
"license" : {
"_id" : "60f7b3b3e6b3a72e8c8e4a1c" ,
"key" : "KB-60f7b3b3e6b3a72e8c8e4a1b-A1B2-C3D4-E5F6" ,
"duration" : 12 ,
"issuedAt" : "2024-01-01T00:00:00.000Z" ,
"expiresAt" : "2025-01-01T00:00:00.000Z" ,
"services" : [ "Hosting" , "Domain" ],
"status" : "PENDING" ,
"user" : "60f7b3b3e6b3a72e8c8e4a19" ,
"client" : "60f7b3b3e6b3a72e8c8e4a1a" ,
"project" : "60f7b3b3e6b3a72e8c8e4a1b"
}
}
Transaction Handling
This endpoint uses MongoDB transactions to ensure atomic creation of both project and license.
The transaction ensures:
Atomicity : Both project and license are created together, or neither is created
Consistency : If any step fails, all changes are rolled back
Data Integrity : No orphaned projects or licenses
Transaction Flow
Start Transaction
Begin MongoDB transaction (skipped in test environment)
Validate Client
Verify the client exists
Create Project
Insert project record within transaction
Generate License
Create license with auto-generated key within transaction
Commit
Commit transaction if all steps succeed
Rollback on Error
Abort transaction if any step fails
Error Responses
Missing Client ID or Project Name
Status Code : 400
{
"message" : "Client ID & Project name required"
}
Invalid Duration
Status Code : 400
{
"message" : "Invalid duration"
}
Duration must be between 1 and 12 months.
Missing Services
Status Code : 400
{
"message" : "At least one service is required"
}
Client Not Found
Status Code : 404
{
"message" : "Client not found"
}
Unauthorized
Status Code : 401
{
"message" : "Unauthorized"
}
Server Error
Status Code : 500
{
"message" : "Failed to create project and license" ,
"error" : "Detailed error message"
}
Services
The services array defines what’s included in the license. Available options:
Hosting : Web hosting service
Domain : Domain registration/management
You must provide at least one service:
{
"services" : [ "Hosting" ]
}
Or multiple services:
{
"services" : [ "Hosting" , "Domain" ]
}
Complete Example
class ProjectManager {
constructor ( serverUrl , authToken ) {
this . serverUrl = serverUrl ;
this . authToken = authToken ;
}
async createProject ( clientId , projectName , duration , services ) {
try {
const response = await fetch (
` ${ this . serverUrl } /projects/createProject` ,
{
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'Authorization' : `Bearer ${ this . authToken } `
},
body: JSON . stringify ({
clientId ,
projectName ,
duration ,
services
})
}
);
if ( ! response . ok ) {
const error = await response . json ();
throw new Error ( error . message || `HTTP ${ response . status } ` );
}
const data = await response . json ();
console . log ( 'Project created:' , data . project . name );
console . log ( 'License key:' , data . license . key );
console . log ( 'License expires:' , new Date ( data . license . expiresAt ));
return data ;
} catch ( error ) {
console . error ( 'Failed to create project:' , error . message );
throw error ;
}
}
}
// Usage - Complete workflow
const manager = new ProjectManager (
'https://your-keybox-server.com' ,
'your-jwt-token'
);
try {
// Assuming you already have a client
const result = await manager . createProject (
'60f7b3b3e6b3a72e8c8e4a1a' , // clientId
'E-commerce Website' , // projectName
12 , // duration (months)
[ 'Hosting' , 'Domain' ] // services
);
// Send license key to client
const licenseKey = result . license . key ;
console . log ( ' \n Share this license key with your client:' );
console . log ( licenseKey );
} catch ( error ) {
console . error ( 'Setup failed:' , error . message );
}
Workflow Integration
Typical workflow for setting up a new project:
Create Project
Use the client ID to create a project with its license
Deliver License
Send the generated license key to the client
Client Setup
Client activates the license in their application
Best Practices
Descriptive Names Use clear, descriptive project names for easy identification
Appropriate Duration Set license duration based on your service agreement
Service Selection Clearly define included services for transparency
Error Handling Handle transaction failures gracefully
See Also