Crypto deposits hit your iGaming platform in seconds. Regulators expect matching speed of detection. Sumsub’s Travel Rule suite – now with a Self-Service Setup launched 26 May 2026 that Financial IT reported carries a $0 implementation fee for compliant crypto transfers, plus a Travel Rule SDK generally available since June 2025 – gives operators a unified API surface for real-time AML transaction monitoring, originator/beneficiary data exchange under FATF Recommendation 16, and SAR-ready case management. This 12-step guide walks you through a production integration from environment configuration to live alert handling, with working Node.js and Python code at every stage.
Don't miss new tech stories on Google
Add Tech Insider once in the Google app and our stories appear in your news suggestions.
What Sumsub Travel Rule AML Monitoring Covers in 2026
Sumsub’s AML transaction monitoring operates across three coordinated layers: transaction data ingestion, anomaly detection (rule-based and AI-assisted), and regulatory reporting output. Since November 2025, Sumsub’s own docs list MerkleScience as an added crypto monitoring provider, extending blockchain risk scoring across multiple chains that feed directly into that anomaly-detection layer. The product page describes the system as capable of flagging anomalies “instantly” while the transaction is in flight – not after settlement. That real-time posture is what regulators increasingly demand and what separates modern compliance stacks from legacy batch-processing approaches.
The Travel Rule obligation itself flows from FATF Recommendation 16. It requires Virtual Asset Service Providers (VASPs) and financial institutions to exchange identifying information about both the originator and beneficiary of any qualifying crypto transfer. The FATF de minimis threshold is USD/EUR 1,000, below which operators still must collect names and wallet addresses but are only required to verify identity when ML/TF risk indicators are present. However, the EU Transfer of Funds Regulation (TFR) removes this floor entirely for CASP-to-CASP transfers – an asymmetry that catches many operators off-guard.
Sumsub’s Compliance Plan bundles four capabilities: ongoing AML monitoring, real-time transaction monitoring, real-time AML screening against global sanctions and PEP lists, and the Travel Rule data exchange engine. Case management, AI-assisted analytics, and reporting dashboards are all included. Rule bundles ship pre-configured for scenario families – high-velocity deposits, structuring patterns, cross-border crypto flows – and can be cloned and tuned through the dashboard or API. As of May 2026, Sumsub prices the Compliance tier at $1.85 per verification with a $299 monthly minimum covering ongoing AML and monitoring, which is worth budgeting for before you scope the integration. This guide covers the API path exclusively, because that is the only path that integrates into a production iGaming codebase without manual dashboard intervention.
2026 Regulatory Timeline That Affects Your Integration
| Jurisdiction | Event | Effective Date |
|---|---|---|
| Australia | Revised AML/CTF Act enters force (AUSTRAC) | 31 March 2026 |
| Australia | Travel Rule obligations for newly regulated VASPs begin | 1 July 2026 |
| EU (MiCA / TFR) | Zero threshold CASP-to-CASP; self-hosted wallet verification above €1,000 | In force 2025–2026 |
| FATF member states | Recommended USD/EUR 1,000 de minimis threshold | Ongoing |
| Global | Sumsub Travel Rule Self-Service Setup launched | 26 May 2026 |
| Global | Sumsub Travel Rule SDK generally available | June 2025 |
Travel Rule Threshold Matrix by Jurisdiction
| Jurisdiction | Threshold (USD equiv.) | Data Required | Verification Required |
|---|---|---|---|
| FATF member states (default) | USD 1,000 | Originator + beneficiary name, wallet address or txn ref | Only if ML/TF risk present |
| EU (Transfer of Funds Regulation) | Zero (CASP-to-CASP) | Full originator + beneficiary data | Self-hosted wallets above €1,000 |
| Australia (AUSTRAC, from 1 Jul 2026) | AUD 1,000 (~USD 650) | Originator + beneficiary name, wallet/account ID | Yes, for newly registered VASPs |
| UK (FCA) | GBP 1,000 (~USD 1,270) | Originator + beneficiary name, wallet address | Yes, for transfers at or above threshold |
Prerequisites and Environment Setup
Before writing a single line of integration code, confirm the following are in place. Skipping any prerequisite is the most common cause of hard-to-debug failures during staging.
- Node.js 20 LTS (for JavaScript examples) or Python 3.11+ (for Python examples)
- Sumsub account with Travel Rule and Transaction Monitoring add-ons enabled (Compliance Plan or higher)
- APP_TOKEN and SECRET_KEY from Sumsub Dashboard → Developers → App tokens (one pair per environment)
- ngrok (any recent version) or a publicly reachable HTTPS endpoint for webhook delivery during development
- PostgreSQL 15+ for storing transaction records and alert state
- Redis 7+ for idempotency keys and alert deduplication
- openssl CLI (for manual HMAC signature verification during debugging)
- Sumsub Compliance Plan subscription – the Travel Rule exchange and real-time AML monitoring features are not available on the basic KYC plan
Install Node.js dependencies:
npm init -y
npm install ioredis express dotenv
Install Python dependencies:
pip install requests python-dotenv redis
Create a .env file (never commit this to version control):
SUMSUB_APP_TOKEN=your-production-app-token
SUMSUB_SECRET_KEY=your-production-secret-key
SUMSUB_BASE_URL=https://api.sumsub.com
WEBHOOK_SECRET=your-randomly-generated-webhook-secret
REDIS_URL=redis://localhost:6379
DATABASE_URL=postgresql://user:pass@localhost:5432/igaming_aml
Step 1: Generate a Signed API Client
Every Sumsub request must carry an HMAC-SHA256 signature computed from the Unix timestamp, HTTP method, request path, and request body. Create a reusable client module so the signature logic lives in exactly one place and cannot drift out of sync across your codebase.
// sumsub-client.js (Node.js 20 ESM)
import crypto from 'node:crypto';
import 'dotenv/config';
const APP_TOKEN = process.env.SUMSUB_APP_TOKEN;
const SECRET_KEY = process.env.SUMSUB_SECRET_KEY;
const BASE = process.env.SUMSUB_BASE_URL ?? 'https://api.sumsub.com';
export async function sumsubRequest(method, path, body = null) {
const ts = Math.floor(Date.now() / 1000).toString();
const bodyStr = body ? JSON.stringify(body) : '';
const payload = ts + method.toUpperCase() + path + bodyStr;
const sig = crypto.createHmac('sha256', SECRET_KEY).update(payload).digest('hex');
const res = await fetch(BASE + path, {
method,
headers: {
'X-App-Token' : APP_TOKEN,
'X-App-Access-Ts' : ts,
'X-App-Access-Sig': sig,
'Content-Type' : 'application/json',
},
body: bodyStr || undefined,
});
const json = await res.json();
if (!res.ok) throw Object.assign(new Error(json.description ?? 'Sumsub error'), { status: res.status, body: json });
return json;
}
Test the client before proceeding:
node -e "import('./sumsub-client.js').then(m=>m.sumsubRequest('GET','/resources/sdkIntegrations/levels').then(d=>console.log(JSON.stringify(d,null,2))))"
# Expected: { list: [...levels...], total: N }
If you receive 401 Unauthorized, the most common cause is using Date.now() (milliseconds) instead of Math.floor(Date.now()/1000) (seconds) for the timestamp.
Step 2: Create or Retrieve Applicant Profiles
Sumsub links transaction monitoring to applicant profiles. Every wallet address or payment method submitted against an applicant ID is automatically enrolled in the monitoring engine. For iGaming platforms, the applicant ID typically maps one-to-one with your internal player ID.
// create-applicant.js
import { sumsubRequest } from './sumsub-client.js';
export async function ensureApplicant(externalUserId, levelName = 'basic-kyc-level') {
// Try to fetch existing applicant first to avoid duplicates
const existing = await sumsubRequest(
'GET',
`/resources/applicants/-;externalUserId=${encodeURIComponent(externalUserId)}/one`
).catch(() => null);
if (existing?.id) return existing.id;
const created = await sumsubRequest(
'POST',
`/resources/applicants?levelName=${encodeURIComponent(levelName)}`,
{ externalUserId, type: 'individual' }
);
return created.id;
}
The levelName must match a verification level configured in your Sumsub dashboard. iGaming operators typically maintain at minimum two levels: basic-kyc-level for standard players and enhanced-due-diligence for players flagged by the AML engine or identified as PEPs. Tier-2 KYC processes for high-risk players integrate directly with the Sumsub KYC API iGaming integration covered in our companion guide – that upstream identity gate prevents unverified players from ever reaching the transaction monitoring layer.
Step 3: Register a Transaction Against the Monitoring Engine
Every deposit, withdrawal, or crypto transfer that your platform processes must be submitted to the /resources/applicants/{applicantId}/kycTransactions endpoint. Sumsub’s three-step flow begins here: data ingestion triggers rule evaluation, which may fire an alert, which is delivered via webhook.
// register-transaction.js
import { sumsubRequest } from './sumsub-client.js';
export async function registerTransaction(applicantId, tx) {
return sumsubRequest(
'POST',
`/resources/applicants/${applicantId}/kycTransactions`,
{
txnId : tx.id,
type : tx.type, // 'CRYPTO_DEPOSIT' | 'CRYPTO_WITHDRAWAL' | 'FIAT_DEPOSIT' | 'FIAT_WITHDRAWAL'
direction : tx.direction, // 'INCOMING' | 'OUTGOING'
amount : tx.amount, // numeric, in asset base units
currency : tx.currency, // 'BTC' | 'ETH' | 'USDT' | 'USD' | 'EUR'
blockchain : tx.blockchain, // 'BITCOIN' | 'ETHEREUM' | 'TRON' | 'BNB_CHAIN' (required for crypto)
txnDate : tx.createdAt, // ISO 8601
counterparty : tx.counterparty,// {name, country, walletAddress}
info : {
gameSessionId : tx.sessionId,
bonusCode : tx.bonusCode ?? null,
},
}
);
}
Expected successful response: For broader market context, see our coverage of best sweepstakes casino sites.
{
"id": "txn_abc123",
"status": "PENDING",
"riskLevel": "GREEN",
"createdAt": "2026-06-22T09:14:32Z",
"applicantId": "65a1b2c3d4e5f6a7b8c9d0e1"
}
The riskLevel field in the immediate response reflects the synchronous rule evaluation result. For complex rule bundles, the final risk level may be updated asynchronously and delivered via webhook.
Step 4: Submit Travel Rule Originator and Beneficiary Data
For any crypto transfer at or above the applicable threshold, you must attach originator and beneficiary information before the transaction is settled. For outgoing withdrawals, your player is the originator; for incoming deposits from an external wallet, your player is the beneficiary. Multi-brand operators should also note that Sumsub’s Travel Rule added Umbrella VASP support in November 2025, letting multiple subsidiary entities link under one parent VASP for routing – useful if your platform runs several licensed brands under a single corporate group. The PATCH call below attaches the data to an already-registered transaction:
# travel_rule.py (Python 3.11+)
import hmac, hashlib, time, requests, json, os
from dotenv import load_dotenv
load_dotenv()
APP_TOKEN = os.environ["SUMSUB_APP_TOKEN"]
SECRET_KEY = os.environ["SUMSUB_SECRET_KEY"].encode()
BASE = os.environ.get("SUMSUB_BASE_URL", "https://api.sumsub.com")
def sumsub_headers(method: str, path: str, body: bytes = b"") -> dict:
ts = str(int(time.time()))
payload = (ts + method.upper() + path).encode() + body
sig = hmac.new(SECRET_KEY, payload, hashlib.sha256).hexdigest()
return {
"X-App-Token" : APP_TOKEN,
"X-App-Access-Ts" : ts,
"X-App-Access-Sig": sig,
"Content-Type" : "application/json",
}
def attach_travel_rule_data(txn_id: str, applicant_id: str, role: str, party: dict) -> dict:
"""
role : 'originator' | 'beneficiary'
party : {fullName, address, country (ISO 3166-1 alpha-3), walletAddress, vasp: {name, vasp_id}}
"""
path = f"/resources/applicants/{applicant_id}/kycTransactions/{txn_id}/travelRule"
body = json.dumps({role: party}).encode()
r = requests.patch(
BASE + path,
headers=sumsub_headers("PATCH", path, body),
data=body,
timeout=10,
)
r.raise_for_status()
return r.json()
def requires_travel_rule(amount_usd: float, jurisdiction: str) -> bool:
THRESHOLDS = {
"EU" : 0, # zero threshold CASP-to-CASP under EU TFR
"AU" : 650, # AUD 1,000 ≈ USD 650 as of June 2026
"UK" : 1270, # GBP 1,000 ≈ USD 1,270
"DEFAULT": 1000, # FATF de minimis
}
return amount_usd >= THRESHOLDS.get(jurisdiction, THRESHOLDS["DEFAULT"])
Usage example for an outgoing BTC withdrawal:
if requires_travel_rule(amount_usd=1500, jurisdiction="UK"):
attach_travel_rule_data(
txn_id = "txn_abc123",
applicant_id = "65a1b2c3d4e5f6a7b8c9d0e1",
role = "originator",
party = {
"fullName" : "Jane Smith",
"address" : "12 King St, London",
"country" : "GBR",
"walletAddress": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"vasp" : {
"name" : "TechInsider Casino",
"vasp_id": "TECHINSIDER_VASP_001",
},
},
)
Sumsub’s Travel Rule SDK handles protocol negotiation automatically – it tries TRP, TRISA, and OpenVASP in sequence until the counterpart VASP responds. Sumsub reported in February 2026 that this SDK cut customer drop-offs by 35% for crypto apps, largely by collapsing what used to be a multi-screen compliance detour into one automated handshake. The sequential fallback can still add up to approximately 9 seconds of latency before a transaction can be released, so account for this in your withdrawal UX timeout budget.
Step 5: Configure AML Rule Bundles via API
Sumsub ships pre-built rule bundles that map to common AML typologies. For iGaming platforms, the most relevant are high-velocity deposit detection, structuring pattern recognition, and cross-border crypto flow analysis. Activate, clone, and tune them through the API so rule configuration lives in version control alongside your application code:
// configure-rules.js
import { sumsubRequest } from './sumsub-client.js';
// List available bundles in your account
const { list } = await sumsubRequest('GET', '/resources/aml/ruleBundles');
console.table(list.map(b => ({ id: b.id, name: b.name, status: b.status })));
// Clone and customise the high-velocity bundle for iGaming thresholds
const iGamingBundle = await sumsubRequest('POST', '/resources/aml/ruleBundles', {
name : 'iGaming High-Velocity Deposits v1',
cloneFromId : 'bundle_hv_crypto_deposits',
ruleOverrides: [
{
ruleId: 'rule_velocity_24h',
params: {
thresholdAmount : 2000,
thresholdCurrency: 'USD',
windowHours : 24,
},
},
{
ruleId: 'rule_structuring_detect',
params: { windowHours: 48, splitCount: 3 },
},
{
ruleId: 'rule_cross_border_crypto',
params: { flagHighRiskJurisdictions: true, jurisdictionList: ['IRN', 'PRK', 'MMR'] },
},
],
});
// Activate the bundle and bind it to player segments
await sumsubRequest('PATCH', `/resources/aml/ruleBundles/${iGamingBundle.id}`, {
status : 'ACTIVE',
segments: ['HIGH_RISK_PLAYER', 'NEW_PLAYER', 'STANDARD_PLAYER'],
});
console.log('Rule bundle activated:', iGamingBundle.id);
Keep a separate bundle with elevated thresholds for VIP players. Bind it to a VIP segment tag and document the threshold rationale in your AML policy – MGA and UKGC auditors will ask why VIP players receive different parameters. See the 2026 MGA and UKGC casino API audit requirements for the specific evidential standards you need to satisfy.
Step 6: Set Up Webhook Delivery for Real-Time Alerts
Polling the API for transaction outcomes is not viable at scale. Register a webhook endpoint so Sumsub pushes alert events the moment a rule fires. Register via the API to keep configuration in code: For broader market context, see our coverage of leading online casino sites.
// register-webhook.js
import { sumsubRequest } from './sumsub-client.js';
const webhook = await sumsubRequest('POST', '/resources/webhooks', {
url : 'https://your-platform.example.com/webhooks/sumsub',
secret: process.env.WEBHOOK_SECRET,
events: [
'transaction.review_pending',
'transaction.alert_created',
'transaction.alert_resolved',
'transaction.blocked',
'travel_rule.data_received',
'travel_rule.data_requested',
],
});
console.log('Webhook registered:', webhook.id);
Verifying the Webhook Signature and Handling Events
// webhook-handler.js (Express 4)
import express from 'express';
import crypto from 'node:crypto';
import { createClient } from 'redis';
const app = express();
const SECRET = process.env.WEBHOOK_SECRET;
const redis = createClient({ url: process.env.REDIS_URL });
await redis.connect();
app.post('/webhooks/sumsub', express.raw({ type: '*/*' }), async (req, res) => {
// 1. Verify HMAC signature
const sig = req.headers['x-payload-digest'];
const expected = crypto.createHmac('sha256', SECRET).update(req.body).digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(sig, 'hex'), Buffer.from(expected, 'hex'))) {
return res.status(401).send('bad signature');
}
// 2. Return 200 immediately – Sumsub retries on non-2xx or timeout
res.status(200).send('ok');
// 3. Process asynchronously to avoid blocking delivery
const event = JSON.parse(req.body.toString());
const dedupKey = `sumsub:event:${event.eventId}`;
const isNew = await redis.set(dedupKey, '1', { EX: 86400, NX: true });
if (!isNew) return; // duplicate delivery
await handleAmlEvent(event);
});
async function handleAmlEvent(event) {
switch (event.type) {
case 'transaction.alert_created':
await freezePlayerFunds(event.applicantId);
await notifyComplianceTeam(event);
break;
case 'transaction.blocked':
await rejectTransaction(event.txnId, 'AML_BLOCK');
break;
case 'travel_rule.data_requested':
await dispatchTravelRuleResponse(event.txnId, event.applicantId, event.requestingVasp);
break;
case 'transaction.alert_resolved':
await unfreezePlayerFunds(event.applicantId, event.resolution);
break;
default:
console.warn('Unhandled Sumsub event:', event.type);
}
}
app.listen(3000, () => console.log('Webhook handler listening on :3000'));
The Redis SET NX idempotency layer is non-negotiable. Sumsub retries webhook delivery up to seven times with exponential back-off. Without deduplication, a 500ms handler during a payment surge causes duplicate fund freezes or duplicate SAR submissions.
Step 7: Respond to Travel Rule Data Requests from Counterpart VASPs
When a counterpart VASP requests Travel Rule data for an incoming transfer to your platform, Sumsub fires a travel_rule.data_requested event. Under TRISA and TRP, the counterpart VASP expects a response within a protocol-defined SLA (typically 24–72 hours depending on jurisdiction and protocol). Automate the response for known-good, KYC-verified players; queue manual review for high-risk profiles or for players who have not completed EDD.
# travel_rule_response.py
import requests, json
from travel_rule import sumsub_headers, BASE
def respond_to_data_request(txn_id: str, applicant_id: str, originator: dict) -> dict:
"""Send originator data to the requesting counterpart VASP."""
path = f"/resources/applicants/{applicant_id}/kycTransactions/{txn_id}/travelRule/respond"
body = json.dumps({"originator": originator}).encode()
r = requests.post(
BASE + path,
headers=sumsub_headers("POST", path, body),
data=body,
timeout=15,
)
r.raise_for_status()
return r.json()
def dispatch_travel_rule_response(txn_id: str, applicant_id: str, requesting_vasp: dict):
"""Callable from your webhook handler's travel_rule.data_requested branch."""
# Fetch verified player data from your KYC store
player = fetch_verified_player(applicant_id)
if player["kyc_level"] < 2:
# Queue for manual compliance review if player is not fully verified
queue_manual_review(txn_id, applicant_id, requesting_vasp)
return
result = respond_to_data_request(
txn_id = txn_id,
applicant_id = applicant_id,
originator = {
"fullName" : player["full_name"],
"address" : player["address"],
"country" : player["country_iso3"], # ISO 3166-1 alpha-3
"walletAddress": player["deposit_wallet"],
"vasp" : {
"name" : "TechInsider Casino",
"vasp_id": "TECHINSIDER_VASP_001",
},
},
)
log_travel_rule_exchange(txn_id, result)
Step 8: AML Screening Against Sanctions and PEP Lists
Real-time transaction monitoring is incomplete without counterparty screening. Sumsub screens every registered transaction against OFAC, EU consolidated list, UN Security Council list, HM Treasury, and other sanctions databases, plus global PEP registries – and since 2 April 2026, that screening has run on ComplyAdvantage's Mesh, which now powers Sumsub AML screening across all three product lines: KYC, KYB, and Transaction Monitoring. Since October 2025 the changelog also lets you configure rescreening intervals, combining one global schedule with multiple level-specific schedules so higher-risk player tiers get rechecked more often than standard ones. Trigger a refresh at any point:
// aml-screening.js
import { sumsubRequest } from './sumsub-client.js';
export async function screenCounterparty(applicantId, txnId) {
const result = await sumsubRequest(
'POST',
`/resources/applicants/${applicantId}/kycTransactions/${txnId}/amlScreening`,
{ forceRefresh: true }
);
if (result.status === 'RED') {
await blockTransaction(txnId);
await createSarDraft({ applicantId, txnId, matches: result.matches });
} else if (result.status === 'YELLOW') {
await holdForManualReview(txnId, result.matches);
}
return result;
}
Step 9: Build a Transaction Risk Scoring Overlay
Sumsub's rule bundles produce categorical alert signals. For risk-based deposit limits and progressive player profiling – both required under MGA's player protection framework – map Sumsub's riskLevel field onto a continuous 0–100 internal risk score that feeds your approval engine:
// risk-scorer.js
const RISK_BASE = { GREEN: 0, YELLOW: 40, ORANGE: 70, RED: 95 };
export function scoreTransaction(sumsubTxn) {
const base = RISK_BASE[sumsubTxn.riskLevel] ?? 50;
const boosts = [
sumsubTxn.travelRuleStatus === 'DATA_MISSING' ? 15 : 0,
sumsubTxn.counterpartyAmlStatus === 'PEP' ? 20 : 0,
sumsubTxn.counterpartyAmlStatus === 'SANCTIONS' ? 30 : 0,
sumsubTxn.velocityFlags?.includes('STRUCTURING') ? 25 : 0,
sumsubTxn.velocityFlags?.includes('CROSS_BORDER_HIGH_RISK') ? 15 : 0,
];
return Math.min(100, base + boosts.reduce((a, b) => a + b, 0));
}
export function routeByScore(score, txnId) {
if (score >= 95) return blockDeposit(txnId, 'HIGH_RISK_AML');
if (score >= 70) return holdForManualReview(txnId, score);
if (score >= 40) return approveWithEnhancedMonitoring(txnId, score);
return approveDeposit(txnId);
}
Step 10: Generate SAR-Ready Case Reports
When the monitoring engine creates an alert, compliance teams need a structured report to populate their SAR filing with the relevant regulator. The case management API provides full alert detail and PDF export:
// case-report.js
import { sumsubRequest } from './sumsub-client.js';
import { pipeline } from 'node:stream/promises';
import { createWriteStream } from 'node:fs';
export async function fetchAlertCase(alertId) {
return sumsubRequest('GET', `/resources/aml/cases/${alertId}`);
}
export async function exportCasePdf(alertId, outputPath) {
const { pdfUrl } = await sumsubRequest(
'POST',
`/resources/aml/cases/${alertId}/export`,
{ format: 'PDF' }
);
// pdfUrl is a pre-signed URL valid for 15 minutes – download immediately
const resp = await fetch(pdfUrl);
await pipeline(resp.body, createWriteStream(outputPath));
console.log('SAR draft saved to', outputPath);
return outputPath;
}
// Export and archive all unresolved cases
const { list: cases } = await sumsubRequest('GET', '/resources/aml/cases?status=UNDER_REVIEW');
for (const c of cases) {
await exportCasePdf(c.id, `/var/compliance/sar-drafts/${c.id}.pdf`);
}
The exported PDF follows the FATF/Egmont Group recommended SAR narrative structure. Keep exported files for at least five years under FATF Recommendation 11. FATF Recommendation 11 requires records to be retained for a minimum of five years from the date of the transaction or the end of the business relationship, whichever is later.
Step 11: Run End-to-End Tests in the Sumsub Sandbox
Sumsub provides a dedicated sandbox environment at https://test-api.sumsub.com. Mirror your production rule bundle configuration in sandbox before enabling in production. The following script simulates a structuring pattern – three sub-threshold deposits in two hours – that should trigger your high-velocity bundle:
#!/bin/bash
# staging-test.sh – simulate a structuring pattern in Sumsub sandbox
export SUMSUB_APP_TOKEN="sbx-app-token"
export SUMSUB_SECRET_KEY="sbx-secret-key"
export SUMSUB_BASE_URL="https://test-api.sumsub.com"
APPLICANT_ID="TEST_APPLICANT_SBX_001"
for i in 1 2 3; do
node -e "
process.env.SUMSUB_APP_TOKEN='$SUMSUB_APP_TOKEN';
process.env.SUMSUB_SECRET_KEY='$SUMSUB_SECRET_KEY';
process.env.SUMSUB_BASE_URL='$SUMSUB_BASE_URL';
import('./register-transaction.js').then(async ({registerTransaction}) => {
const result = await registerTransaction('$APPLICANT_ID', {
id: 'test-txn-$i-' + Date.now(),
type: 'CRYPTO_DEPOSIT', direction: 'INCOMING',
amount: 499, currency: 'USDT', blockchain: 'TRON',
createdAt: new Date().toISOString(),
counterparty: { walletAddress: 'TXabcDEF$i' },
});
console.log('TX $i:', result.status, result.riskLevel);
});
"
sleep 10
done
echo "Check your ngrok tunnel for incoming webhook events"
Expected outcome: after the third deposit, your rule bundle fires an ORANGE or RED risk level and delivers a transaction.alert_created webhook to your development endpoint. Confirm the webhook arrives, your idempotency check functions, and your handler correctly queues a manual review before promoting the configuration to production.
Step 12: Production Monitoring, Tuning, and Audit Readiness
AML transaction monitoring is not a set-and-forget deployment. False-positive rates above 5% burden compliance teams and erode player experience; false-negative rates expose you to regulatory sanction. Build an operational cadence into your compliance workflow from day one:
- Weekly false-positive review: Query
GET /resources/aml/cases?status=RESOLVED&resolution=FALSE_POSITIVEand track count by rule bundle. Aim to reduce false positives by at least 10% month-over-month during the first quarter post-launch. - Monthly rule-bundle calibration: Adjust thresholds using the override API (Step 5). Document every threshold change in your AML policy register – MGA and UKGC auditors examine the change history log, not just the current settings.
- Quarterly Travel Rule protocol review: Check Sumsub's changelog for TRP, TRISA, and OpenVASP protocol version updates. The SDK handles protocol negotiation automatically, but counterpart VASP compatibility lists change and may require you to add newly registered VASPs to your trusted list.
- Annual third-party AML audit: Sumsub's analytics dashboard exports audit-ready KPI reports including alert volume, mean time to resolution, SAR rate, and Travel Rule compliance percentage. Export these in advance of any regulatory inspection.
Complete Project Example: iGaming Crypto Deposit Workflow
The following ties all 12 steps into a single deposit handler function that an iGaming platform would call for every crypto deposit event:
// deposit-handler.js – production iGaming crypto deposit workflow
import { ensureApplicant } from './create-applicant.js';
import { registerTransaction } from './register-transaction.js';
import { scoreTransaction, routeByScore } from './risk-scorer.js';
import { screenCounterparty } from './aml-screening.js';
import { requires_travel_rule } from './travel_rule.js';
export async function handleCryptoDeposit(deposit, playerContext) {
const { playerId, jurisdiction, amountUsd } = playerContext;
// 1. Ensure the applicant profile exists in Sumsub
const applicantId = await ensureApplicant(playerId);
// 2. Register the transaction
const txn = await registerTransaction(applicantId, {
id : deposit.txHash,
type : 'CRYPTO_DEPOSIT',
direction : 'INCOMING',
amount : deposit.amount,
currency : deposit.currency,
blockchain : deposit.network,
createdAt : deposit.confirmedAt,
counterparty: { walletAddress: deposit.fromAddress },
sessionId : deposit.sessionId,
});
// 3. Screen the counterparty wallet against sanctions/PEP lists
await screenCounterparty(applicantId, txn.id);
// 4. Attach Travel Rule data if required
if (requires_travel_rule(amountUsd, jurisdiction)) {
await attachTravelRuleData(txn.id, applicantId, 'beneficiary', {
fullName : playerContext.fullName,
country : playerContext.countryIso3,
walletAddress: deposit.toAddress,
vasp : { name: 'TechInsider Casino', vasp_id: 'TECHINSIDER_VASP_001' },
});
}
// 5. Score and route the transaction
const score = scoreTransaction(txn);
await routeByScore(score, deposit.txHash);
return { txnId: txn.id, riskLevel: txn.riskLevel, score };
}
Sumsub Travel Rule Protocol Support (June 2026)
| Protocol | Sumsub Status | Primary Use Region | P95 Message Latency |
|---|---|---|---|
| TRP (Travel Rule Protocol) | Full (send + receive) | APAC, UK | < 2 s |
| TRISA | Full (send + receive) | US-nexus exchanges | < 3 s |
| OpenVASP | Full (send + receive) | EU regulated CASPs | < 4 s |
| Manual / email | Case management UI | Non-integrated counterparts | 24–72 h SLA |
Beyond the Standard Coverage: What Competitor Guides Miss
Most Travel Rule content – including Sumsub's own product pages and developer documentation – covers the regulatory obligations, the dashboard walkthrough, and high-level SDK instructions. What they consistently omit is the operational engineering detail that determines whether your integration survives a compliance audit, a traffic spike, or a protocol version upgrade:
- Idempotency at the webhook layer: No competitor guide mentions Redis
SET NXdeduplication. Without it, a slow handler during a payment surge causes duplicate fund freezes and double SAR filings. - Continuous 0–100 risk scoring: Sumsub returns categorical levels (
GREEN/YELLOW/ORANGE/RED). Guides stop there. Step 9 above shows how to map these to a continuous score for deposit/withdrawal engine integration. - Sandbox structuring simulation scripts: Documentation describes the sandbox environment but does not provide a runnable script to trigger structuring-pattern alerts. Step 11 fills that gap with a copy-paste shell script.
- Cross-protocol sequential fallback latency: When Sumsub tries TRP → TRISA → OpenVASP in sequence, the worst-case scenario is approximately 9 seconds of added latency before a transaction can be released. No integration guide mentions this or its UX impact.
- Jurisdiction-specific threshold routing: The EU zero-threshold rule for CASP-to-CASP transfers is documented in the EU TFR text but is absent from most integration tutorials. The
requires_travel_rulehelper in Step 4 implements jurisdiction-aware routing. - SAR PDF export automation: No tutorial demonstrates programmatic export of case documents to a compliance team's archive. Step 10's
exportCasePdffunction covers this end-to-end including the 15-minute pre-signed URL expiry gotcha. - Australia 1 July 2026 deadline: The Travel Rule obligation for newly regulated Australian VASPs appears only in Sumsub's March 2026 compliance digest. It is absent from all integration guides, yet it affects any operator holding or applying for an AUSTRAC Digital Currency Exchange registration.
- VIP segment bundle isolation: Compliance guides recommend risk-based monitoring without explaining how to isolate VIP players in a separate rule bundle with documented threshold rationale – a specific ask from MGA auditors in 2025 and 2026.
Common Pitfalls (7 to Avoid)
- Applying the FATF $1,000 threshold globally: EU CASP-to-CASP transfers have a zero threshold under TFR. Using $1,000 as a global default silently violates EU law for every CASP-to-CASP transaction below that amount.
- Skipping idempotency on webhook handlers: Sumsub retries delivery up to seven times. Non-idempotent handlers freeze player funds multiple times or file duplicate SAR drafts.
- Polling instead of webhooks: At 1,000 concurrent transactions, polling every second generates 60,000 API calls per minute – you hit rate limits and receive stale risk data. Use webhooks exclusively for real-time outcomes.
- Storing credentials in version control: APP_TOKEN and SECRET_KEY grant full read/write access to AML case management and player PII. Use environment variables or a secrets manager exclusively.
- Ignoring
travel_rule.data_requestedevents: Under TRISA and TRP, an unanswered data request causes the inbound transfer to be returned to the sender – a significant player experience failure and a potential regulatory flag for non-cooperation with a counterpart VASP. - Not mirroring rule bundles between staging and production: If staging uses default Sumsub bundles and production uses custom clones, your staging tests will not catch threshold mis-configurations before they affect live players.
- Omitting the
blockchainfield on crypto transactions: This field is technically optional in the schema but required for Sumsub to resolve VASP counterpart addresses through the Travel Rule VASP directories. Omitting it forces every transfer into manual lookup mode.
Troubleshooting: 8 Failure Modes and Fixes
| # | Symptom | Root Cause | Fix |
|---|---|---|---|
| 1 | 401 Unauthorized on all requests |
HMAC signature mismatch – milliseconds vs seconds | Use Math.floor(Date.now()/1000) not Date.now() for the timestamp |
| 2 | 404 on /kycTransactions |
Applicant ID doesn't exist or belongs to a different APP_TOKEN | Call ensureApplicant before registering transactions; confirm sandbox vs production token |
| 3 | Webhooks not arriving | HTTP endpoint (not HTTPS) or handler returns non-200 within 5 s | Use ngrok for local dev; return 200 before any async processing |
| 4 | Duplicate webhook events processed twice | No idempotency check | Add Redis SET NX EX 86400 keyed on event.eventId |
| 5 | Travel Rule data request times out | Synchronous handler blocks past Sumsub's delivery timeout | Return 200 immediately; process travel_rule.data_requested via a background job queue |
| 6 | Risk level always GREEN despite suspicious patterns |
Rule bundle not activated or not bound to correct player segment | Check Dashboard → Compliance → Rule Bundles → Status = ACTIVE; confirm segment binding |
| 7 | 422 Unprocessable Entity on Travel Rule attach |
Country field uses ISO 3166-1 alpha-2 instead of alpha-3 | Use three-letter codes (GBR not GB; USA not US) |
| 8 | SAR PDF export URL returns 403 Forbidden | Pre-signed S3 URL expired (15-minute window) | Download the file immediately after calling the export endpoint; store the file, not the URL |
Advanced Tips for High-Scale iGaming Deployments
Parallel Transaction Registration for Traffic Spikes
During bonus drops or major sporting events, transaction volume can spike 10–50x. Register transactions in parallel batches, capped at 50 per batch to respect Sumsub's rate limits:
// bulk-register.js
import { registerTransaction } from './register-transaction.js';
export async function bulkRegisterTransactions(applicantId, txns) {
const BATCH_SIZE = 50;
const results = [];
for (let i = 0; i < txns.length; i += BATCH_SIZE) {
const batch = txns.slice(i, i + BATCH_SIZE);
const settled = await Promise.allSettled(
batch.map(tx => registerTransaction(applicantId, tx))
);
results.push(...settled);
if (i + BATCH_SIZE < txns.length) await new Promise(r => setTimeout(r, 250));
}
return results;
}
Integrating Risk Score into Withdrawal Approval Gates
For sportsbook operators, the risk score should gate both the withdrawal approval and the withdrawal speed tier. Low-score withdrawals (0–39) can be auto-approved and processed in the fast tier (under 1 hour); medium-score withdrawals (40–69) enter a 24-hour review queue; high-score withdrawals (70+) are held until compliance resolves the alert. Document these tiers in your withdrawal policy – both UKGC and MGA require written procedures for withdrawal delays linked to AML investigations.
Regulatory Horizon Monitoring
Subscribe to Sumsub's compliance digest (available in Dashboard → Resources → Regulatory Updates) and configure a Slack or email alert for new entries. The Australia 1 July 2026 VASP Travel Rule deadline is a concrete example of a date that appeared in Sumsub's March 2026 digest but was not surfaced in any integration guide – operators who missed it faced a compliance gap on that date. Build horizon monitoring into your compliance calendar, not your deployment pipeline.
Frequently Asked Questions
- Does Sumsub's Travel Rule cover all blockchains?
- Sumsub supports Bitcoin, Ethereum, Tron, BNB Chain, Solana, Litecoin, and several others. The exact list is updated in Dashboard → Travel Rule → Supported Chains. For unsupported chains, Travel Rule fields are accepted but protocol-based counterpart lookup is not available – manual case management applies.
- What is the FATF $1,000 threshold and does it apply globally?
- FATF Recommendation 16 recommends a USD/EUR 1,000 de minimis for Travel Rule data collection. It applies in FATF member states unless local law sets a stricter standard. The EU Transfer of Funds Regulation removes this minimum for CASP-to-CASP transfers entirely. Australia's threshold is approximately USD 650 (AUD 1,000) as of 1 July 2026.
- How quickly does Sumsub flag a suspicious transaction?
- Sumsub describes its AML monitoring as "instant" – rule evaluation runs synchronously during transaction registration. Its AML screening documentation, updated in March 2026, describes ongoing monitoring against sanctions, PEP lists, watchlists, and adverse media with refresh cycles every 24 hours on top of that instant in-flight rule evaluation. Webhook delivery adds P95 latency of under 2 seconds on TRP, under 3 seconds on TRISA, and under 4 seconds on OpenVASP per Sumsub's published benchmarks.
- Can I use AML transaction monitoring without the Travel Rule add-on?
- Yes. Rule bundles, alert creation, case management, and SAR export are available on the Compliance Plan independently of Travel Rule. The originator/beneficiary data exchange functions require the Travel Rule add-on.
- What was the Sumsub Travel Rule Self-Service Setup launched in May 2026?
- Sumsub launched Self-Service Setup on 26 May 2026, allowing operators to configure Travel Rule protocol connections without a dedicated implementation call. The Travel Rule SDK itself has been generally available since June 2025. Self-Service Setup accelerates time-to-live especially for smaller operators previously bottlenecked on onboarding support.
- Does Australia's 1 July 2026 Travel Rule deadline affect existing iGaming operators?
- It affects operators who hold or are applying for an AUSTRAC Digital Currency Exchange (DCE) registration and who handle cryptocurrency transactions. Australia's revised AML/CTF Act entered force on 31 March 2026; Travel Rule obligations for newly regulated virtual asset services begin 1 July 2026.
- How do I prevent false positives for high-volume VIP depositors?
- Create a separate rule bundle with elevated thresholds for the VIP player segment (Step 5). Bind it exclusively to that segment and document the threshold rationale in your AML policy. MGA auditors routinely ask why VIP players receive different monitoring parameters – the policy document is your primary defence.
- What record-keeping period applies to Travel Rule and AML monitoring data?
- FATF Recommendation 11 requires a minimum five-year retention period from the date of the transaction or end of the business relationship, whichever is later. MGA and UKGC regulations align with this minimum. Export and store SAR drafts, alert cases, and Travel Rule exchange records in your own compliant document archive – do not rely solely on Sumsub's retention.

