Due Diligence Renforcée (EDD) automatisée : guide 2025 pour CGP et Fintech
Automatisez votre Due Diligence Renforcée (EDD) : critères déclencheurs, workflows par segment, APIs, preuves d'audit et ROI. Guide complet CGP/Fintech 2025.
Guide technique d'intégration API KYC pour Fintech/PSP/PSAN : policy-as-code, webhooks temps réel, observabilité et conformité scalable.
En résumé : Intégrez la surveillance KYC continue dans votre stack technique via API REST, policy-as-code versionnée et observabilité complète. Voir la documentation API →
Les Fintech/PSP/PSAN ont des besoins spécifiques qui diffèrent des CGP :
graph TD
A[Votre App] -->|REST API| B[Swiftgum API Gateway]
B --> C[Surveillance Engine]
B --> D[Policy Engine]
B --> E[Case Management]
C -->|Webhooks| A
D -->|Policy Updates| A
E -->|Audit Exports| A
F[INPI] --> C
G[Sirene] --> C
H[Sanctions] --> C
I[RBE] --> C
Benefits identifiés :
curl -X POST https://api.swiftgum.com/auth/token \
-H "Content-Type: application/json" \
-d '{
"client_id": "your_client_id",
"client_secret": "your_client_secret",
"scope": "kyc:read kyc:write webhooks:manage"
}'
Réponse :
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "kyc:read kyc:write webhooks:manage"
}
curl -X POST https://api.swiftgum.com/v1/entities \
-H "Authorization: Bearer your_access_token" \
-H "Content-Type: application/json" \
-d '{
"external_id": "customer_12345",
"type": "individual",
"data": {
"first_name": "Jean",
"last_name": "Martin",
"date_of_birth": "1985-03-15",
"nationality": "FR",
"document": {
"type": "national_id",
"number": "850315123456",
"expiry_date": "2030-03-15"
}
},
"risk_profile": "medium",
"monitoring_level": "enhanced"
}'
curl -X PUT https://api.swiftgum.com/v1/entities/customer_12345/monitoring \
-H "Authorization: Bearer your_access_token" \
-d '{
"sources": ["sanctions", "pep", "adverse_media"],
"frequency": "realtime",
"thresholds": {
"sanctions": 0.0,
"pep": 0.3,
"adverse_media": 0.7
}
}'
curl https://api.swiftgum.com/v1/entities/customer_12345/status \
-H "Authorization: Bearer your_access_token"
Réponse :
{
"entity_id": "customer_12345",
"risk_score": 0.25,
"status": "approved",
"last_updated": "2025-01-15T10:30:00Z",
"alerts": [],
"monitoring_status": "active",
"next_review": "2025-07-15T10:30:00Z"
}
Fichier : kyc-policy-v2.1.yaml
apiVersion: "kyc.swiftgum.com/v1"
kind: Policy
metadata:
name: "fintech-standard"
version: "2.1"
namespace: "production"
spec:
risk_assessment:
individual:
sanctions:
weight: 0.4
sources: ["ofac", "eu", "un"]
threshold_reject: 0.0
pep:
weight: 0.3
include_family: true
family_multiplier: 0.6
threshold_enhanced: 0.3
adverse_media:
weight: 0.2
recency_days: 90
threshold_review: 0.7
document_verification:
weight: 0.1
required_documents: ["id", "proof_address"]
id_verification_level: "government_issued"
corporate:
ownership_transparency:
weight: 0.5
ultimate_beneficial_owner: true
threshold_percentage: 25.0
sanctions_screening:
weight: 0.3
include_directors: true
include_shareholders: true
adverse_media:
weight: 0.2
lookback_years: 2
monitoring:
frequency:
low_risk: "quarterly"
medium_risk: "monthly"
high_risk: "weekly"
triggers:
- "sanctions_list_update"
- "pep_list_update"
- "director_change"
- "ownership_change_25_percent"
actions:
approve:
conditions: "risk_score < 0.3"
automatic: true
review:
conditions: "risk_score >= 0.3 AND risk_score < 0.7"
sla_hours: 24
reject:
conditions: "risk_score >= 0.7"
automatic: true
require_justification: true
# Upload de la nouvelle politique
curl -X POST https://api.swiftgum.com/v1/policies \
-H "Authorization: Bearer your_access_token" \
-H "Content-Type: application/yaml" \
--data-binary @kyc-policy-v2.1.yaml
# Test de la politique sur un subset
curl -X POST https://api.swiftgum.com/v1/policies/fintech-standard:2.1/test \
-d '{
"entities": ["customer_12345", "customer_67890"],
"dry_run": true
}'
# Déploiement progressif (10% -> 50% -> 100%)
curl -X POST https://api.swiftgum.com/v1/policies/fintech-standard:2.1/deploy \
-d '{
"strategy": "canary",
"percentage": 10,
"rollback_threshold": 0.05
}'
curl -X POST https://api.swiftgum.com/v1/webhooks \
-H "Authorization: Bearer your_access_token" \
-d '{
"url": "https://yourapp.com/webhooks/kyc",
"events": [
"risk_score_updated",
"alert_created",
"document_expired",
"monitoring_status_changed"
],
"secret": "your_webhook_secret",
"retry_policy": {
"max_attempts": 3,
"backoff": "exponential"
}
}'
Payload d'exemple :
{
"event": "risk_score_updated",
"timestamp": "2025-01-15T14:30:00Z",
"webhook_id": "wh_123456",
"data": {
"entity_id": "customer_12345",
"previous_score": 0.25,
"new_score": 0.75,
"trigger": "sanctions_list_match",
"policy_version": "2.1",
"rationale": {
"primary_reason": "Match on OFAC list",
"confidence": 0.95,
"evidence": {
"source": "ofac_sdn_2025_01_15",
"match_score": 0.98,
"matched_fields": ["full_name", "date_of_birth"]
}
},
"recommended_action": "immediate_review"
}
}
Handler côté client :
from flask import Flask, request
import hmac, hashlib
app = Flask(__name__)
@app.route('/webhooks/kyc', methods=['POST'])
def handle_kyc_webhook():
# Vérification de la signature
signature = request.headers.get('X-Swiftgum-Signature')
expected = hmac.new(
webhook_secret.encode(),
request.data,
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(signature, f"sha256={expected}"):
return "Invalid signature", 401
payload = request.json
event_type = payload['event']
if event_type == 'risk_score_updated':
handle_risk_score_update(payload['data'])
elif event_type == 'alert_created':
handle_new_alert(payload['data'])
return "OK", 200
def handle_risk_score_update(data):
entity_id = data['entity_id']
new_score = data['new_score']
# Logique métier
if new_score > 0.7:
suspend_customer(entity_id)
notify_compliance_team(data)
elif new_score > 0.3:
flag_for_review(entity_id)
# Métriques globales
curl https://api.swiftgum.com/v1/metrics \
-H "Authorization: Bearer your_access_token"
Réponse :
{
"period": "last_30_days",
"entities_monitored": 45678,
"alerts_generated": 234,
"false_positive_rate": 0.12,
"true_positive_rate": 0.89,
"mean_time_to_resolution_hours": 6.5,
"api_performance": {
"avg_response_time_ms": 145,
"p95_response_time_ms": 280,
"p99_response_time_ms": 450,
"uptime_percentage": 99.95
},
"source_coverage": {
"inpi": 99.8,
"sirene": 99.9,
"sanctions": 100.0,
"rbe": 98.5
}
}
Dashboard JSON snippet :
{
"dashboard": {
"title": "Swiftgum KYC Monitoring",
"panels": [
{
"title": "False Positive Rate",
"type": "stat",
"targets": [{
"expr": "swiftgum_false_positive_rate",
"legendFormat": "FPR"
}],
"thresholds": [
{"value": 0.15, "color": "red"},
{"value": 0.10, "color": "yellow"},
{"value": 0.05, "color": "green"}
]
}
]
}
}
Exemple d'alerte :
# prometheus/alerts.yml
groups:
- name: kyc_slos
rules:
- alert: HighFalsePositiveRate
expr: swiftgum_false_positive_rate > 0.20
for: 15m
annotations:
summary: "FPR above threshold"
description: "False positive rate {{ $value }} exceeds 20%"
- alert: SlowAPIResponse
expr: swiftgum_api_response_time_p95 > 500
for: 5m
annotations:
summary: "API response time degraded"
1. API Keys (développement)
curl https://api.swiftgum.com/v1/entities \
-H "X-API-Key: sk_live_1234567890abcdef"
2. OAuth 2.0 + JWT (production)
# Récupération du token
curl -X POST https://api.swiftgum.com/oauth/token \
-d "grant_type=client_credentials" \
-d "client_id=your_client_id" \
-d "client_secret=your_client_secret"
# Utilisation
curl https://api.swiftgum.com/v1/entities \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc..."
3. mTLS (Enterprise)
curl https://api.swiftgum.com/v1/entities \
--cert client.crt \
--key client.key \
--cacert ca.crt
En transit :
Au repos :
Audit trail :
Flux typique :
Implémentation :
def onboard_customer(customer_data):
# Appel API synchrone
response = kyc_api.check_customer(customer_data)
if response.risk_score < 0.3:
return create_account(customer_data)
elif response.risk_score < 0.7:
return request_additional_docs(customer_data, response.missing_docs)
else:
log_rejection(customer_data, response.rationale)
return reject_application()
Besoins spécifiques :
Architecture :
# Webhook handler pour changements de risque
@app.route('/webhook/merchant-risk')
def handle_merchant_risk_change():
data = request.json
merchant_id = data['entity_id']
new_risk = data['new_score']
if new_risk > 0.8:
# Suspension immédiate
payment_processor.suspend_merchant(merchant_id)
# Notification équipe risque
risk_team.notify(
f"Merchant {merchant_id} suspended - risk score: {new_risk}"
)
# Log pour audit
audit_logger.log({
'action': 'merchant_suspended',
'merchant_id': merchant_id,
'risk_score': new_risk,
'timestamp': datetime.utcnow()
})
Particularités crypto :
Intégration :
def analyze_crypto_transaction(tx_data):
# Enrichissement via API KYC
sender_risk = kyc_api.screen_address(tx_data.sender_address)
receiver_risk = kyc_api.screen_address(tx_data.receiver_address)
# Analyse comportementale
pattern_risk = kyc_api.analyze_transaction_pattern({
'amount': tx_data.amount,
'frequency': tx_data.sender_frequency,
'time_of_day': tx_data.timestamp.hour
})
# Décision composite
total_risk = max(sender_risk, receiver_risk, pattern_risk)
if total_risk > 0.7:
return block_transaction(tx_data, total_risk)
else:
return approve_transaction(tx_data)
Objectif : Valider la solution sans impact métier
def hybrid_kyc_check(customer_data):
# Système existant (décision)
legacy_result = legacy_kyc_system.check(customer_data)
# Swiftgum API (validation)
try:
swiftgum_result = kyc_api.check_customer(customer_data)
# Comparaison pour métriques
compare_results(legacy_result, swiftgum_result)
except Exception as e:
# Pas d'impact sur le flux principal
logger.error(f"Swiftgum API error: {e}")
# Décision basée sur le legacy
return legacy_result
Canary deployment par segment :
def smart_kyc_routing(customer_data):
customer_segment = determine_segment(customer_data)
# Configuration du rollout
rollout_config = {
'premium': 0.10, # 10% des clients premium
'standard': 0.05, # 5% des clients standard
'basic': 0.01 # 1% des clients basic
}
if should_use_swiftgum(customer_segment, rollout_config):
return kyc_api.check_customer(customer_data)
else:
return legacy_kyc_system.check(customer_data)
Checklist de validation :
1. Gestion des erreurs
@retry(max_attempts=3, backoff=exponential_backoff)
def resilient_kyc_check(customer_data):
try:
return kyc_api.check_customer(customer_data)
except RateLimitError:
# Circuit breaker pattern
return fallback_to_manual_review(customer_data)
except APIError as e:
if e.is_retryable():
raise # Déclenche le retry
else:
return handle_permanent_error(customer_data, e)
2. Caching intelligent
def cached_kyc_check(customer_id):
# Cache Redis avec TTL adaptatif
cache_key = f"kyc_result:{customer_id}"
cached_result = redis_client.get(cache_key)
if cached_result and not is_cache_stale(cached_result):
return cached_result
# Fresh API call
result = kyc_api.check_customer(customer_id)
# TTL basé sur le risk score
ttl = 3600 if result.risk_score < 0.3 else 900 # 1h vs 15min
redis_client.setex(cache_key, ttl, result)
return result
L'intégration API-first transforme le KYC d'un centre de coût en avantage concurrentiel pour les Fintech. L'orchestration automatisée (surveillance → scoring → action → audit) permet de scaler sans friction tout en maintenant la conformité réglementaire.
Pour maîtriser l'architecture des intégrations multi-sources et automatiser la Due Diligence Renforcée dans vos workflows API, consultez nos guides techniques complémentaires.
Les 3 piliers du succès :
Le passage à l'API KYC perpétuel n'est plus une option pour les scale-ups financières : c'est une nécessité stratégique face à l'accélération réglementaire.
Moins de faux positifs, moins de relances inutiles, plus de dossiers complets. Exports prêts-contrôle AMF/ACPR en quelques clics.
Python SDK
pip install swiftgum-kyc
Node.js SDK
npm install @swiftgum/kyc-sdk
Documentation complète : api.swiftgum.com/docs Playground interactif : api.swiftgum.com/playground Status page : status.swiftgum.com
Moins de faux positifs, moins de relances inutiles, plus de dossiers complets. Exports prêts-contrôle AMF/ACPR en quelques clics.