MiCA is live. FATF is enforcing. If your stablecoin payment stack relies on one-time address screening, you have compliance gaps — and this guide will show you exactly where they are and how to fix them at the infrastructure layer.
The Three Gaps That Get Teams Flagged
Gap 1: Single-chain coverage. Your screening covers Ethereum. Your customer routes through Tron-USDT or Solana-USDC. You miss it.
Gap 2: Static address screening. You run a blocklist check at onboarding. You never re-screen as that address transacts. A clean address can receive funds from a mixer between your checks.
Gap 3: Broadcast treated as finality. Funds release the moment you call your broadcast endpoint. The compliance window between broadcast and on-chain finality is unmonitored.
Each gap has a fix. Here's the architecture.
Layer 1 — Pre-Payment Address Screening
Use the Verify Address API to screen every payer and payee before your transaction preparation flow begins.
async function screenAddress(blockchain, network, address) {
const response = await fetch(
`https://rest.cryptoapis.io/compliance/verify-address/${blockchain}/${network}/${address}`,
{
headers: {
'X-API-Key': process.env.CRYPTO_APIS_KEY,
'Content-Type': 'application/json'
}
}
);
const data = await response.json();
if (data.item.riskScore > RISK_THRESHOLD || data.item.isSanctioned) {
throw new ComplianceError({
address,
verdict: data.item.riskScore,
listMatches: data.item.sanctionsMatches,
timestamp: new Date().toISOString()
});
}
return { pass: true, metadata: data.item };
}
This covers 20+ chains — same function, same schema. You write it once.
Layer 2 — Continuous Monitoring with Blockchain Events
Subscribe to all active customer addresses using the Blockchain Events API. When an event fires, screen the counterparty addresses in that transaction.
async function subscribeToAddressEvents(blockchain, address, callbackUrl) {
const response = await fetch(
`https://rest.cryptoapis.io/blockchain-events/${blockchain}/mainnet/subscriptions/address-coins-transactions`,
{
method: 'POST',
headers: { 'X-API-Key': process.env.CRYPTO_APIS_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({
context: "compliance-monitoring",
callbackSecretKey: process.env.WEBHOOK_SECRET,
callbackUrl,
address,
confirmations: 1
})
}
);
return response.json();
}
// Webhook handler — fires on every incoming tx
app.post('/webhooks/blockchain-events', async (req, res) => {
const event = req.body;
const counterpartyAddresses = extractCounterparties(event);
const screeningResults = await Promise.all(
counterpartyAddresses.map(addr =>
screenAddress(event.blockchain, 'mainnet', addr)
)
);
await logComplianceEvent({
eventId: event.transactionId,
addresses: counterpartyAddresses,
results: screeningResults,
blockHeight: event.blockHeight,
timestamp: event.minedInBlockTimestamp
});
res.status(200).send('OK');
});
Layer 3 — Enhanced Due Diligence for Large Flows
For payments above your EDD threshold, pull full transaction history using Address History and Transactions Data.
async function runEnhancedDueDiligence(blockchain, address, lookbackDays = 90) {
const historyResponse = await fetch(
`https://rest.cryptoapis.io/blockchain-data/${blockchain}/mainnet/addresses/${address}/transactions?limit=50`,
{ headers: { 'X-API-Key': process.env.CRYPTO_APIS_KEY } }
);
const history = await historyResponse.json();
const cutoff = Date.now() - (lookbackDays * 86400 * 1000);
const counterparties = new Set();
history.data.items
.filter(tx => tx.timestamp * 1000 > cutoff)
.forEach(tx => {
tx.senders?.forEach(s => counterparties.add(s.address));
tx.recipients?.forEach(r => counterparties.add(r.address));
});
const results = await Promise.all(
[...counterparties].map(addr => screenAddress(blockchain, 'mainnet', addr))
);
return { address, counterpartiesAnalyzed: counterparties.size, results };
}
The Broadcast vs. Finality Window
Configure Blockchain Events subscriptions to fire at your required confirmation threshold — not just at broadcast:
body: JSON.stringify({
address,
confirmations: 3, // Don't release until 3 confirmations
callbackUrl: '/webhooks/confirmation-gate'
})
The MiCA Audit Log Schema
{
"eventId": "uuid-v4",
"type": "ADDRESS_SCREENING",
"address": "0x...",
"blockchain": "ethereum",
"timestamp": "2026-06-03T14:22:31Z",
"listVersion": "OFAC-20260603",
"riskScore": 12,
"sanctionsMatch": false,
"associatedTransactionId": "0x...",
"decisionOutcome": "PASS",
"decisionTimestamp": "2026-06-03T14:22:31.082Z",
"operatorId": "system-automated"
}
Getting Started
- Sign up for Crypto APIs — free tier available
- Read the API overview
- Wire Layer 1 first (Verify Address) — one endpoint, immediate coverage
- Add Layer 2 (Blockchain Events) for continuous monitoring
- Add Layer 3 trigger logic at your EDD threshold
Full blog post with architecture diagrams: cryptoapis.io/blog
Have questions about multi-chain compliance architecture? Drop them in the comments.
Top comments (0)