Skip to main content

Overview

This guide covers the complete flow for transaction monitoring, from creation through automatic risk analysis and alert generation. Transactions are evaluated against transaction-specific rules to detect suspicious patterns, unusual amounts, high-risk jurisdictions, and other red flags.

Flow Diagram

Step 1: Create Transaction

Transactions are created via the transaction API with automatic currency conversion and optional rule execution. Endpoint: POST /transactions Request:
{
  "externalId": "TXN-2024-00001",
  "type": "TRANSFER",
  "status": "PENDING",
  "amount": 50000,
  "currency": "EUR",
  "paymentMethod": "bank_transfer",
  "originEntityId": "sender-entity-uuid",
  "originName": "John Doe",
  "originCountry": "FR",
  "destinationEntityId": "receiver-entity-uuid",
  "destinationName": "Acme Corporation",
  "destinationCountry": "US",
  "description": "Business payment for services",
  "category": "B2B",
  "transactedAt": "2025-12-24T10:30:00Z",
  "executeRules": true,
  "metadata": {
    "ip": "192.168.1.1",
    "userAgent": "Mozilla/5.0...",
    "sessionId": "sess_abc123"
  }
}
Field Descriptions:
FieldTypeRequiredDescription
externalIdstringYesYour unique identifier for this transaction
typeenumYesTransaction type: PAYMENT, TRANSFER, WITHDRAWAL, DEPOSIT, REFUND, CHARGEBACK, REVERSAL, FEE, ADJUSTMENT, OTHER
statusenumNoTransaction status (default: PENDING)
amountnumberYesTransaction amount in original currency
currencystringYesISO 4217 currency code (e.g., USD, EUR, GBP)
paymentMethodenumNoPayment method used
originEntityIduuidNoSender entity ID (if entity exists in system)
originExternalIdstringNoSender external identifier
originNamestringNoSender name
originCountrystringNoSender country (ISO 3166-1 alpha-2)
destinationEntityIduuidNoReceiver entity ID (if entity exists in system)
destinationExternalIdstringNoReceiver external identifier
destinationNamestringNoReceiver name
destinationCountrystringNoReceiver country (ISO 3166-1 alpha-2)
descriptionstringNoTransaction description
categorystringNoTransaction category
transactedAtdatetimeNoWhen the transaction occurred (default: now)
executeRulesbooleanNoExecute rules automatically (default: true)
metadataobjectNoAdditional custom metadata
What happens automatically:
  1. Currency Conversion:
    • If currency is not USD, converts amount to USD using real-time exchange rates
    • Stores: amountInUsd, exchangeRate, rateSource, rateTimestamp
    • On conversion failure, transaction is still created (without USD amount)
  2. Transaction Creation:
    • Transaction record created in database
    • Unique ID generated
    • Links to origin/destination entities if provided
  3. Automatic Risk Analysis (if executeRules: true):
    • Executes transaction-specific rules
    • Calculates risk score
    • Creates alerts for matched rules
    • Updates transaction status if needed
