Skip to main content

Transaction Monitoring

Evaluate transactions in real-time against configurable AML rules. When a rule triggers, an alert is created for investigation.

Base URL & authentication

Pick the base URL for your environment:

EnvironmentBase URL
Sandboxhttps://sandbox.korastratum.com/api/v1
Productionhttps://compliance.korastratum.com/api/v1

The examples below use the sandbox host. Authenticate with your API key as Authorization: Bearer YOUR_API_KEY — the key already identifies your workspace, so the X-Tenant-ID header is optional (shown in the examples for completeness; it's ignored when a key is present). Use a sandbox key (sk_sandbox_…) against the sandbox host and a live key against production.

Evaluate a Transaction

Submit a transaction for rule evaluation:

curl -X POST https://sandbox.korastratum.com/api/v1/monitoring/evaluate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-Tenant-ID: YOUR_TENANT_ID" \
-H "Content-Type: application/json" \
-d '{
"transaction_id": "txn_abc123",
"customer_id": "cust_def456",
"transaction_type": "TRANSFER",
"amount": 15000.00,
"currency": "USD",
"direction": "DEBIT",
"channel": "WIRE",
"country": "KY"
}'

Response (a transaction that matched a high-risk-country rule):

{
"composite_score": 60,
"risk_level": "HIGH",
"decision": "REVIEW",
"confidence": 0.6,
"matches": 1,
"layer_scores": {
"rules": {
"score": 60,
"weight": 0.35,
"details": [
{
"Rule": { "code": "HIGH_RISK_GEO", "rule_type": "GEOGRAPHIC", "severity": "CRITICAL" },
"RiskScore": 60,
"RiskFactors": [
{ "code": "HIGH_RISK_COUNTRY", "description": "Transaction involves high-risk jurisdiction: IR", "score": 60 }
]
}
]
}
},
"rule_matches": [ /* same matched-rule objects as layer_scores.rules.details */ ],
"explanation": "Rule engine scored 60. Composite score: 60 (REVIEW)."
}

A transaction with no matches returns "decision": "CLEAR", "matches": 0, and an empty details. risk_level is one of LOW, HIGH, or CRITICAL; decision is CLEAR, REVIEW, or BLOCKED. matches is the number of rules that fired; each matched rule (with its RiskFactors) appears under layer_scores.rules.details and again in the top-level rule_matches array — the Rule object is abbreviated above but is returned in full. explanation is a human-readable summary. Alerts raised by a triggered rule are retrieved separately via GET /monitoring/alerts.

Monitoring Rules

Rules define what triggers an alert. Each rule has a rule_type, its matching parameters, optional conditions that scope which transactions it applies to, a category, and a severity.

List Rules

curl https://sandbox.korastratum.com/api/v1/monitoring/rules \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-Tenant-ID: YOUR_TENANT_ID"

Create a Rule

Rules are typed: you choose a rule_type and supply the matching parameters, rather than composing generic field / operator / value conditions. A THRESHOLD rule that flags cash transactions at or above $10,000:

curl -X POST https://sandbox.korastratum.com/api/v1/monitoring/rules \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-Tenant-ID: YOUR_TENANT_ID" \
-H "Content-Type: application/json" \
-d '{
"code": "LARGE_CASH_10K",
"name": "Large cash transaction",
"description": "Flag cash transactions at or above $10,000",
"rule_type": "THRESHOLD",
"category": "AML",
"severity": "HIGH",
"parameters": {
"amount_threshold": 10000,
"amount_operator": "GTE"
},
"conditions": {
"transaction_types": ["CASH"]
},
"actions": {
"create_alert": true,
"alert_priority": "HIGH"
}
}'

code is a stable identifier, unique per tenant (re-using one returns 409). rule_type is one of THRESHOLD, VELOCITY, PATTERN, GEOGRAPHIC, BEHAVIORAL, NETWORK, SCREENING, BLACKLIST, CHARGEBACK_RATIO, DORMANT_REACTIVATION, NEW_DEVICE, CUSTOM. See the AML Rule Catalog for every type and the typologies each covers. category is one of AML, FRAUD, SANCTIONS, STRUCTURING, TERRORIST_FINANCING, TAX_EVASION, CORRUPTION, OTHER. severity is LOW, MEDIUM, HIGH, or CRITICAL.

Amount operators

Amount comparisons use parameters.amount_operator against parameters.amount_threshold. These are the only comparison operators, and they apply to the amount — there is no generic per-field operator:

OperatorMeaning
GTamount > threshold
GTEamount ≥ threshold (default if omitted)
LTamount < threshold
LTEamount ≤ threshold
EQamount = threshold
No NOT_EQUALS

The engine has no NOT_EQUALS / NEQ operator (nor IN / BETWEEN / CONTAINS). Amount uses the five operators above; everything else is expressed through typed conditions (below).

Conditions (scoping which transactions a rule applies to)

