Fintech Compliance Software: KYC, AML, PCI DSS, and SOC 2 for Financial Applications
Build compliant fintech software with KYC/AML workflows, PCI DSS card data handling, SOC 2 controls, and open banking integrations. Includes architecture diagra
Fintech Compliance Software: KYC, AML, PCI DSS, and SOC 2 for Financial Applications
Compliance is the primary reason fintech software costs more to build and maintain than a standard SaaS product. It's also the primary reason fintech products take longer to launch, and why cutting corners on compliance creates existential risk rather than just technical debt.
This guide covers the four compliance frameworks most relevant to financial software โ what each requires, how to implement the technical controls, and what it costs to do it properly.
The Compliance Stack for Fintech
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ User Interface โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ KYC/KYB Layer โ AML Screening โ Fraud โ
โ (Identity verify) โ (Transaction) โ Detection โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Application Logic โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ PCI DSS Scope โ Audit Logging โ Encryption โ
โ (Card Data) โ (Immutable) โ at Rest/TLS โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ SOC 2 Controls (Pervasive) โ
โ Access Control โ Monitoring โ Incident Response โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Each layer has regulatory requirements, technical controls, and operational processes. The layers interact: your AML screening depends on having solid KYC data; your PCI scope depends on how you handle card data; your SOC 2 audit covers all of it.
KYC/KYB: Identity Verification
Know Your Customer (KYC) for individuals, Know Your Business (KYB) for companies โ these are the requirements to verify who you're doing business with before allowing financial activity.
KYC data collected:
- Full legal name
- Date of birth
- Government-issued ID (passport, driver's license) โ document scan + liveness check
- Address proof
- SSN or equivalent national ID (for US)
- Source of funds (for higher-risk customers)
The implementation choice: Build vs buy for identity verification.
| Approach | Vendors | Cost | Build Time |
|---|---|---|---|
| API-based IDV | Persona, Onfido, Jumio, Stripe Identity | $1โ5 per verification | 2โ4 weeks integration |
| Self-built | Tesseract OCR + face matching library | Engineering + compliance overhead | 6โ12 months |
| Banking-as-a-Service | Unit, Treasury Prime, Synapse | Bundled in BaaS pricing | 4โ8 weeks total |
Build the KYC workflow, buy the identity verification engine. Building OCR + liveness detection is a compliance and fraud liability, not a competitive differentiator.
KYC status machine:
// types/kyc.ts
type KycStatus =
| 'NOT_STARTED'
| 'PENDING' // User started, not submitted
| 'SUBMITTED' // Documents sent for review
| 'MANUAL_REVIEW' // Flagged for human review
| 'APPROVED'
| 'REJECTED'
| 'EXPIRED'; // Re-verification required (typically every 1โ2 years)
interface KycRecord {
id: string;
userId: string;
status: KycStatus;
riskLevel: 'low' | 'medium' | 'high';
verificationProvider: 'persona' | 'onfido' | 'manual';
externalVerificationId?: string;
documents: KycDocument[];
reviewNotes?: string;
approvedAt?: Date;
expiresAt?: Date;
createdAt: Date;
updatedAt: Date;
}
// services/kyc.ts
export async function initiateKyc(userId: string): Promise<string> {
// Create Persona inquiry
const inquiry = await persona.inquiries.create({
'inquiry-template-id': process.env.PERSONA_TEMPLATE_ID!,
meta: { user_id: userId },
});
await db.kycRecord.create({
data: {
userId,
status: 'PENDING',
verificationProvider: 'persona',
externalVerificationId: inquiry.id,
},
});
return inquiry.attributes['session-token']; // Pass to frontend SDK
}
// Handle Persona webhook
export async function handlePersonaWebhook(event: PersonaEvent) {
const inquiry = event.data.attributes;
const userId = event.data.attributes.meta?.user_id;
const newStatus: KycStatus =
inquiry.status === 'approved' ? 'APPROVED' :
inquiry.status === 'declined' ? 'REJECTED' :
inquiry.status === 'needs_review' ? 'MANUAL_REVIEW' :
'SUBMITTED';
await db.kycRecord.updateMany({
where: { externalVerificationId: event.data.id },
data: {
status: newStatus,
riskLevel: mapRiskScore(inquiry['risk-score']),
approvedAt: newStatus === 'APPROVED' ? new Date() : undefined,
expiresAt: newStatus === 'APPROVED'
? addYears(new Date(), 2)
: undefined,
},
});
if (newStatus === 'APPROVED') {
await enableFinancialFeatures(userId);
}
}
๐ค Can This Strategy Be Automated?
In 2026, top traders run custom EAs โ not manual charts. We build MT4/MT5 Expert Advisors that execute your exact strategy 24/7, pass prop firm challenges, and eliminate emotional decisions.
- Runs 24/7 โ no screen time, no missed entries
- Prop-firm compliant (FTMO, MFF, TFT drawdown rules)
- MyFXBook-verified backtest results included
- From strategy brief to live EA in 2โ4 weeks
AML: Transaction Monitoring
Anti-Money Laundering (AML) requirements mandate that you screen customers against sanctions lists, monitor transactions for suspicious patterns, and file Suspicious Activity Reports (SARs) with FinCEN.
Sanctions screening (must happen at onboarding and on every transaction):
// services/sanctions.ts
import { OfacClient } from 'ofac-api-client'; // Or use Chainalysis, Elliptic, ComplyAdvantage
const ofac = new OfacClient({ apiKey: process.env.OFAC_API_KEY! });
interface SanctionsResult {
clear: boolean;
matches: SanctionsMatch[];
screeningId: string;
}
export async function screenEntity(entity: {
name: string;
dateOfBirth?: string;
country?: string;
taxId?: string;
}): Promise<SanctionsResult> {
const result = await ofac.search({
name: entity.name,
dob: entity.dateOfBirth,
country: entity.country,
minScore: 85, // 85%+ match score triggers review
});
// Log every screening โ required for compliance audit
const screening = await db.sanctionsScreening.create({
data: {
entityName: entity.name,
clear: result.matches.length === 0,
matchCount: result.matches.length,
rawResult: result,
screenedAt: new Date(),
},
});
if (result.matches.length > 0) {
await alertComplianceTeam(screening.id, result.matches);
}
return {
clear: result.matches.length === 0,
matches: result.matches,
screeningId: screening.id,
};
}
// Transaction monitoring rules
export async function assessTransactionRisk(transaction: {
userId: string;
amount: number; // In cents
type: 'deposit' | 'withdrawal' | 'transfer';
counterparty?: string;
}): Promise<{ riskScore: number; flags: string[] }> {
const flags: string[] = [];
let riskScore = 0;
// Rule 1: Large cash transactions (CTR threshold: $10,000)
if (transaction.amount >= 1_000_000) { // $10,000 in cents
flags.push('CTR_THRESHOLD');
riskScore += 40;
}
// Rule 2: Structuring detection (multiple transactions just below CTR threshold)
const recentTotal = await getRecentTransactionTotal(
transaction.userId,
24 // hours
);
if (recentTotal + transaction.amount >= 950_000 &&
transaction.amount < 1_000_000) {
flags.push('POSSIBLE_STRUCTURING');
riskScore += 60;
}
// Rule 3: Velocity โ too many transactions too fast
const txCount = await getTransactionCount(transaction.userId, 1); // 1 hour
if (txCount > 10) {
flags.push('HIGH_VELOCITY');
riskScore += 30;
}
// Rule 4: Round amounts (often indicator of structured payments)
if (transaction.amount % 100_000 === 0 && transaction.amount >= 500_000) {
flags.push('ROUND_AMOUNT');
riskScore += 10;
}
return { riskScore, flags };
}
SAR filing requirement: If a transaction is suspicious and exceeds $5,000 (or $2,000 for certain businesses), you must file a SAR with FinCEN within 30 days of detection. This is a regulatory obligation with criminal penalties for willful failure.
PCI DSS: Card Data Handling
PCI DSS (Payment Card Industry Data Security Standard) governs how you handle cardholder data. The most important rule: don't store card numbers (PAN). Let your payment processor handle it.
PCI scope reduction with Stripe Elements:
// โ NEVER do this โ storing raw card data puts you in full PCI scope
const card = {
number: req.body.cardNumber, // Never touch this
expiry: req.body.expiry,
cvv: req.body.cvv,
};
// โ
Use tokenization โ card data never touches your server
// Frontend: Stripe Elements handles card input
// Your server receives only the PaymentMethod ID
// server/api/payment-methods.ts
export async function POST(request: Request) {
const { paymentMethodId, userId } = await request.json();
// Attach the payment method to a Stripe Customer
const customer = await getOrCreateStripeCustomer(userId);
await stripe.paymentMethods.attach(paymentMethodId, {
customer: customer.stripeCustomerId,
});
// Store only the Stripe token reference โ not card data
await db.paymentMethod.create({
data: {
userId,
stripePaymentMethodId: paymentMethodId, // Safe to store
// NEVER store: card number, CVV, full expiry
},
});
return Response.json({ success: true });
}
PCI compliance levels by transaction volume:
| Level | Annual Transactions | Requirement |
|---|---|---|
| Level 1 | > 6 million | Annual QSA audit + quarterly network scans |
| Level 2 | 1โ6 million | Annual SAQ + quarterly scans |
| Level 3 | 20,000โ1 million (e-commerce) | Annual SAQ + quarterly scans |
| Level 4 | < 20,000 (e-commerce) | Annual SAQ |
Using Stripe/Braintree/Adyen without storing card data puts you in SAQ-A (the simplest questionnaire). Handling card data directly triggers SAQ-D or a full QSA audit.
๐ Stop Trading Manually โ Let AI Do It
While you sleep, your EA keeps working. Viprasol builds prop-firm-compliant Expert Advisors with strict risk management, real backtests, and live deployment support.
- No rule violations โ daily drawdown, max drawdown, consistency rules built in
- Covers MT4, MT5, cTrader, and Python-based algos
- 5.0โ Upwork record โ 100% job success rate
- Free strategy consultation before we write a single line
SOC 2: Trust Service Criteria
SOC 2 is an audit framework covering five trust criteria: Security, Availability, Processing Integrity, Confidentiality, and Privacy. Most B2B fintech customers require SOC 2 Type II certification.
SOC 2 technical controls to implement early:
// 1. Immutable audit logging โ every sensitive action logged
// services/auditLog.ts
export async function logAuditEvent(event: {
actorId: string;
actorType: 'user' | 'admin' | 'system';
action: string;
resourceType: string;
resourceId: string;
before?: unknown;
after?: unknown;
ipAddress?: string;
userAgent?: string;
}) {
// Write to append-only table โ no UPDATE/DELETE allowed
await db.$executeRaw`
INSERT INTO audit_log (
actor_id, actor_type, action, resource_type, resource_id,
before_state, after_state, ip_address, user_agent, occurred_at
) VALUES (
${event.actorId}, ${event.actorType}, ${event.action},
${event.resourceType}, ${event.resourceId},
${JSON.stringify(event.before)}, ${JSON.stringify(event.after)},
${event.ipAddress}, ${event.userAgent}, NOW()
)
`;
}
// Postgres: restrict DELETE on audit_log via row-level security
// CREATE POLICY audit_log_no_delete ON audit_log FOR DELETE USING (false);
# 2. Encryption at rest โ AWS RDS encryption config (Terraform)
resource "aws_db_instance" "primary" {
engine = "postgres"
engine_version = "16.1"
storage_encrypted = true # AES-256 encryption at rest
kms_key_id = aws_kms_key.rds.arn
backup_retention_period = 30 # 30-day backups
deletion_protection = true # Prevent accidental deletion
# Enable enhanced monitoring
monitoring_interval = 60
monitoring_role_arn = aws_iam_role.rds_monitoring.arn
}
SOC 2 controls summary:
| Control | Implementation |
|---|---|
| Access control | MFA for all admin access, RBAC, quarterly access reviews |
| Encryption | TLS 1.3 in transit, AES-256 at rest, KMS key management |
| Audit logging | Immutable audit trail for all sensitive operations |
| Vulnerability management | Weekly dependency scans, monthly pen tests |
| Incident response | Documented IR plan, < 4h detection SLA |
| Change management | All prod changes via PR + approval |
| Availability | 99.9% SLA, RTO < 4h, RPO < 1h |
Compliance Cost Reality
| Compliance | One-Time Build | Annual Ongoing | Who Does It |
|---|---|---|---|
| KYC integration (Persona) | $15,000โ40,000 | $1โ5/verification + $2,000โ5,000/mo platform | Engineering + Compliance |
| AML transaction monitoring | $20,000โ60,000 | $500โ2,000/mo (self) or $2,000โ8,000/mo (vendor) | Engineering + Compliance Officer |
| PCI SAQ-A (no card storage) | $3,000โ8,000 | $1,000โ3,000/year (SAQ + scans) | Engineering + Assessor |
| PCI Level 1/2 (storing cards) | $100,000โ300,000 | $30,000โ100,000/year (QSA audit) | QSA + Engineering |
| SOC 2 Type I | $30,000โ80,000 | โ | Auditor ($20โ50K) + Engineering |
| SOC 2 Type II | $60,000โ150,000 | $30,000โ80,000/year renewal | Auditor + ongoing controls |
The compounding advantage of getting compliance right early: Companies that implement proper KYC, AML, and audit logging from day one spend 40โ60% less on their first SOC 2 audit than those who retrofit controls onto an existing system.
Working With Viprasol
We build fintech software with compliance requirements built into the architecture from the start โ not retrofitted before an audit. Our experience includes payment platforms, lending software, and investment tools with KYC, AML, PCI, and SOC 2 requirements.
We also help teams navigate the compliance landscape: determining which requirements apply, selecting vendors, and implementing technical controls that satisfy auditors while keeping the product moving.
โ Talk to our fintech team about your compliance requirements.
See Also
- Payment Gateway Integration โ Stripe integration basics
- Stripe Connect Marketplace โ platform payment flows
- API Security Best Practices โ securing financial APIs
- SaaS Security Best Practices โ application security controls
- Trading Software Development โ financial application development
About the Author
Viprasol Tech Team
Custom Software Development Specialists
The Viprasol Tech team specialises in algorithmic trading software, AI agent systems, and SaaS development. With 100+ projects delivered across MT4/MT5 EAs, fintech platforms, and production AI systems, the team brings deep technical experience to every engagement. Based in India, serving clients globally.
Ready to Automate Your Trading?
Get a custom Expert Advisor built by professionals with verified MyFXBook results.
Free consultation โข No commitment โข Response within 24 hours
Need a custom EA or trading bot built?
We specialise in MT4/MT5 Expert Advisor development โ prop-firm compliant, forward-tested before live, MyFXBook verifiable. 5.0โ Upwork, 100% Job Success, 100+ projects shipped.