Response (with risk analysis):
{
  "transaction": {
    "id": "txn-uuid",
    "organizationId": "org-uuid",
    "externalId": "TXN-2024-00001",
    "type": "TRANSFER",
    "status": "PENDING",
    "amount": "50000.00",
    "currency": "EUR",
    "amountInUsd": "54500.00",
    "exchangeRate": "1.09",
    "rateSource": "fixer.io",
    "rateTimestamp": "2025-12-24T10:30:00Z",
    "convertedAt": "2025-12-24T10:30:01Z",
    "originEntityId": "sender-entity-uuid",
    "originName": "John Doe",
    "originCountry": "FR",
    "destinationEntityId": "receiver-entity-uuid",
    "destinationName": "Acme Corporation",
    "destinationCountry": "US",
    "riskScore": "68.00",
    "flagged": true,
    "riskFactors": [
      "Large transaction amount detected",
      "Cross-border transaction to high-risk jurisdiction"
    ],
    "transactedAt": "2025-12-24T10:30:00Z",
    "createdAt": "2025-12-24T10:30:02Z"
  },
  "rulesResult": {
    "success": true,
    "executed": true,
    "result": {
      "entityId": "txn-uuid",
      "entityType": "transaction",
      "riskScore": 68,
      "overallConfidence": 0.95,
      "totalRules": 8,
      "successfulRules": 3,
      "rulesExecuted": [
        {
          "ruleId": "rule-uuid-1",
          "ruleName": "Large Transaction Amount",
          "executed": true,
          "conditionsMet": true,
          "confidence": 0.98,
          "actionsExecuted": [
            {
              "type": "add_risk_score",
              "value": 30
            }
          ]
        },
        {
          "ruleId": "rule-uuid-2",
          "ruleName": "High-Risk Jurisdiction Transfer",
          "executed": true,
          "conditionsMet": true,
          "confidence": 0.92,
          "actionsExecuted": [
            {
              "type": "add_risk_score",
              "value": 38
            },
            {
              "type": "create_alert",
              "result": {
                "alertId": "alert-uuid"
              }
            }
          ]
        }
      ],
      "flags": [
        {
          "type": "LARGE_AMOUNT",
          "severity": "warning",
          "reason": "Transaction amount exceeds $50,000 threshold",
          "confidence": 0.98
        },
        {
          "type": "HIGH_RISK_JURISDICTION",
          "severity": "critical",
          "reason": "Transfer to high-risk jurisdiction",
          "confidence": 0.92
        }
      ]
    },
    "rulesTriggered": 3,
    "executionTimeMs": 850
  }
}

Step 2: Currency Conversion

How Currency Conversion Works

  1. Automatic Conversion: If currency !== 'USD', system automatically converts to USD
  2. Provider: Uses ms-providers service (configured via MS_PROVIDERS_URL)
  3. Caching: Exchange rates cached for 1 minute (TTL)
  4. Resilience: Circuit breaker pattern with fallback to stale cache
  5. Graceful Degradation: If conversion fails, transaction still created (without USD amount)
Conversion Metadata:
{
  "amountInUsd": "54500.00",
  "exchangeRate": "1.09",
  "rateSource": "fixer.io",
  "rateTimestamp": "2025-12-24T10:30:00Z",
  "convertedAt": "2025-12-24T10:30:01Z"
}
USD Transactions:
  • If currency: 'USD', no conversion needed
  • amountInUsd = amount
  • exchangeRate = 1
  • rateSource = 'no-conversion'

Conversion Failure Handling

If currency service is unavailable:
{
  "transaction": {
    "amount": "50000.00",
    "currency": "EUR",
    "amountInUsd": null,
    "exchangeRate": null,
    "rateSource": null
  }
}
Transaction is created successfully, but USD amount is unavailable. Rules that depend on USD amounts will use original amount instead.

Step 3: Transaction Risk Analysis

How Transaction Risk Analysis Works

The RulesExecutionService evaluates transactions using transaction-specific rules:
  1. Context Loading:
    • Loads transaction data
    • Loads linked entities (origin/destination) with enrichment data
    • Prepares execution context
  2. Rule Selection:
    • Filters rules by targetEntityTypes: ['transaction']
    • Filters by trigger: 'created' (for automatic) or 'manual_evaluation'
    • Filters by status: enabled: true and status: 'active'
  3. Rules Execution:
    • Evaluates rule conditions against transaction context
    • Executes actions for matched rules (add score, create alerts, update status)
    • Accumulates risk score
  4. Score Update:
    • Updates transaction riskScore
    • Sets flagged: true if score > 50
    • Stores riskFactors array with reasons
  5. Alert Creation:
    • Rules with create_alert action generate alerts
    • Alerts linked to transaction
    • Alerts consolidated into investigations after 5-second delay

Transaction-Specific Rules Examples

