Overview
The dashboard endpoint returns a hierarchical view of all your data - clients with their projects, and each project with its licenses. This provides a complete overview of your licensing infrastructure.
Endpoint
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
Optional Request Body
Optional MongoDB ObjectId to filter dashboard data for a specific client
If no clientId is provided, the endpoint returns data for all clients owned by the authenticated user.
Example Request
cURL - All Clients
cURL - Specific Client
JavaScript
Python
curl -X GET https://your-keybox-server.com/dashboard \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Response
Success Response
Total number of clients returned
Total number of projects across all clients
Array of client objects with nested projects and licenses
Each client object contains: Client’s MongoDB ObjectId
Client’s name or company name
User ID who owns this client
Each project object contains: Project’s MongoDB ObjectId
Client ID this project belongs to
Array of license objects for this project
Each license object contains: License status (PENDING, ACTIVE, EXPIRED, REVOKED)
Array of included services
Hashed machine ID (if activated)
Example Response
{
"message" : "Dashboard fetched successfully" ,
"clientsCount" : 2 ,
"projectsCount" : 3 ,
"data" : [
{
"_id" : "60f7b3b3e6b3a72e8c8e4a1a" ,
"name" : "Acme Corporation" ,
"email" : "[email protected] " ,
"owner" : "60f7b3b3e6b3a72e8c8e4a19" ,
"projects" : [
{
"_id" : "60f7b3b3e6b3a72e8c8e4a1b" ,
"name" : "E-commerce Website" ,
"client" : "60f7b3b3e6b3a72e8c8e4a1a" ,
"licenses" : [
{
"_id" : "60f7b3b3e6b3a72e8c8e4a1c" ,
"key" : "KB-60f7b3b3e6b3a72e8c8e4a1b-A1B2-C3D4-E5F6" ,
"duration" : 12 ,
"issuedAt" : "2024-01-01T00:00:00.000Z" ,
"expiresAt" : "2025-01-01T00:00:00.000Z" ,
"status" : "ACTIVE" ,
"services" : [ "Hosting" , "Domain" ],
"machineId" : "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
}
]
},
{
"_id" : "60f7b3b3e6b3a72e8c8e4a1d" ,
"name" : "Mobile App Backend" ,
"client" : "60f7b3b3e6b3a72e8c8e4a1a" ,
"licenses" : [
{
"_id" : "60f7b3b3e6b3a72e8c8e4a1e" ,
"key" : "KB-60f7b3b3e6b3a72e8c8e4a1d-B2C3-D4E5-F6G7" ,
"duration" : 6 ,
"issuedAt" : "2024-02-01T00:00:00.000Z" ,
"expiresAt" : "2024-08-01T00:00:00.000Z" ,
"status" : "PENDING" ,
"services" : [ "Hosting" ]
}
]
}
]
},
{
"_id" : "60f7b3b3e6b3a72e8c8e4a1f" ,
"name" : "TechStart Inc" ,
"email" : "[email protected] " ,
"owner" : "60f7b3b3e6b3a72e8c8e4a19" ,
"projects" : [
{
"_id" : "60f7b3b3e6b3a72e8c8e4a20" ,
"name" : "SaaS Platform" ,
"client" : "60f7b3b3e6b3a72e8c8e4a1f" ,
"licenses" : [
{
"_id" : "60f7b3b3e6b3a72e8c8e4a21" ,
"key" : "KB-60f7b3b3e6b3a72e8c8e4a20-C3D4-E5F6-G7H8" ,
"duration" : 12 ,
"issuedAt" : "2024-01-15T00:00:00.000Z" ,
"expiresAt" : "2025-01-15T00:00:00.000Z" ,
"status" : "ACTIVE" ,
"services" : [ "Hosting" , "Domain" ],
"machineId" : "b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7"
}
]
}
]
}
]
}
Data Hierarchy
The dashboard returns data in this hierarchy:
Client
├─ Client Info (name, email, owner)
└─ Projects []
├─ Project Info (name, client)
└─ Licenses []
└─ License Info (key, status, duration, etc.)
Query Behavior
The endpoint automatically filters by the authenticated user’s ID (owner field). You only see clients you own.
If you provide a clientId, only that specific client’s data is returned (if you own it).
The endpoint uses MongoDB’s aggregation to efficiently fetch nested relationships without multiple queries.
Error Responses
Unauthorized
Status Code : 401
{
"message" : "Unauthorized"
}
Server Error
Status Code : 500
{
"message" : "Failed to fetch dashboard" ,
"error" : "Detailed error message"
}
Complete Example
class Dashboard {
constructor ( serverUrl , authToken ) {
this . serverUrl = serverUrl ;
this . authToken = authToken ;
}
async fetchAll () {
try {
const response = await fetch ( ` ${ this . serverUrl } /dashboard` , {
headers: {
'Authorization' : `Bearer ${ this . authToken } `
}
});
if ( ! response . ok ) {
throw new Error ( `HTTP ${ response . status } ` );
}
const data = await response . json ();
this . displaySummary ( data );
return data ;
} catch ( error ) {
console . error ( 'Failed to fetch dashboard:' , error );
throw error ;
}
}
async fetchClient ( clientId ) {
try {
const response = await fetch ( ` ${ this . serverUrl } /dashboard` , {
method: 'GET' ,
headers: {
'Content-Type' : 'application/json' ,
'Authorization' : `Bearer ${ this . authToken } `
},
body: JSON . stringify ({ clientId })
});
const data = await response . json ();
return data ;
} catch ( error ) {
console . error ( 'Failed to fetch client:' , error );
throw error ;
}
}
displaySummary ( data ) {
console . log ( ' \n === Dashboard Summary ===' );
console . log ( `Total Clients: ${ data . clientsCount } ` );
console . log ( `Total Projects: ${ data . projectsCount } ` );
let totalLicenses = 0 ;
let activeLicenses = 0 ;
let pendingLicenses = 0 ;
data . data . forEach ( client => {
client . projects . forEach ( project => {
totalLicenses += project . licenses . length ;
project . licenses . forEach ( license => {
if ( license . status === 'ACTIVE' ) activeLicenses ++ ;
if ( license . status === 'PENDING' ) pendingLicenses ++ ;
});
});
});
console . log ( `Total Licenses: ${ totalLicenses } ` );
console . log ( `Active: ${ activeLicenses } ` );
console . log ( `Pending: ${ pendingLicenses } ` );
console . log ( '======================== \n ' );
}
getExpiringLicenses ( days = 30 ) {
const threshold = new Date ();
threshold . setDate ( threshold . getDate () + days );
const expiring = [];
this . lastData ?. data . forEach ( client => {
client . projects . forEach ( project => {
project . licenses . forEach ( license => {
const expiresAt = new Date ( license . expiresAt );
if ( license . status === 'ACTIVE' && expiresAt < threshold ) {
expiring . push ({
client: client . name ,
project: project . name ,
key: license . key ,
expiresAt: expiresAt
});
}
});
});
});
return expiring ;
}
}
// Usage
const dashboard = new Dashboard (
'https://your-keybox-server.com' ,
'your-jwt-token'
);
// Fetch all data
const data = await dashboard . fetchAll ();
// Check for expiring licenses
const expiring = dashboard . getExpiringLicenses ( 30 );
if ( expiring . length > 0 ) {
console . log ( ' \n Licenses expiring in 30 days:' );
expiring . forEach ( item => {
console . log ( ` ${ item . client } - ${ item . project } : ${ item . expiresAt . toDateString () } ` );
});
}
Use Cases
Admin Overview Get a complete view of all clients, projects, and licenses
Client Portal Filter by clientId to show client-specific data
Expiration Alerts Identify licenses expiring soon for renewal
Analytics Analyze license usage patterns and status distribution
Best Practices
Cache Results Cache dashboard data locally to reduce API calls
Pagination For large datasets, consider implementing pagination
Refresh Strategy Refresh data periodically or on user action
Error Handling Handle network errors and display fallback UI
See Also