conditions is an object (not an array) that narrows a rule to a subset of transactions. Categorical fields are inclusion lists — the rule applies only when the transaction's value is in the list:

ConditionTypeThe rule applies when…
min_amount / max_amountnumberamount falls within the range
transaction_typeslisttransaction type is in the list — e.g. ["CASH"]
directionslistdirection is in the list — e.g. ["DEBIT"]
auth_statuslistauthorization status is in the list — e.g. ["DECLINED","FAILED"]
currencieslistcurrency is in the list
customer_typeslistcustomer type is in the list
risk_categorieslistcustomer risk category is in the list

Field values. direction is one of CREDIT, DEBIT, or INTERNAL (an outbound payment is a DEBIT). These are the values the engine matches on, so a directions condition must use them.

Expressing “not equal”. Because these are inclusion lists, there is no “not equals”. To exclude a value, list the ones you do want to match (the complement). For example, to apply a rule to every transaction type except CASH, set "transaction_types": ["TRANSFER","WITHDRAWAL","DEPOSIT"] with the types you want covered. To apply a rule to all transaction types, simply omit transaction_types.

Update a Rule

PUT with the same schema as create:

curl -X PUT https://sandbox.korastratum.com/api/v1/monitoring/rules/{rule_id} \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-Tenant-ID: YOUR_TENANT_ID" \
-H "Content-Type: application/json" \
-d '{
"code": "LARGE_CASH_10K",
"name": "Large cash transaction",
"rule_type": "THRESHOLD",
"category": "AML",
"severity": "HIGH",
"parameters": { "amount_threshold": 25000, "amount_operator": "GTE" },
"conditions": { "transaction_types": ["CASH"] },
"actions": { "create_alert": true, "alert_priority": "HIGH" }
}'

Enable / disable a rule (no delete)

Compliance rules are never hard-deleted (audit requirement) — disable or re-enable them instead:

# Disable
curl -X PUT https://sandbox.korastratum.com/api/v1/monitoring/rules/{rule_id}/disable \
-H "Authorization: Bearer YOUR_API_KEY" -H "X-Tenant-ID: YOUR_TENANT_ID"

# Re-enable
curl -X PUT https://sandbox.korastratum.com/api/v1/monitoring/rules/{rule_id}/enable \
-H "Authorization: Bearer YOUR_API_KEY" -H "X-Tenant-ID: YOUR_TENANT_ID"

Quick-Setup Presets

Presets provision a ready-made AML scenario — the rule (and a scenario grouping) with sensible defaults — in a single call, so you don't have to hand-author parameters. POST to the preset endpoint; no request body is required.

curl -X POST https://sandbox.korastratum.com/api/v1/monitoring/scenarios/presets/fan-out \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-Tenant-ID: YOUR_TENANT_ID"

Response:

{
"scenario_code": "FAN_OUT",
"scenario_id": "fd431a12-6aab-4905-986c-f134b6363032",
"rule_ids": ["41c14f43-a708-4da5-9772-c297cc78fcf7"],
"created": ["NETWORK_FAN_OUT", "FAN_OUT"],
"skipped": null
}

The call is idempotent — a code already present for the tenant comes back under skipped instead of created, so re-running never duplicates a rule.

Available presets:

Preset (endpoint suffix)DetectsDefault threshold
merchant-volume-spikeUnusual activity at a merchant (amount spike vs baseline or hourly volume)3σ deviation; $100k/hour
card-testingBIN-attack card testing — repeated declines / high-volume bursts on one card5+ declined in 60s; 10+ in 5min
first-time-beneficiaryTransfers to a counterparty the customer hasn't paid before, gated on amount$500 amount cap
wallet-velocityPer-wallet outbound velocity (compromised-wallet drain)Per preset
dormant-reactivationHigh-value activity from a customer returning after long inactivity100 days inactive + $10,000
new-deviceHigh-value activity from a device not previously seen for the customer$5,000 + device fingerprint
fan-outOne-to-many — one customer sending to many distinct beneficiaries>10 distinct beneficiaries / 24h
beneficiary-fan-inMany-to-one — many distinct customers funnelling into one beneficiary>10 distinct senders / 24h
Presets are created disabled

A preset provisions its rule disabled so you can review the thresholds first. Turn it on with the enable endpoint (or the sandbox dashboard). Adjust any default with Update a Rule — see Tuning a preset's thresholds below.

Tuning a preset's thresholds

Every numeric default is editable from the API. Fetch the rule (GET /monitoring/rules/{rule_id}) to see its current parameters, then PUT the rule back with the numbers you want. parameters is replaced wholesale, not merged — send the complete object, including non-numeric fields like pattern_type, so they aren't dropped. For example, to make the fan-out rule fire at >15 distinct beneficiaries over a 12-hour window:

curl -X PUT https://sandbox.korastratum.com/api/v1/monitoring/rules/{rule_id} \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-Tenant-ID: YOUR_TENANT_ID" \
-H "Content-Type: application/json" \
-d '{
"parameters": {
"pattern_type": "FAN_OUT",
"count_threshold": 15,
"time_window_minutes": 720
}
}'

Manage Alerts

List Alerts

# List all new alerts
curl "https://sandbox.korastratum.com/api/v1/monitoring/alerts?status=NEW" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-Tenant-ID: YOUR_TENANT_ID"

# List high-severity alerts
curl "https://sandbox.korastratum.com/api/v1/monitoring/alerts?severity=HIGH" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-Tenant-ID: YOUR_TENANT_ID"

Get Alert Details

curl https://sandbox.korastratum.com/api/v1/monitoring/alerts/alt_abc123 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-Tenant-ID: YOUR_TENANT_ID"

Dispose an Alert

curl -X PUT https://sandbox.korastratum.com/api/v1/monitoring/alerts/alt_abc123/disposition \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-Tenant-ID: YOUR_TENANT_ID" \
-H "Content-Type: application/json" \
-d '{
"disposition": "TRUE_POSITIVE",
"reason": "Suspicious pattern confirmed — filing SAR"
}'

Alert statuses:

StatusDescription
NEWAlert just created
UNDER_REVIEWBeing investigated
ESCALATEDEscalated to senior reviewer
CLOSEDResolved with disposition

Common Rule Patterns

Structuring Detection

Flag repeated transactions just below the reporting threshold — a PATTERN rule:

{
"code": "STRUCTURING_JUST_BELOW_10K",
"name": "Potential structuring",
"description": "3+ transactions just below $10,000 within 24 hours",
"rule_type": "PATTERN",
"category": "STRUCTURING",
"severity": "HIGH",
"parameters": {
"pattern_type": "STRUCTURING",
"just_below_amount": 10000,
"count_threshold": 3,
"time_window_minutes": 1440
},
"actions": { "create_alert": true, "alert_priority": "HIGH" }
}

High-Risk Jurisdiction

Flag outbound transactions to sanctioned countries — a GEOGRAPHIC rule (the country list lives in parameters, and conditions.directions scopes it to outbound):

{
"code": "SANCTIONED_JURISDICTION_OUT",
"name": "High-risk jurisdiction transfer",
"rule_type": "GEOGRAPHIC",
"category": "SANCTIONS",
"severity": "CRITICAL",
"parameters": {
"sanctioned_countries": ["IR", "KP", "SY", "CU"]
},
"conditions": { "directions": ["DEBIT"] },
"actions": { "create_alert": true, "alert_priority": "CRITICAL" }
}

Unusual Amount

Flag large transfers/withdrawals — a THRESHOLD rule scoped by transaction_types:

{
"code": "UNUSUAL_LARGE_AMOUNT",
"name": "Unusual transaction amount",
"rule_type": "THRESHOLD",
"category": "AML",
"severity": "MEDIUM",
"parameters": { "amount_threshold": 50000, "amount_operator": "GTE" },
"conditions": { "transaction_types": ["TRANSFER", "WITHDRAWAL"] },
"actions": { "create_alert": true, "alert_priority": "MEDIUM" }
}

Network — One-to-Many (Fan-Out)

Flag a single customer distributing funds across many distinct beneficiaries in a short window — a NETWORK rule. For network rules, count_threshold counts distinct counterparties (not transaction count), and the rule fires when that count exceeds the threshold. The fastest way to enable this is the fan-out preset; the equivalent explicit rule is:

{
"code": "NETWORK_FAN_OUT",
"name": "One customer to many beneficiaries",
"description": "More than 10 distinct beneficiaries in 24 hours",
"rule_type": "NETWORK",
"category": "AML",
"severity": "HIGH",
"parameters": {
"pattern_type": "FAN_OUT",
"count_threshold": 10,
"time_window_minutes": 1440
},
"actions": { "create_alert": true, "alert_priority": "HIGH" }
}

Network — Many-to-One (Beneficiary Fan-In)

Flag many distinct customers funnelling funds into a single beneficiary account — a mule / funnel-account signal. Same NETWORK type with pattern_type BENEFICIARY_FAN_IN; count_threshold here counts distinct sending customers into one beneficiary. Available as the beneficiary-fan-in preset, or explicitly:

{
"code": "NETWORK_BENEFICIARY_FAN_IN",
"name": "Many customers to one beneficiary",
"description": "More than 10 distinct customers to the same beneficiary in 24 hours",
"rule_type": "NETWORK",
"category": "AML",
"severity": "HIGH",
"parameters": {
"pattern_type": "BENEFICIARY_FAN_IN",
"count_threshold": 10,
"time_window_minutes": 1440
},
"conditions": { "directions": ["DEBIT"] },
"actions": { "create_alert": true, "alert_priority": "HIGH" }
}