Rule 1: Large Transaction Amount
{
  "name": "Large Transaction Amount",
  "targetEntityTypes": ["transaction"],
  "triggers": ["created"],
  "conditions": {
    "operator": "AND",
    "conditions": [
      {
        "field": "amountInUsd",
        "operator": "greater_than",
        "value": 50000
      }
    ]
  },
  "actions": [
    {
      "type": "add_risk_score",
      "value": 30
    }
  ]
}
Rule 2: High-Risk Jurisdiction Transfer
{
  "name": "High-Risk Jurisdiction Transfer",
  "targetEntityTypes": ["transaction"],
  "triggers": ["created"],
  "conditions": {
    "operator": "OR",
    "conditions": [
      {
        "field": "originCountry",
        "operator": "in_list",
        "value": ["AF", "IR", "KP", "SY"]
      },
      {
        "field": "destinationCountry",
        "operator": "in_list",
        "value": ["AF", "IR", "KP", "SY"]
      }
    ]
  },
  "actions": [
    {
      "type": "add_risk_score",
      "value": 50
    },
    {
      "type": "create_alert",
      "severity": "critical",
      "description": "Transaction involves high-risk jurisdiction"
    }
  ]
}
Rule 3: Rapid Transaction Velocity
{
  "name": "Rapid Transaction Velocity",
  "targetEntityTypes": ["transaction"],
  "triggers": ["created"],
  "conditions": {
    "operator": "AND",
    "conditions": [
      {
        "field": "originEntityId",
        "operator": "historical_count",
        "timeWindow": "1h",
        "comparison": "greater_than",
        "value": 10
      }
    ]
  },
  "actions": [
    {
      "type": "add_risk_score",
      "value": 40
    },
    {
      "type": "create_alert",
      "severity": "warning",
      "description": "Unusual transaction velocity detected"
    }
  ]
}
Rule 4: Sanctioned Entity Transaction
{
  "name": "Sanctioned Entity Transaction",
  "targetEntityTypes": ["transaction"],
  "triggers": ["created"],
  "conditions": {
    "operator": "OR",
    "conditions": [
      {
        "field": "originEntity.enrichment.sanctionsMatch",
        "operator": "equals",
        "value": true
      },
      {
        "field": "destinationEntity.enrichment.sanctionsMatch",
        "operator": "equals",
        "value": true
      }
    ]
  },
  "actions": [
    {
      "type": "add_risk_score",
      "value": 100
    },
    {
      "type": "update_status",
      "status": "blocked"
    },
    {
      "type": "create_alert",
      "severity": "critical",
      "description": "Transaction involves sanctioned entity"
    }
  ]
}

Transaction Context Structure

The rules engine receives this context:
{
  "transaction": {
    "id": "txn-uuid",
    "type": "TRANSFER",
    "amount": 50000,
    "currency": "EUR",
    "amountInUsd": 54500,
    "originEntityId": "sender-uuid",
    "originName": "John Doe",
    "originCountry": "FR",
    "destinationEntityId": "receiver-uuid",
    "destinationName": "Acme Corp",
    "destinationCountry": "US",
    "transactedAt": "2025-12-24T10:30:00Z"
  },
  "originEntity": {
    "id": "sender-uuid",
    "type": "person",
    "name": "John Doe",
    "enrichmentData": {
      "isPep": false,
      "sanctionsMatch": false,
      "riskScore": 25
    }
  },
  "destinationEntity": {
    "id": "receiver-uuid",
    "type": "company",
    "name": "Acme Corp",
    "enrichmentData": {
      "sanctionsMatch": false,
      "riskScore": 42
    }
  }
}

Step 4: Batch Transaction Creation

