Risk evaluation
The single most important endpoint in Anti-Fraud Platform. Call it on every onboarding application and every transaction.
/api/evaluateRequest
customerIdstringRequiredlaneenumRequiredorgIdstringsessionTokenstringexternalIdstringamountintegercurrencystring (ISO-4217)dataobjectCommon data fields (transaction lane)
| Field | Notes |
|---|---|
channel | transfer · qris · card · atm · topup · withdrawal |
beneficiaryName | Counterparty name |
beneficiaryAccount | Counterparty bank account / wallet ID |
beneficiaryBank | Bank code (BCA, MANDIRI, …) |
merchantCategory | MCC code for card / QRIS |
ipAddress | Source IP if available |
userAgent | Source UA if available |
Common data fields (onboarding lane)
| Field | Notes |
|---|---|
fullName | As entered by the applicant |
nik | 16-digit Indonesian NIK |
email | As entered |
phone | E.164 format |
dateOfBirth | YYYY-MM-DD |
referralSource | How the user found you |
ipAddress, userAgent | Source signals |
data is intentionally open-ended — rules read whatever fields they reference, so you can pass everything you have.
Response
{
"data": {
"decision": "allow | flag | review | block",
"fraudScore": 0-100,
"subScores": {
"rules": 0-100,
"velocity": 0-100,
"ml": 0-100
},
"appliedRules": [
{
"code": "VL-003",
"name": "High amount unverified counterparty",
"action": "review",
"severity": "high",
"score": 20
}
],
"sessionId": "alt_01HXY..."
},
"ok": true
}fraudScore is the headline figure — a weighted blend of subScores. Use it for downstream analytics; use decision for the actual gate.
Decision logic
┌──────────────┐
│ subScores │
│ rules: R │
│ velocity: V │
│ ml: M │
└──────┬───────┘
▼
fraudScore = weighted(R, V, M) ← weights configurable per-org
│
▼
applied rules' actions are merged.
If a rule with action "block" fires AND its bypass-ML flag is true, decision = "block".
Otherwise:
fraudScore ≥ blockThreshold → block
fraudScore ≥ reviewThreshold → review
fraudScore ≥ flagThreshold → flag
else → allowDefault thresholds: flag 30 · review 50 · block 75. Configurable via dashboard.
ML suppression
Rules can be marked bypassMl: true. These enforce their action regardless of ML confidence — useful for hard regulatory rules (blocked country, blocked NIK).
Non-bypass rules may have their action downgraded when ML confidence is below the org's per-lane mlThresholds:
block → review → flag → allowThis prevents over-blocking when the ML model is uncertain. Disable by setting mlThresholds.onboarding = 0 (never downgrade) or mlThresholds.transaction = 0.
Idempotency
Pass externalId. Within 24 hours, replays return the original decision with data.idempotent: true.
Test mode
For unit-testing without persisting alerts:
/api/test-evaluateAccepts the same body plus an optional scenario:
{
"lane": "onboarding",
"scenario": "clean | medium | high",
"payload": { /* same shape as /api/evaluate */ }
}scenario injects a fake risk score (40 / 60 / 90) to deterministically force a decision path. Useful for testing your downstream handling without depending on actual rules firing.
Latency expectations
Sandbox is configured for low fixed cost, not low latency — expect p95 ~120ms.
Production p95 SLAs:
| Tier | p95 | Use case |
|---|---|---|
| Standard | 80ms | Most banking / lending traffic |
| Premium | 40ms | Real-time payments, QRIS at POS |
| Enterprise | 20ms | Co-located inside your VPC |
Per-tier contracts are in your MSA — talk to sales@quantumelixir.tech if your latency budget is tight.
Don't put evaluate behind a queue
This endpoint is designed to sit on the critical path. Putting it behind an async queue forfeits the most valuable property — actionable risk decision before the transaction commits.