Evidence Chain & Source Traceability
Every match returned by SanctionsWise API includes a complete evidence chain, providing full audit trail for regulatory compliance and internal investigations.
Why Evidence Chain Matters​
Regulatory Requirements​
Financial institutions must demonstrate due diligence in their sanctions compliance programs:
- BSA/AML: Bank Secrecy Act requires documented screening processes
- OFAC Compliance: Must show source of sanctions information
- FINRA: Broker-dealers need auditable compliance records
- European Regulations: GDPR requires data provenance tracking
SanctionsWise Evidence Chain​
Every match includes:
- Source Authority - Who published the sanctions list
- Source List ID - Which specific list the entity appears on
- Source Entry UID - Original identifier from the authority
- Data Timestamps - When data was retrieved and last updated
- Match Details - How the match was determined
Evidence Chain Structure​
Complete Match Response​
{
"screening_id": "SCR-20251210185252-2FFDC8AE",
"status": "potential_match",
"query": {
"name": "Vladimir Putin",
"entity_type": "individual",
"threshold": 0.60,
"lists_screened": ["ofac_sdn"]
},
"matches": [
{
"entity_id": "sw_ofac_sdn_35096",
"matched_name": "VLADIMIR VLADIMIROVICH PUTIN",
"confidence_score": 0.7714,
"match_type": "fuzzy+semantic",
"semantic_score": 0.89,
"entity_details": {
"primary_name": "VLADIMIR VLADIMIROVICH PUTIN",
"entity_type": "individual",
"nationality": "Russia",
"programs": ["RUSSIA-EO14024", "UKRAINE-EO13660"],
"listing_date": "2022-02-25"
},
"source_evidence": {
"source_authority": "US Treasury OFAC",
"source_list_id": "ofac_sdn",
"source_entry_uid": "sw_ofac_sdn_35096",
"last_updated": "2025-12-10T17:26:38Z"
},
"identifier_evidence": {
"match_type": "exact",
"query_type": "passport",
"entity_type": "passport_number",
"confidence": 1.0,
"matched_value": "AB12***"
}
}
],
"timestamp": "2025-12-10T18:52:52.527387Z",
"processing_time_ms": 378,
"data_freshness": {
"last_update": "2025-12-10T17:26:38Z"
}
}
Evidence Components​
1. Screening Identification​
| Field | Description | Example |
|---|---|---|
| screening_id | Unique request identifier | SCR-20251210185252-2FFDC8AE |
| timestamp | When screening was performed | 2025-12-10T18:52:52.527387Z |
Purpose: Links the screening request to audit logs and compliance records.
2. Query Context​
"query": {
"name": "Vladimir Putin",
"entity_type": "individual",
"threshold": 0.60,
"lists_screened": ["ofac_sdn"]
}
| Field | Description |
|---|---|
| name | Original query submitted |
| entity_type | Classification used for matching |
| threshold | Confidence cutoff applied |
| lists_screened | Which sanctions lists were checked |
Purpose: Documents exactly what was searched and how.
3. Source Authority​
"source_evidence": {
"source_authority": "US Treasury OFAC",
"source_list_id": "ofac_sdn",
"source_entry_uid": "sw_ofac_sdn_35096",
"last_updated": "2025-12-10T17:26:38Z"
}
| Field | Description |
|---|---|
| source_authority | Government body that issued the sanctions |
| source_list_id | Specific list within that authority |
| source_entry_uid | Original entry identifier |
| last_updated | When entity data was last modified |
Purpose: Traces match back to authoritative government source.
4. Match Methodology​
{
"confidence_score": 0.7714,
"match_type": "fuzzy+semantic",
"semantic_score": 0.89
}
| Field | Description |
|---|---|
| confidence_score | Combined confidence (0.0-1.0) |
| match_type | How match was determined |
| semantic_score | AI similarity score (if used) |
Match Types:
exact- Direct name match after normalizationfuzzy- String similarity algorithmsfuzzy+semantic- Enhanced with AI vectorssemantic- Found via contextual searchidentifier_confirmed- Document number match
Purpose: Explains why this was flagged as a match.
5. Data Freshness​
"data_freshness": {
"last_update": "2025-12-10T17:26:38Z"
}
Purpose: Proves sanctions data was current at time of screening.
Source Authorities​
Supported Authorities​
| Authority | Lists | Update Frequency |
|---|---|---|
| US Treasury OFAC | SDN, Consolidated, FSE, SSI | Real-time to daily |
| US Commerce BIS | Entity List, Denied Persons | Weekly |
Authority Verification​
Each entity's source can be verified against original government publications:
| List | Verification URL |
|---|---|
| OFAC SDN | https://sanctionslist.ofac.treas.gov/ |
| OFAC Consolidated | https://www.treasury.gov/ofac/downloads/ |
| BIS Entity List | https://www.bis.doc.gov/index.php/the-denied-persons-list |
Audit Trail Best Practices​
1. Store Complete Responses​
Always store the full API response for compliance records:
import json
from datetime import datetime
def screen_and_log(name, entity_type):
result = screen_entity(name, entity_type)
# Store complete audit record
audit_record = {
"screening_id": result["screening_id"],
"request_time": datetime.utcnow().isoformat(),
"query": result["query"],
"status": result["status"],
"match_count": result["match_count"],
"matches": result["matches"],
"data_freshness": result["data_freshness"]
}
save_to_audit_database(audit_record)
return result
2. Log Decision Points​
Document when matches require escalation:
def process_screening_result(result):
if result["status"] == "clear":
log_decision("APPROVED", result["screening_id"], "No matches")
elif result["status"] == "match":
log_decision("BLOCKED", result["screening_id"],
f"High-confidence match: {result['matches'][0]['matched_name']}")
escalate_to_compliance(result)
elif result["status"] == "potential_match":
log_decision("REVIEW_REQUIRED", result["screening_id"],
f"{result['match_count']} potential matches")
queue_for_manual_review(result)
3. Maintain Evidence Retention​
Keep screening records for required retention periods:
| Regulation | Retention Period |
|---|---|
| BSA/AML | 5 years |
| OFAC | 5 years |
| GDPR | As long as necessary |
4. Regular Data Freshness Checks​
Verify screening was performed against current data:
from datetime import datetime, timedelta
def validate_data_freshness(result):
last_update = datetime.fromisoformat(
result["data_freshness"]["last_update"].replace("Z", "+00:00")
)
age_hours = (datetime.utcnow() - last_update.replace(tzinfo=None)).seconds / 3600
if age_hours > 24:
log_warning(f"Screening used data {age_hours:.1f} hours old")
return age_hours < 24
Compliance Reporting​
Generate Audit Report​
def generate_compliance_report(screenings):
"""Generate compliance audit report from screening records."""
report = {
"report_date": datetime.utcnow().isoformat(),
"total_screenings": len(screenings),
"status_breakdown": {
"clear": sum(1 for s in screenings if s["status"] == "clear"),
"match": sum(1 for s in screenings if s["status"] == "match"),
"potential_match": sum(1 for s in screenings if s["status"] == "potential_match")
},
"sources_used": list(set(
s["query"]["lists_screened"][0]
for s in screenings
)),
"average_confidence": sum(
s["matches"][0]["confidence_score"]
for s in screenings if s["matches"]
) / max(1, sum(1 for s in screenings if s["matches"]))
}
return report
Sample Audit Report​
SANCTIONS SCREENING AUDIT REPORT
================================
Report Date: 2025-12-10T19:00:00Z
Reporting Period: 2025-12-01 to 2025-12-10
SCREENING SUMMARY
-----------------
Total Screenings: 10,542
- Clear: 10,012 (95.0%)
- Potential Match: 518 (4.9%)
- Confirmed Match: 12 (0.1%)
DATA SOURCES
------------
- OFAC SDN: 10,542 screenings
- Data freshness: Real-time (< 1 hour)
MATCH ANALYSIS
--------------
- Average confidence (matches): 0.847
- Match types: fuzzy (65%), fuzzy+semantic (28%), exact (7%)
EVIDENCE CHAIN INTEGRITY
------------------------
- All screenings include source_evidence: YES
- All matches traceable to authority: YES
- Data freshness within 24 hours: YES
For API integration details, see the API Reference