For high-volume scenarios, use the batch endpoint to create multiple transactions efficiently. Endpoint: POST /transactions/batch Request:
{
  "transactions": [
    {
      "externalId": "TXN-001",
      "type": "PAYMENT",
      "amount": 1000,
      "currency": "USD",
      "originName": "Customer A",
      "destinationName": "Merchant X"
    },
    {
      "externalId": "TXN-002",
      "type": "PAYMENT",
      "amount": 2500,
      "currency": "EUR",
      "originName": "Customer B",
      "destinationName": "Merchant X"
    }
  ],
  "executeRules": true,
  "skipDuplicates": true
}
Features:
  • Bulk insert for better performance
  • Optimized currency conversion (caches rates for same currency)
  • Automatic duplicate detection (by externalId)
  • Optional rule execution on all transactions
  • Max 1000 transactions per batch
  • 2-minute timeout
Response:
{
  "summary": {
    "total": 2,
    "created": 2,
    "duplicates": 0,
    "failed": 0,
    "flagged": 0,
    "totalCost": 150
  },
  "transactions": [
    {
      "id": "txn-uuid-1",
      "externalId": "TXN-001",
      "riskScore": "15.00",
      "flagged": false
    },
    {
      "id": "txn-uuid-2",
      "externalId": "TXN-002",
      "riskScore": "22.00",
      "flagged": false
    }
  ],
  "executionTimeMs": 3200
}

Step 5: Manual Transaction Analysis

If you created a transaction with executeRules: false, you can manually trigger risk analysis later. Endpoint: POST /entities/:transactionId/analyze Request:
{
  "entityType": "transaction",
  "enrichIfNeeded": false
}
Use Cases:
  • Re-analyze transaction after entity enrichment
  • Analyze transaction after rule updates
  • Periodic re-scoring of pending transactions
Response: Same as automatic risk analysis result

Step 6: Transaction Queries and Monitoring

List Transactions with Filtering

Endpoint: GET /transactions Query Parameters:
GET /transactions?flagged=true&minAmount=10000&sortBy=risk_score&sortOrder=desc&limit=50
Available Filters:
  • flagged: Filter by flagged status (true, false, all)
  • minAmount / maxAmount: Amount range filter (in original currency)
  • currency: Filter by currency
  • type: Filter by transaction type
  • status: Filter by transaction status
  • entityId: Filter by origin or destination entity
  • startDate / endDate: Date range filter
  • search: Free-text search (externalId, description, names)
  • sortBy: Sort field (transacted_at, amount, risk_score, created_at)
  • sortOrder: Sort direction (asc, desc)
Response:
{
  "transactions": [
    {
      "id": "txn-uuid",
      "externalId": "TXN-2024-00001",
      "type": "TRANSFER",
      "amount": "50000.00",
      "currency": "EUR",
      "amountInUsd": "54500.00",
      "riskScore": "68.00",
      "flagged": true,
      "originName": "John Doe",
      "destinationName": "Acme Corp",
      "transactedAt": "2025-12-24T10:30:00Z"
    }
  ],
  "pagination": {
    "total": 150,
    "limit": 50,
    "offset": 0
  }
}

Get Transaction Details

Endpoint: GET /transactions/:transactionId Response: Full transaction object with risk analysis details

View Transaction Alerts

Endpoint: GET /alerts?transactionId=:transactionId Response: All alerts generated for the transaction

Step 7: Alert Consolidation and Investigations

After risk analysis, alerts are automatically consolidated into investigations:
  1. Alert Creation: Rules with create_alert action create individual alerts
  2. 5-Second Delay: System waits to collect all related alerts
  3. Consolidation: Related alerts consolidated into single investigation
  4. Investigation Creation: Investigation created with:
    • Priority based on highest alert severity
    • Status: β€œopen”
    • All related alerts linked
  5. Notifications: Analysts notified of new investigation
Investigation Structure:
{
  "id": "investigation-uuid",
  "organizationId": "org-uuid",
  "title": "High-Risk Transaction: TXN-2024-00001",
  "priority": "critical",
  "status": "open",
  "relatedTransactions": ["txn-uuid"],
  "relatedEntities": ["sender-uuid", "receiver-uuid"],
  "alerts": [
    {
      "id": "alert-uuid-1",
      "severity": "critical",
      "type": "HIGH_RISK_JURISDICTION",
      "description": "Transaction involves high-risk jurisdiction"
    },
    {
      "id": "alert-uuid-2",
      "severity": "warning",
      "type": "LARGE_AMOUNT",
      "description": "Transaction amount exceeds threshold"
    }
  ],
  "createdAt": "2025-12-24T10:30:07Z"
}

