Risk & Fraud
Part of AfriHex Verify — layers that keep lending decisions honest: real-time fraud detection on every verification, portfolio-level risk analytics, AML/PEP sanctions screening, and hex-level usage analytics.
Fraud detection
Fraud checks run automatically inside KYC and
Proximity verification. Results surface as a fraud_check
block:
{
"fraud_check": {
"blocked": false,
"risk_score": 0.12,
"risk_level": "low",
"signals": [
{ "type": "ip_geo_match", "severity": "low", "description": "IP country matches address country", "score": 0.05 }
],
"recommendation": "Approve transaction",
"degraded": false,
"degraded_checks": []
}
}
degraded: true means one or more sub-checks (velocity, IP-bulk,
device-bulk, synthetic-identity) couldn't run — e.g. a transient DB error —
so risk_score reflects fewer signals than usual. Those sub-checks fail
open by design (a blip degrades the check, it doesn't block the
verification), so treat a degraded result as "we don't fully know," not as
"nothing suspicious." degraded_checks names which ones were skipped.
Signals include:
- GPS spoofing — implausible coordinates for the device's IP location.
- VPN / proxy detection — traffic from known anonymising endpoints.
- Velocity abuse — implausible request rates or geo-impossible travel between consecutive events.
- Mock location — device reports
is_mock_location: true(proximity flow).
risk_level is low | medium | high | critical; blocked is true only for
critical signals. High-risk verifications persist a fraud alert for review
(admin: GET /v2/admin/fraud/alerts).
Portfolio risk
POST /v2/analytics/portfolio-risk requires Banking Suite
access. Send your loan book (up to
10,000 loans per request) and get it bucketed into hex zones with exposure
and delinquency rate per zone:
curl -X POST "https://api.afrihex.com/v2/analytics/portfolio-risk" \
-H "X-API-Key: $AFRIHEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"loans": [
{ "loan_id": "loan_456", "lat": 5.603, "lng": -0.187, "amount": 50000, "status": "performing" },
{ "loan_id": "loan_789", "lat": 5.614, "lng": -0.205, "amount": 30000, "status": "delinquent" }
]
}'
{
"success": true,
"data": {
"total_loans": 2,
"hex_zones": [
{
"hex_code": "AF-GH-7-0GXTQD5RFZZZZ",
"loan_count": 1,
"total_exposure": 50000,
"delinquency_rate": 0.0,
"risk_level": "low"
},
{
"hex_code": "AF-GH-7-0GXTQDJJB0ZZZ",
"loan_count": 1,
"total_exposure": 30000,
"delinquency_rate": 1.0,
"risk_level": "high"
}
]
}
}
status is one of performing, delinquent, or default — the last two
count toward a zone's delinquency rate. risk_level is low (< 10%
delinquent), medium (10–25%), or high (≥ 25%). Use it to triage: where is
risk concentrated geographically, not just which individual loans are late.
AML / PEP screening
:::warning In progress — PEP coverage incomplete AML screening is being built out. The sanctions index is live (≈292k entities, including UN, EU, and US OFAC lists), but the full PEP / legislator collection is not yet loaded — the data server currently lacks the resources to index the entire OpenSanctions dataset — so screening may miss politically exposed persons. Treat any output as a work-in-progress signal, not a complete compliance check, and don't use it as the sole basis for a regulatory decision. We're working on bringing the full dataset online. :::
POST /v2/aml/screen screens a name against a self-hosted OpenSanctions
dataset (sanctions + politically exposed persons). Advisory by design — results
flag for manual review, they don't auto-block:
curl -X POST "https://api.afrihex.com/v2/aml/screen" \
-H "X-API-Key: $AFRIHEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "full_name": "Kofi Mensah", "customer_id": "cust_123" }'
{
"success": true,
"data": {
"screening_id": "c30725ca-…",
"status": "clear",
"top_score": 0
}
}
Review outcomes with POST /v2/aml/screenings/{id}/review, and list past
screenings with GET /v2/aml/screenings.
Hex analytics
Understand where traffic comes from:
GET /v2/analytics/hotspots— busiest hex cells over time:
{
"success": true,
"data": {
"resolution": 7,
"days": 30,
"count": 20,
"cells": [
{
"h3_index": "877576973ffffff",
"resolution": 7,
"center": { "lat": 5.587652594702177, "lng": -0.2021282623530355 },
"request_count": 433,
"first_seen": "2026-04-26 12:44:42",
"last_seen": "2026-07-31 15:59:25"
}
]
}
}
GET /v2/analytics/heatmap?bbox=...&res=7— request-density heatmap (bbox formatnorth,south,east,west).GET /v2/analytics/cell/{h3index}— stats for a single cell.GET /v2/analytics/poi-density— point-of-interest density in a bounding box.
Compliance notes
- Every score here is advisory, not a decision.
risk_score,risk_level,degraded, and AMLstatusare signals to combine with your own policy — not a system that itself approves, denies, or flags a customer. Route anything ambiguous, or anything that would trigger an adverse action, to a human reviewer. - A location signal is location evidence, not proof. A fraud or risk score is never guaranteed proof of identity, ownership, residence, creditworthiness, or legality — see Understanding Confidence and Verification for the same principle applied across every AfriHex verification endpoint.
- Don't use geographic risk concentration as a proxy for who someone is.
POST /v2/analytics/portfolio-riskbuckets loan performance by hex zone to help you triage collections effort — it says nothing about the people who live in a zone, and using zone-level delinquency to infer creditworthiness, identity, or eligibility for an individual applicant who hasn't yet transacted is exactly the kind of geographic proxy discrimination (redlining) that fair-lending regulation exists to prevent. Use it for operational triage on your existing portfolio, not as an input to new underwriting decisions. - AML/PEP coverage is partial today — see the warning under AML / PEP
screening above. A
clearresult is not a complete compliance check.
API reference
See Risk & Fraud — API Reference for every endpoint in this group.