Skip to main content

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 format north,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 AML status are 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-risk buckets 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 clear result is not a complete compliance check.

API reference​

See Risk & Fraud — API Reference for every endpoint in this group.