Best Practices

  1. Always Enable Auto-Rules: Set executeRules: true (default) to catch suspicious transactions immediately.
  2. Use Batch API for Volume: For bulk imports or high-volume scenarios, use /transactions/batch for better performance.
  3. Link Entities: Always provide originEntityId and destinationEntityId when available. This enables:
    • Entity enrichment data in rule evaluation
    • Better risk aggregation
    • Entity-level transaction patterns
  4. External ID Mapping: Always set unique externalId for correlation with your systems.
  5. Currency Handling: System handles currency conversion automatically. Ensure MS_PROVIDERS_URL is configured correctly.
  6. Rule Configuration: Configure transaction rules for your risk appetite:
    • Amount thresholds appropriate for your business
    • High-risk jurisdictions based on your compliance requirements
    • Velocity rules based on normal transaction patterns
  7. Status Management: Use transaction status field to track lifecycle:
    • PENDING β†’ APPROVED/REJECTED/CANCELLED
    • Update status based on manual review or external validation
  8. Monitoring: Set up dashboards to monitor:
    • Flagged transaction rate
    • Average risk scores
    • Alert volume by type
    • Investigation resolution time

Advanced Patterns

Pattern 1: Entity Risk Affects Transaction Risk

Configure rules that consider entity risk:
{
  "name": "High-Risk Entity Transaction",
  "conditions": {
    "operator": "OR",
    "conditions": [
      {
        "field": "originEntity.riskScore",
        "operator": "greater_than",
        "value": 70
      },
      {
        "field": "destinationEntity.riskScore",
        "operator": "greater_than",
        "value": 70
      }
    ]
  },
  "actions": [
    {
      "type": "add_risk_score",
      "value": 35
    }
  ]
}

Pattern 2: Velocity and Pattern Detection

Use historical queries in rules:
{
  "name": "Unusual Transaction Pattern",
  "conditions": {
    "operator": "AND",
    "conditions": [
      {
        "field": "originEntityId",
        "operator": "historical_sum",
        "aggregateField": "amountInUsd",
        "timeWindow": "24h",
        "comparison": "greater_than",
        "value": 100000
      }
    ]
  }
}

Pattern 3: Sanctions Screening on Transaction

{
  "name": "Transaction Sanctions Check",
  "conditions": {
    "operator": "OR",
    "conditions": [
      {
        "field": "originEntity.enrichment.sanctionsMatch",
        "operator": "equals",
        "value": true
      },
      {
        "field": "destinationEntity.enrichment.sanctionsMatch",
        "operator": "equals",
        "value": true
      }
    ]
  },
  "actions": [
    {
      "type": "update_status",
      "status": "blocked"
    },
    {
      "type": "add_risk_score",
      "value": 100
    }
  ]
}

Error Handling

Currency Conversion Failures

{
  "transaction": {
    "amountInUsd": null,
    "exchangeRate": null
  },
  "warnings": [
    "Currency conversion failed: fixer.io service unavailable"
  ]
}
Transaction created successfully, rules use original amount.

Rule Execution Failures

{
  "rulesResult": {
    "success": false,
    "error": "Rules engine timeout after 30000ms",
    "executed": false
  }
}
Transaction created, but risk not calculated. Manually trigger analysis later.

Batch Partial Failures

{
  "summary": {
    "total": 100,
    "created": 95,
    "failed": 5
  },
  "failures": [
    {
      "externalId": "TXN-042",
      "error": "Validation failed: invalid currency code"
    }
  ]
}
Successful transactions created, failures reported separately.

Next Steps