Skip to main content

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

MethodDescriptionAuth RequiredHTTP Endpoint
createUserByAdminCreate user as adminPOST /admins/users
getListAdminGet admin listGET /admins/list
approveUserKYCApprove user KYCPOST /admins/approve-kyc/:userId
getUserDetailsGet user detailsGET /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

ParameterTypeRequiredDescription
userDataobjectUser creation data
userData.client_idnumberClient ID to associate user with
userData.usernamestringUsername for the new user
userData.emailstringEmail address for the new user
userData.phonestringPhone number for the new user
userData.country_codestringCountry code for eKYC entry
userData.rolestringUser role (default: 'user')
userData.is_wishlistbooleanWishlist 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-key required

getListAdmin

Retrieve list of all admin users with their KYC verification status.

Syntax

const result = await admin.getListAdmin(params);

Parameters

ParameterTypeRequiredDescription
paramsobjectQuery 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-key required

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

ParameterTypeRequiredDescription
userIdstringUser 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

  1. Update eKYC Status: Sets ekyc_status = 'APPROVED'
  2. Activate User: Sets user_status = 'ACTIVE'
  3. Timestamp: Records ekyc_verified_at = CURRENT_TIMESTAMP
  4. Activity Log: Logs admin approval action
  5. 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-key required

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

ParameterTypeRequiredDescription
userIdstringUser 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:

  1. 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
  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-key required

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() and gen_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_logs table
  • 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

ErrorDescriptionSolution
400: All fields are requiredMissing required parametersProvide all mandatory fields
400: Email is already registeredDuplicate email under clientUse different email address
404: Client not foundInvalid client_idVerify client exists
404: User not FoundInvalid user_id for operationsCheck user ID exists
500: Database errorServer-side issuesRetry 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_accounts for balance tracking
  • Status Sync: KYC approval updates Xendit customer status

Admin Dashboard

Use getListAdmin() and getUserDetails() to build comprehensive admin management dashboards with complete user information.

Password Security

Temporary passwords are sent via email. Users should change passwords on first login.

Auto-Approval

Admin-created users automatically receive APPROVED eKYC status, bypassing standard verification.

Xendit Integration

Indonesia users (country_code: 'ID') automatically get Xendit customer accounts created through PSP service integration.