Skip to main content

Risk Scoring

Combine signals from a phone number, email, IP address, device fingerprint, and declared identity into a single risk score from 0–100. Each request returns the contributing factors and an actionable recommendation, so you can automate low-risk approvals and route the rest to manual review.

🚀 Quick Start​

curl -X POST https://api.afriroute.ai/api/v1/identity/risk-score \
-H "Authorization: Bearer $AFRIROUTE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+251911234567",
"email": "[email protected]",
"ip_address": "196.190.1.100",
"device_fingerprint": "fp_abc123"
}'

📡 Endpoint​

Compute Risk Score​

POST /v1/identity/risk-score

Parameters​

FieldTypeRequiredDescription
phone_numberstringNoE.164 number to assess for VoIP/fraud history
emailstringNoEmail to check for validity and domain reputation
ip_addressstringNoIP for geolocation and blacklist checks
device_fingerprintstringNoDevice ID for velocity and known-device checks
customer_infoobjectNoDeclared name/DOB for cross-signal matching

At least one signal is required. More signals produce a more accurate score.

💻 Code Samples​

Node.js
const res = await fetch('https://api.afriroute.ai/api/v1/identity/risk-score', {
method: 'POST',
headers: { 'Authorization': 'Bearer $AFRIROUTE_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({
phone_number: '+251911234567',
email: '[email protected]',
ip_address: '196.190.1.100',
device_fingerprint: 'fp_abc123',
customer_info: { full_name: 'Abebe Kebede', date_of_birth: '1990-05-15' }
})
});
const data = await res.json();
if (data.recommendation === 'proceed') approve();
Python
import requests

res = requests.post(
'https://api.afriroute.ai/api/v1/identity/risk-score',
headers={'Authorization': 'Bearer $AFRIROUTE_API_KEY'},
json={
'phone_number': '+251911234567',
'email': '[email protected]',
'ip_address': '196.190.1.100',
'device_fingerprint': 'fp_abc123'
}
)
print(res.json()['risk_level'], res.json()['recommendation'])

📊 Response​

{
"risk_score": 12,
"risk_level": "low",
"recommendation": "proceed",
"factors": [
{ "factor": "phone_risk", "score": 5, "details": "Real mobile number, known carrier" },
{ "factor": "email_risk", "score": 3, "details": "Valid email, domain age 5 years" },
{ "factor": "geo_risk", "score": 2, "details": "IP matches declared country" },
{ "factor": "device_risk", "score": 2, "details": "Known device, no suspicious activity" }
],
"checks": {
"phone_verified": true,
"email_valid": true,
"ip_blacklisted": false,
"device_known": true,
"velocity_check": "passed",
"name_match": "high_confidence"
}
}

🎯 Score Bands​

ScoreLevelRecommendation
0–20Low ✅proceed — auto-approve
21–50Medium ⚠️review — optional manual review
51–75High 🚨manual_review — require human approval
76–100Very high ❌reject — likely fraud

💡 Best Practices​

  • Pass every signal you have — device fingerprint and IP dramatically improve accuracy.
  • Treat the score as advisory, not a hard gate; combine it with your own business rules.
  • Re-score at key events (signup, first payout, password reset), not just once at onboarding.
  • Store the factors array for audit and dispute resolution.
  • Monitor velocity — a clean device seen across many accounts is a strong fraud signal.

⚠️ Error Handling​

CodeHTTPDescription
NO_SIGNALS_PROVIDED400Request contained no scorable signals
INVALID_IP400ip_address is malformed
INVALID_EMAIL400email is malformed
SCORING_UNAVAILABLE503A scoring subsystem is temporarily degraded

See the error code reference for the full list.


Last Updated: May 2026 | Need help? [email protected]