Skip to content

Risk Scoring API

API endpoints for managing customer risk profiles, risk score calculation, and transaction limits.

Base URL

/admin/aml

Endpoints

Get Customer Risk Profile

Retrieves the risk profile and score history for a customer.

http
GET /admin/aml/customers/:userId/risk-profile

Path Parameters:

ParameterTypeDescription
userIdstringUser UUID

Response:

json
{
  "success": true,
  "message": "Risk profile retrieved successfully",
  "data": {
    "profile": {
      "id": "profile-123",
      "userId": "user-uuid-123",
      "riskScore": 25,
      "riskRating": "LOW",
      "riskFactors": {
        "geographicRisk": 10,
        "transactionVolume": 20,
        "transactionFrequency": 15,
        "productRisk": 5,
        "verificationStatus": 0,
        "pepStatus": 0,
        "alertHistory": 5
      },
      "transactionLimits": {
        "dailyLimit": 50000,
        "weeklyLimit": 200000,
        "monthlyLimit": 500000,
        "singleTransactionLimit": 25000,
        "dailyUsed": 5000,
        "weeklyUsed": 15000,
        "monthlyUsed": 45000
      },
      "manualOverride": null,
      "lastCalculatedAt": "2026-01-20T10:00:00Z",
      "user": {
        "id": "user-uuid-123",
        "firstName": "John",
        "lastName": "Doe",
        "email": "john@example.com",
        "phoneNumber": "+26878123456"
      }
    },
    "history": [
      {
        "id": "history-1",
        "riskScore": 25,
        "riskRating": "LOW",
        "changeReason": "Scheduled recalculation",
        "createdAt": "2026-01-20T10:00:00Z"
      },
      {
        "id": "history-2",
        "riskScore": 30,
        "riskRating": "MEDIUM",
        "changeReason": "Alert resolved",
        "createdAt": "2026-01-15T10:00:00Z"
      }
    ]
  }
}

Recalculate Risk Score

Triggers a risk score recalculation for a specific user.

http
POST /admin/aml/customers/:userId/recalculate-risk

Path Parameters:

ParameterTypeDescription
userIdstringUser UUID

Response:

json
{
  "success": true,
  "message": "Risk score recalculated successfully",
  "data": {
    "id": "profile-123",
    "userId": "user-uuid-123",
    "riskScore": 28,
    "riskRating": "MEDIUM",
    "riskFactors": {
      "geographicRisk": 10,
      "transactionVolume": 25,
      "transactionFrequency": 18,
      "productRisk": 5,
      "verificationStatus": 0,
      "pepStatus": 0,
      "alertHistory": 8
    },
    "transactionLimits": {
      "dailyLimit": 25000,
      "weeklyLimit": 100000,
      "monthlyLimit": 250000,
      "singleTransactionLimit": 10000
    },
    "lastCalculatedAt": "2026-01-20T14:30:00Z"
  }
}

Bulk Recalculate All Risk Scores

Recalculates risk scores for all users in the system. Processes users in batches of 100.

http
POST /admin/aml/recalculate-all-risk-scores

Response:

json
{
  "success": true,
  "message": "Risk score recalculation completed: 4985 updated, 15 failed",
  "data": {
    "totalUsers": 5000,
    "updated": 4985,
    "failed": 15,
    "errors": [
      "User user-123: Profile not found",
      "User user-456: Transaction data unavailable"
    ]
  }
}

Risk Score Calculation

Score Ranges

Score RangeRisk RatingDescription
0-25LOWMinimal risk indicators
26-50MEDIUMSome risk indicators present
51-75MEDIUM_HIGHElevated risk requiring monitoring
76-100HIGHHigh risk requiring enhanced due diligence

Risk Categories (Weights)

CategoryWeightDescription
Geographic Risk15%Country and region risk factors
Transaction Volume20%Total transaction amounts
Transaction Frequency15%Number of transactions per period
Product Risk10%Types of products/services used
Verification Status15%KYC verification completeness
PEP Status15%Politically Exposed Person match
Alert History10%Previous AML alert count

Transaction Limits by Risk Rating

Risk RatingDaily LimitWeekly LimitMonthly LimitSingle Transaction
LOWE50,000E200,000E500,000E25,000
MEDIUME25,000E100,000E250,000E10,000
MEDIUM_HIGHE10,000E40,000E100,000E5,000
HIGHE2,500E10,000E25,000E1,000

TypeScript Types

typescript
interface CustomerRiskProfile {
  id: string;
  userId: string;
  riskScore: number;
  riskRating: RiskRating;
  riskFactors: RiskFactors;
  transactionLimits: TransactionLimits;
  manualOverride: ManualOverride | null;
  lastCalculatedAt: Date;
  user: {
    id: string;
    firstName: string;
    lastName: string;
    email: string;
    phoneNumber: string;
  };
}

type RiskRating = 'LOW' | 'MEDIUM' | 'MEDIUM_HIGH' | 'HIGH';

interface RiskFactors {
  geographicRisk: number;
  transactionVolume: number;
  transactionFrequency: number;
  productRisk: number;
  verificationStatus: number;
  pepStatus: number;
  alertHistory: number;
}

interface TransactionLimits {
  dailyLimit: number;
  weeklyLimit: number;
  monthlyLimit: number;
  singleTransactionLimit: number;
  dailyUsed?: number;
  weeklyUsed?: number;
  monthlyUsed?: number;
}

interface RiskScoreHistory {
  id: string;
  entityUserId: string;
  entityType: string;
  riskScore: number;
  riskRating: RiskRating;
  changeReason: string | null;
  createdAt: Date;
}

interface ManualOverride {
  rating: RiskRating;
  setBy: string;
  setAt: Date;
  reason: string;
}

Error Responses

Profile Not Found

json
{
  "success": false,
  "message": "Risk profile not found",
  "statusCode": 404
}

User ID Required

json
{
  "success": false,
  "message": "User ID is required",
  "statusCode": 400
}

Code Examples

Recalculate Single User Risk Score

typescript
import axios from 'axios';

async function recalculateUserRisk(userId: string) {
  const response = await axios.post(
    `/admin/aml/customers/${userId}/recalculate-risk`,
    {},
    {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    }
  );

  return response.data;
}

// Usage
const result = await recalculateUserRisk('user-uuid-123');
console.log(`New risk score: ${result.data.riskScore}`);
console.log(`New risk rating: ${result.data.riskRating}`);

Bulk Recalculate All Users

typescript
async function bulkRecalculateRiskScores() {
  const response = await axios.post(
    '/admin/aml/recalculate-all-risk-scores',
    {},
    {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    }
  );

  const { updated, failed, errors } = response.data.data;

  console.log(`Updated: ${updated}, Failed: ${failed}`);

  if (errors.length > 0) {
    console.log('Errors:', errors);
  }
}

Get Risk Profile with History

typescript
async function getRiskProfile(userId: string) {
  const response = await axios.get(
    `/admin/aml/customers/${userId}/risk-profile`,
    {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    }
  );

  const { profile, history } = response.data.data;

  console.log(`Current Score: ${profile.riskScore}`);
  console.log(`Current Rating: ${profile.riskRating}`);
  console.log(`Risk Factors:`, profile.riskFactors);
  console.log(`Score History (last 5):`, history.slice(0, 5));
}

Internal use only - Keshless Payment Platform