Admin Module
The admin module provides administrative functions for user management, KYC approval, and admin operations. Includes Xendit integration for Indonesia users.
Import
const admin = await brdzSDK.admin;
Methods Overview
| Method | Description | Auth Required | HTTP Endpoint |
|---|---|---|---|
createUserByAdmin | Create user as admin | ✅ | POST /admins/users |
getListAdmin | Get admin list | ✅ | GET /admins/list |
approveUserKYC | Approve user KYC | ✅ | POST /admins/approve-kyc/:userId |
getUserDetails | Get user details | ✅ | GET /admins/users/:userId |
createUserByAdmin
Create a new user account with admin privileges. Automatically generates temporary password, creates eKYC entry with APPROVED status, and sends welcome email. Includes Xendit customer creation for Indonesia users.
Syntax
const result = await admin.createUserByAdmin(userData);
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
userData | object | ✅ | User creation data |
userData.client_id | number | ✅ | Client ID to associate user with |
userData.username | string | ✅ | Username for the new user |
userData.email | string | ✅ | Email address for the new user |
userData.phone | string | ✅ | Phone number for the new user |
userData.country_code | string | ✅ | Country code for eKYC entry |
userData.role | string | ❌ | User role (default: 'user') |
userData.is_wishlist | boolean | ❌ | Wishlist status (default: false) |
Returns
Promise<{
message: string;
user: {
user_id: number;
username: string;
email: string;
phone: string;
role: string;
user_status: string;
created: string;
updated: string;
is_wishlist: boolean;
};
temp_password: string;
ekyc_status: string;
xendit_integration?: {
psp_provider: string;
customer_status: string;
customer_id: string;
customer_type: string;
database_id: number;
};
}>
Example
try {
const newUser = await admin.createUserByAdmin({
client_id: 1,
username: 'newuser123',
email: 'newuser@example.com',
phone: '+628123456789',
country_code: 'ID',
role: 'user',
is_wishlist: false
});
console.log('User created:', newUser.user.username);
console.log('User ID:', newUser.user.user_id);
console.log('Temporary password:', newUser.temp_password);
console.log('eKYC Status:', newUser.ekyc_status);
// Check for Xendit integration (Indonesia users only)
if (newUser.xendit_integration) {
console.log('Xendit Customer ID:', newUser.xendit_integration.customer_id);
console.log('Customer Type:', newUser.xendit_integration.customer_type);
console.log('PSP Provider:', newUser.xendit_integration.psp_provider);
} else {
console.log('No Xendit integration (non-Indonesia user)');
}
// Store credentials securely for user
const credentials = {
email: newUser.user.email,
password: newUser.temp_password,
userId: newUser.user.user_id
};
// Send credentials to user via secure channel
sendCredentialsToUser(credentials);
} catch (error) {
console.error('User creation failed:', error.message);
if (error.message.includes('Email is already registered')) {
console.error('Email conflict under this client');
} else if (error.message.includes('Client not found')) {
console.error('Invalid client_id provided');
}
}
Features
- Automatic eKYC Approval: User gets APPROVED status immediately
- Password Generation: Temporary password format
User{timestamp}! - Email Notification: Welcome email sent automatically
- Xendit Integration: Auto-create Xendit customer for Indonesia users
- Activity Logging: Admin action logged for audit trail
- Validation: Client existence and email uniqueness checked
HTTP Endpoint
- Method:
POST - URL:
https://api.brdz.link/api/admins/users - Headers:
Authorization: Bearer <JWT_TOKEN>,x-api-keyrequired
getListAdmin
Retrieve list of all admin users with their KYC verification status.
Syntax
const result = await admin.getListAdmin(params);
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
params | object | ❌ | Query parameters (currently not used) |
Returns
Promise<{
admins: Array<{
user_id: number;
username: string;
email: string;
user_status: string;
kyc_status: string;
}>;
}>
Example
try {
const adminList = await admin.getListAdmin();
console.log('Total admins:', adminList.admins.length);
adminList.admins.forEach(admin => {
console.log(`Admin: ${admin.username} (${admin.email})`);
console.log(`Status: ${admin.user_status}, KYC: ${admin.kyc_status}`);
console.log('---');
});
// Filter active admins
const activeAdmins = adminList.admins.filter(admin =>
admin.user_status === 'ACTIVE'
);
// Filter admins needing KYC approval
const pendingKyc = adminList.admins.filter(admin =>
admin.kyc_status === 'PENDING'
);
console.log(`Active admins: ${activeAdmins.length}`);
console.log(`Pending KYC: ${pendingKyc.length}`);
} catch (error) {
console.error('Failed to get admin list:', error.message);
}
Database Query
The method executes this SQL query:
SELECT u.user_id, u.username, u.email, u.user_status,
COALESCE(e.ekyc_status, 'PENDING') AS kyc_status
FROM users u
LEFT JOIN ekyc_info e ON u.user_id = e.user_id
WHERE u.role = 'admin'
ORDER BY u.user_id DESC;
HTTP Endpoint
- Method:
GET - URL:
https://api.brdz.link/api/admins/list - Headers:
Authorization: Bearer <JWT_TOKEN>,x-api-keyrequired
approveUserKYC
Approve user's KYC status manually as admin. Updates eKYC status to APPROVED and activates user account. Includes Xendit status sync for Indonesia users.
Syntax
const result = await admin.approveUserKYC(userId);
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
userId | string | ✅ | User ID to approve KYC for |
Returns
Promise<{
message: string;
user: {
user_id: number;
username: string;
email: string;
ekyc_status: string;
user_status: string;
};
xendit_info?: {
country_code: string;
psp_provider: string;
kyc_approved_in_brdz: boolean;
};
}>
Example
try {
const userId = '123';
const approval = await admin.approveUserKYC(userId);
console.log('Approval message:', approval.message);
console.log('User:', approval.user.username);
console.log('KYC Status:', approval.user.ekyc_status);
console.log('User Status:', approval.user.user_status);
// Check Xendit integration info
if (approval.xendit_info) {
console.log('Country:', approval.xendit_info.country_code);
console.log('PSP Provider:', approval.xendit_info.psp_provider);
console.log('KYC Approved in BRDZ:', approval.xendit_info.kyc_approved_in_brdz);
}
// Log successful approval
console.log(`KYC approved for user ${approval.user.email}`);
// Notify user of approval
notifyUserKycApproved(approval.user);
} catch (error) {
console.error('KYC approval failed:', error.message);
if (error.message.includes('User not Found')) {
console.error('Invalid user ID or user cannot be approved');
}
}
Database Operations
- Update eKYC Status: Sets
ekyc_status = 'APPROVED' - Activate User: Sets
user_status = 'ACTIVE' - Timestamp: Records
ekyc_verified_at = CURRENT_TIMESTAMP - Activity Log: Logs admin approval action
- Xendit Sync: Updates customer status for Indonesia users
HTTP Endpoint
- Method:
POST - URL:
https://api.brdz.link/api/admins/approve-kyc/:userId - Headers:
Authorization: Bearer <JWT_TOKEN>,x-api-keyrequired
getUserDetails
Get detailed user information including client data, eKYC status, and Xendit integration info (for Indonesia users). Provides comprehensive user profile for admin management.
Syntax
const result = await admin.getUserDetails(userId);
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
userId | string | ✅ | User ID to get details for |
Returns
Promise<{
user: {
user_id: number;
username: string;
email: string;
phone: string;
role: string;
user_status: string;
created: string;
updated: string;
client_id: number;
client_alias: string;
client_type: string;
country_code: string;
client_code: string;
ekyc_status: string;
ekyc_verified_at: string | null;
};
xendit_integration: {
country_code: string;
psp_provider: string;
customer_info: {
xendit_customer_id: string;
customer_type: string;
status: string;
created_at: string;
} | null;
} | null;
}>
Example
try {
const userId = '123';
const userDetails = await admin.getUserDetails(userId);
const user = userDetails.user;
console.log('User Info:');
console.log(`- Username: ${user.username}`);
console.log(`- Email: ${user.email}`);
console.log(`- Phone: ${user.phone}`);
console.log(`- Role: ${user.role}`);
console.log(`- Status: ${user.user_status}`);
console.log(`- eKYC: ${user.ekyc_status}`);
console.log('\nClient Info:');
console.log(`- Client: ${user.client_alias} (${user.client_code})`);
console.log(`- Type: ${user.client_type}`);
console.log(`- Country: ${user.country_code}`);
// Check Xendit integration for Indonesia users
const xendit = userDetails.xendit_integration;
if (xendit) {
console.log('\nXendit Integration:');
console.log(`- Provider: ${xendit.psp_provider}`);
console.log(`- Country: ${xendit.country_code}`);
if (xendit.customer_info) {
const customer = xendit.customer_info;
console.log(`- Customer ID: ${customer.xendit_customer_id}`);
console.log(`- Customer Type: ${customer.customer_type}`);
console.log(`- Status: ${customer.status}`);
console.log(`- Created: ${customer.created_at}`);
} else {
console.log('- Customer: Not created yet');
}
} else {
console.log('\nXendit Integration: Not available (non-Indonesia user)');
}
// Use data for admin dashboard
displayUserProfile(userDetails);
} catch (error) {
console.error('Failed to get user details:', error.message);
if (error.message.includes('User not found')) {
console.error('Invalid user ID provided');
}
}
Use Cases
- Admin Dashboard: Display complete user profiles
- User Management: View all user information in one call
- Xendit Monitoring: Check Indonesia users' Xendit integration status
- KYC Management: View eKYC status and verification timestamps
- Client Relationship: See user-client associations and details
Database Operations
The method executes these queries:
- User Details Query:
SELECT u.user_id, u.username, u.email, u.phone, u.role, u.user_status, u.created, u.updated,
c.client_id, c.client_alias, c.client_type, c.country_code, c.client_code,
e.ekyc_status, e.ekyc_verified_at
FROM users u
LEFT JOIN clients c ON u.client_id = c.client_id
LEFT JOIN ekyc_info e ON u.user_id = e.user_id
WHERE u.user_id = $1
- Xendit Customer Query (for Indonesia users):
SELECT xendit_customer_id, customer_type, status, created_at
FROM xendit_customers
WHERE user_id = $1
HTTP Endpoint
- Method:
GET - URL:
https://api.brdz.link/api/admins/users/:userId - Headers:
Authorization: Bearer <JWT_TOKEN>,x-api-keyrequired
Complete Admin Management Example
Admin Dashboard Implementation
class AdminManager {
constructor(sdk) {
this.sdk = sdk;
}
async getDashboardData() {
const admin = await this.sdk.admin;
try {
// Get all admins with their status
const adminList = await admin.getListAdmin();
// Calculate statistics
const stats = this.calculateAdminStats(adminList.admins);
return {
admins: adminList.admins,
stats
};
} catch (error) {
throw new Error(`Failed to load dashboard: ${error.message}`);
}
}
async createNewUser(userData) {
const admin = await this.sdk.admin;
try {
// Validate required fields
this.validateUserData(userData);
// Create user via admin
const result = await admin.createUserByAdmin(userData);
// Log successful creation
console.log(`New user created: ${result.user.username}`);
// Return user info (without password in logs)
return {
user: result.user,
hasTemporaryPassword: true,
hasXenditIntegration: !!result.xendit_integration,
message: result.message
};
} catch (error) {
throw new Error(`User creation failed: ${error.message}`);
}
}
async approveKYC(userId) {
const admin = await this.sdk.admin;
try {
const approval = await admin.approveUserKYC(userId);
console.log(`KYC approved for user ${approval.user.username}`);
return approval;
} catch (error) {
throw new Error(`KYC approval failed: ${error.message}`);
}
}
async getUserProfile(userId) {
const admin = await this.sdk.admin;
try {
const userDetails = await admin.getUserDetails(userId);
// Format for display
return {
profile: userDetails.user,
xenditInfo: userDetails.xendit_integration,
hasXenditIntegration: !!userDetails.xendit_integration?.customer_info,
isIndonesianUser: userDetails.user.country_code === 'ID'
};
} catch (error) {
throw new Error(`Failed to get user profile: ${error.message}`);
}
}
async bulkApproveKYC(userIds) {
const results = [];
for (const userId of userIds) {
try {
const approval = await this.approveKYC(userId);
results.push({ userId, success: true, data: approval });
} catch (error) {
results.push({ userId, success: false, error: error.message });
}
}
return results;
}
// Utility methods
calculateAdminStats(admins) {
return {
total: admins.length,
active: admins.filter(a => a.user_status === 'ACTIVE').length,
pendingKyc: admins.filter(a => a.kyc_status === 'PENDING').length,
approvedKyc: admins.filter(a => a.kyc_status === 'APPROVED').length
};
}
validateUserData(userData) {
const required = ['client_id', 'username', 'email', 'phone', 'country_code'];
for (const field of required) {
if (!userData[field]) {
throw new Error(`${field} is required`);
}
}
// Email format validation
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(userData.email)) {
throw new Error('Invalid email format');
}
// Phone format validation
if (!userData.phone.startsWith('+')) {
throw new Error('Phone must include country code with +');
}
}
}
// Usage Example
const adminManager = new AdminManager(brdzSDK);
// Load admin dashboard
adminManager.getDashboardData()
.then(dashboard => {
console.log('Admin Stats:', dashboard.stats);
console.log('Admin List:', dashboard.admins);
})
.catch(error => {
console.error('Dashboard load failed:', error.message);
});
// Create new user
const newUserData = {
client_id: 1,
username: 'testuser',
email: 'test@example.com',
phone: '+628123456789',
country_code: 'ID',
role: 'user'
};
adminManager.createNewUser(newUserData)
.then(result => {
console.log('User created successfully:', result.user.username);
if (result.hasXenditIntegration) {
console.log('Xendit customer created automatically');
}
})
.catch(error => {
console.error('User creation failed:', error.message);
});
// Get user profile
adminManager.getUserProfile('123')
.then(profile => {
console.log('User Profile:', profile.profile.username);
console.log('Client:', profile.profile.client_alias);
console.log('Has Xendit:', profile.hasXenditIntegration);
})
.catch(error => {
console.error('Failed to get profile:', error.message);
});
// Approve KYC
adminManager.approveKYC('123')
.then(approval => {
console.log('KYC approved:', approval.user.username);
})
.catch(error => {
console.error('KYC approval failed:', error.message);
});
Batch Operations Example
// Batch create users with Xendit integration tracking
async function batchCreateUsers(userList) {
const admin = await brdzSDK.admin;
const results = [];
for (const userData of userList) {
try {
const result = await admin.createUserByAdmin(userData);
results.push({
email: userData.email,
success: true,
userId: result.user.user_id,
tempPassword: result.temp_password,
hasXenditIntegration: !!result.xendit_integration,
xenditCustomerId: result.xendit_integration?.customer_id || null
});
} catch (error) {
results.push({
email: userData.email,
success: false,
error: error.message
});
}
}
return results;
}
// Batch get user details
async function batchGetUserDetails(userIds) {
const admin = await brdzSDK.admin;
const results = [];
for (const userId of userIds) {
try {
const details = await admin.getUserDetails(userId);
results.push({
userId,
success: true,
user: details.user,
hasXenditIntegration: !!details.xendit_integration?.customer_info
});
} catch (error) {
results.push({
userId,
success: false,
error: error.message
});
}
}
return results;
}
// Monitor Xendit integration status
async function checkXenditIntegrationStatus(userIds) {
const admin = await brdzSDK.admin;
const results = [];
for (const userId of userIds) {
try {
const details = await admin.getUserDetails(userId);
if (details.user.country_code === 'ID') {
results.push({
userId,
username: details.user.username,
email: details.user.email,
xenditStatus: details.xendit_integration?.customer_info ? 'INTEGRATED' : 'PENDING',
customerId: details.xendit_integration?.customer_info?.xendit_customer_id || null,
customerType: details.xendit_integration?.customer_info?.customer_type || null
});
}
} catch (error) {
results.push({
userId,
xenditStatus: 'ERROR',
error: error.message
});
}
}
return results;
}
Security Features
Access Control
- Admin Role Required: All methods require authenticated admin user
- JWT Token Validation: Bearer token required for all requests
- API Key Required: x-api-key header mandatory
Password Security
- bcrypt Encryption: Passwords encrypted with
crypt()andgen_salt('bf') - Temporary Password: Format
User{timestamp}!ensures uniqueness - Email Delivery: Passwords sent via secure email service
Audit Trail
- Activity Logging: All admin actions logged to
user_activity_logstable - Detailed Tracking: Action type, description, and timestamp recorded
- Admin Identification: Admin user ID tracked for all operations
Xendit Security
- PSP Service Integration: Secure Xendit customer creation via
pspService - Country Validation: Xendit integration only for Indonesia (ID) users
- Error Handling: Xendit failures don't prevent user creation
- Status Tracking: Customer status tracked in local database
Error Handling
Common Errors
| Error | Description | Solution |
|---|---|---|
400: All fields are required | Missing required parameters | Provide all mandatory fields |
400: Email is already registered | Duplicate email under client | Use different email address |
404: Client not found | Invalid client_id | Verify client exists |
404: User not Found | Invalid user_id for operations | Check user ID exists |
500: Database error | Server-side issues | Retry or contact support |
Error Handling Pattern
try {
const result = await admin.createUserByAdmin(userData);
// Handle success
} catch (error) {
if (error.message.includes('All fields are required')) {
// Handle validation error
showFieldValidationErrors();
} else if (error.message.includes('Email is already registered')) {
// Handle duplicate email
showEmailConflictError();
} else if (error.message.includes('Client not found')) {
// Handle invalid client
showClientNotFoundError();
} else if (error.message.includes('User not found')) {
// Handle invalid user ID
showUserNotFoundError();
} else {
// Handle generic error
showGenericError(error.message);
}
}
Integration Notes
Email Service Integration
- Uses
emailService.sendEmail()for welcome emails - HTML template includes temporary password
- Email sent automatically on user creation
Database Integration
- users table: Main user data storage
- ekyc_info table: KYC status management
- user_activity_logs table: Audit trail logging
- xendit_customers table: Xendit customer data (Indonesia users)
- xendit_accounts table: Xendit account information
KYC Workflow
- Admin-created users get automatic APPROVED eKYC status
- Manual KYC approval available for existing users
- Activity logging for all KYC operations
- Xendit status sync for Indonesia users
Xendit Integration
- Auto-Creation: Indonesia users automatically get Xendit customer account
- PSP Integration: Uses
pspService.getPspUser()for customer creation - Account Management: Links to
xendit_accountsfor balance tracking - Status Sync: KYC approval updates Xendit customer status
Use getListAdmin() and getUserDetails() to build comprehensive admin management dashboards with complete user information.
Temporary passwords are sent via email. Users should change passwords on first login.
Admin-created users automatically receive APPROVED eKYC status, bypassing standard verification.
Indonesia users (country_code: 'ID') automatically get Xendit customer accounts created through PSP service integration.