mcpField
D
didit-aml-screening

didit-aml-screening

github.com/didit-protocol安全29226 次安装2 周前更新
代码仓库

关于 didit-aml-screening

面向开发者的 Didit 技能,可在一次同步请求中将个人或企业与全球监控名单及数据库进行筛查。它分别给出匹配分数和风险分数,并支持配置阈值、搜索负面媒体及持续监控。

主要功能

  1. 01筛查个人和企业
  2. 02查询监控名单及数据库
  3. 03分别计算匹配分数和风险分数
  4. 04配置审核阈值
  5. 05可选搜索负面媒体和持续监控

适用场景

  1. 01在客户注册时筛查个人
  2. 02核查企业是否命中制裁及监管名单
  3. 03将疑似匹配项交由合规人员审核
  4. 04持续监控档案的变化

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/didit-protocol/skills --skill didit-aml-screening

安装后在 Claude Code 中输入/didit-aml-screening确认已加载。

附带文件scripts/screen_aml.py

详细介绍

Didit AML 筛查 API

概览

通过一次同步调用,将个人或公司与 1,300 多个全球监控名单和数据库进行筛查。每个命中项有两个分数:匹配分数(是否为同一个人?)和 风险分数(匹配的实体风险有多高?)。

主要限制:

  • full_name 是唯一必填字段(至少 2 个字符)。
  • entity_type:"person"(默认值)或 "company"。
  • nationality 是 ISO 3166-1 alpha-2 代码(ES,不是 ESP)。其他值都会返回 400。
  • aml_name_weight + aml_dob_weight + aml_country_weight 的总和必须正好为 100。
  • aml_score_approve_threshold 必须小于或等于 aml_score_review_threshold。
  • include_ongoing_monitoring: true 要求 save_api_request: true(默认值)。
  • include_adverse_media: true 会等待不利媒体筛查结果(约 5 秒,另加最多 25 秒):客户端超时时间至少应设为 60 秒。
  • 重试时请发送 Idempotency-Key 标头,确保超时不会导致重复筛查或重复计费。

覆盖范围(根据文档): 制裁名单(例如 OFAC SDN、UN、EU、HM Treasury)、执法和通缉名单(例如 FBI、Interpol)、PEP(1-4 级)及其亲属和密切关联人、警告和监管执法记录、适格性和诚信记录、破产记录,以及来自 5 万多个新闻来源的不利媒体信息(仅在 include_adverse_media: true 时提供)。

评分:

  1. 每个命中项的匹配分数(0-100):低于 aml_match_score_threshold(默认值为 93)时,命中项为 "False Positive";达到或高于该值时为 "Unreviewed"。不会返回低于 75 的命中项。
  2. 每个命中项的风险分数(0-100):非“False Positive”命中项中最高的风险分数会成为 aml.score,并根据你设置的两个阈值确定 aml.status。

持久化: 设置 save_api_request: true(默认值)后,筛查结果会保存为一个会话:request_id 可用于调用 GET /v3/session/{sessionId}/decision/,结果会显示在 Business Console 中,并触发 status.updated webhook,之后还可以审核命中项。设置为 false 时不会保存任何内容,request_id 仅用作关联 ID。

沙盒: 沙盒 API 密钥会跳过筛查和计费,并返回模拟结果:除非传入 sandbox_scenario,否则返回 "Approved" 且命中数为零(decline_aml_hit 返回一个命中项和 "Declined",review_aml_possible_match 返回 "In Review";场景目录见 GET /v1/sandbox/scenarios/)。实时应用不接受 sandbox_scenario。

价格: AML 筛查每次 $0.20(筛查成功后扣除一个额度;幂等重放不会再次收费;独立调用没有免费额度)。AML 监控每个受监控档案每年 $0.07。以上为截至 2026 年 11 月 1 日的标价,届时 Didit 将调整价格,每月 500 次免费检查将改为每月 $10 的免费额度。当前价格请查看 didit.me/pricing。

API 参考: https://docs.didit.me/standalone-apis/aml-screening
功能指南: https://docs.didit.me/core-technology/aml-screening/overview
匹配分数: https://docs.didit.me/core-technology/aml-screening/aml-match-score
风险分数: https://docs.didit.me/core-technology/aml-screening/aml-risk-score


身份验证

每个请求都需要 x-api-key 标头。请使用 Didit Business Console 中 Developers > API keys 下的应用 API 密钥,或以编程方式创建账号和密钥(参见 Getting Started)。具有自定义访问权限的命名密钥需要 Sessions 写入权限才能运行独立检查;受限于部分工作流或仅限已批准会话的密钥无法运行这些检查。

快速开始(还没有账户?)

如果你还没有 Didit API 密钥,只需进行 2 次 API 调用即可创建:

  1. 注册: 使用 {"email": "[email protected]", "password": "MyStr0ng!Pass"} 调用 POST https://apx.didit.me/auth/v2/programmatic/register/
  2. 查看邮箱,获取 6 位验证码
  3. 验证: 使用 {"email": "[email protected]", "code": "A3K9F2"} 调用 POST https://apx.didit.me/auth/v2/programmatic/verify-email/。密钥位于响应中的 application.api_key。

充值: 使用 GET /v3/billing/balance/ 查看余额;使用 POST /v3/billing/top-up/ 并传入 {"amount_in_dollars": 50} 获取 Stripe 结账链接。

完整的平台管理说明(工作流、会话、用户、账单)请参阅 didit-verification-management 技能。


端点

POST https://verification.didit.me/v3/aml/
请求头
请求头值必填
x-api-key你的 API 密钥是
Content-Typeapplication/json是
Idempotency-Key你的重试密钥,最多 255 个字符否

Idempotency-Key 的作用范围为你的应用和完全相同的请求正文。使用相同密钥和正文重试时,会返回已存储的响应,不会再次进行筛查或计费;相同密钥搭配不同正文时,会返回 409;首次请求仍在运行时重试,会返回带有 Retry-After: 30 的 409。

请求正文(JSON)
参数类型必填默认值说明
full_namestring是-个人或公司名称,至少 2 个字符
entity_typestring否"person""person" 或 "company"
date_of_birthstring否-YYYY-MM-DD:出生日期(个人)或注册成立日期(公司)
nationalitystring否-ISO 3166-1 alpha-2 国家代码,例如 US
document_numberstring否-身份证件号码。不参与加权:作为“黄金密钥”(参见匹配分数)。仅当长度为 2-50 个字符时用作搜索筛选条件;超出此范围时仍会进行筛查并计费,但不会缩小搜索范围
aml_match_score_thresholdinteger否930-100。低于此值的命中项标记为 "False Positive",达到或高于此值的标记为 "Unreviewed"
aml_name_weightinteger否600-100。匹配分数中的姓名权重
aml_dob_weightinteger否250-100。匹配分数中的出生日期权重
aml_country_weightinteger否150-100。匹配分数中的国家权重(三项权重之和必须为 100)
aml_score_approve_thresholdnumber否800-100。aml.score 小于或等于此值时,状态为 "Approved"
aml_score_review_thresholdnumber否1000-100。aml.score 高于此值时,状态为 "Declined";介于两个阈值之间时,状态为 "In Review"
include_adverse_mediaboolean否false同时搜索负面新闻报道(最多约增加 30 秒)
include_ongoing_monitoringboolean否false持续重新筛查此个人资料,并通过 webhook 报告变更。按 AML Monitoring 计费。需要设置 save_api_request: true
save_api_requestboolean否true将筛查结果保存为会话(控制台、决策端点、webhook、命中项审核)
vendor_datastring否-你为受筛查用户指定的标识符,将被存储并在响应中返回
metadataobject否null与请求一起存储并在响应中返回的自由格式 JSON
sandbox_scenariostring否-仅适用于沙盒密钥:decline_aml_hit、review_aml_possible_match、……
示例
import requests

response = requests.post(
    "https://verification.didit.me/v3/aml/",
    headers={
        "x-api-key": "YOUR_API_KEY",
        "Content-Type": "application/json",
        "Idempotency-Key": "aml-user-1234-2026-10-12",
    },
    json={
        "full_name": "Jane Doe",
        "date_of_birth": "1985-03-15",
        "nationality": "US",
        "document_number": "AB1234567",
        "entity_type": "person",
        "vendor_data": "user-1234",
    },
    timeout=90,
)
aml = response.json()["aml"]
print(aml["status"], aml["score"], aml["total_hits"])
const response = await fetch("https://verification.didit.me/v3/aml/", {
  method: "POST",
  headers: {
    "x-api-key": "YOUR_API_KEY",
    "Content-Type": "application/json",
    "Idempotency-Key": "aml-user-1234-2026-10-12",
  },
  body: JSON.stringify({
    full_name: "Jane Doe",
    date_of_birth: "1985-03-15",
    nationality: "US",
    vendor_data: "user-1234",
  }),
});
const { aml } = await response.json();
响应(200 OK,已删节)

一个制裁名单命中项标记为 Unreviewed(匹配分数 97,风险分数 86),另一个 PEP 命中项标记为 False Positive(匹配分数 88),且不会计入 aml.score。使用默认阈值时,86 高于 80 且不高于 100,因此状态为 "In Review"。

{
  "request_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
  "aml": {
    "status": "In Review",
    "total_hits": 2,
    "entity_type": "person",
    "hits": [
      {
        "id": "hit-001",
        "url": "https://sanctions.example.org/entry/123",
        "match": false,
        "score": 0.97,
        "match_score": 97.0,
        "risk_score": 86.0,
        "caption": "Jane Doe",
        "datasets": ["Sanctions"],
        "review_status": "Unreviewed",
        "rca_name": "",
        "first_seen": "2024-01-07T00:00:00",
        "last_seen": "2026-05-02T00:00:00",
        "properties": {"name": ["Jane Doe"], "birthDate": ["1985-03-15"], "nationality": ["United States"]},
        "score_breakdown": {
          "name_score": 95, "name_weight": 60, "name_weight_normalized": 60.0, "name_contribution": 57.0,
          "dob_score": 100, "dob_weight": 25, "dob_weight_normalized": 25.0, "dob_contribution": 25.0,
          "country_score": 100, "country_weight": 15, "country_weight_normalized": 15.0, "country_contribution": 15.0,
          "document_number_match_type": "NEUTRAL",
          "document_number_effect": "Hit has no document number data",
          "total_score": 97
        },
        "pep_matches": [],
        "sanction_matches": [{"list_name": ["Example Sanctions List"], "matched_name": "Jane Doe", "source_url": "https://sanctions.example.org/entry/123"}],
        "warning_matches": [],
        "adverse_media_matches": [],
        "adverse_media_details": null,
        "linked_entities": []
      },
      {
        "id": "hit-002",
        "match_score": 88.0,
        "risk_score": 47.5,
        "caption": "Jane A. Doe",
        "datasets": ["PEP Level 2"],
        "review_status": "False Positive",
        "score_breakdown": {
          "name_score": 80, "name_weight": 60, "name_weight_normalized": 60.0, "name_contribution": 48.0,
          "dob_score": 100, "dob_weight": 25, "dob_weight_normalized": 25.0, "dob_contribution": 25.0,
          "country_score": 100, "country_weight": 15, "country_weight_normalized": 15.0, "country_contribution": 15.0,
          "document_number_match_type": "NEUTRAL",
          "document_number_effect": "Hit has no document number data",
          "total_score": 88
        }
      }
    ],
    "score": 86.0,
    "screened_data": {
      "full_name": "Jane Doe",
      "date_of_birth": "1985-03-15",
      "nationality": "US",
      "document_number": "AB1234567"
    },
    "warnings": [
      {
        "feature": "AML",
        "risk": "POSSIBLE_MATCH_FOUND",
        "additional_data": null,
        "log_type": "warning",
        "short_description": "Possible match found in AML screening",
        "long_description": "The Anti-Money Laundering (AML) screening process identified potential matches with watchlists or high-risk databases, requiring further review."
      }
    ]
  },
  "vendor_data": "user-1234",
  "metadata": null,
  "created_at": "2026-10-12T10:23:44.812000+00:00"
}
状态值与处理方式
aml.status规则(默认值)操作
"Approved"aml.score <= 批准阈值(80)。包括无命中,以及所有命中均为 False Positive(分数为 0)的情况可安全继续
"In Review"批准阈值 < aml.score <= 审核阈值(100)对尚未审核的命中进行人工合规审核
"Declined"aml.score > 审核阈值。默认值为 100 时不会出现这种情况:调低 aml_score_review_threshold 以自动拒绝根据你的政策拦截或升级处理

独立 API 仅返回这三种状态。

错误响应
代码含义操作
400请求无效查看响应正文中的字段错误。跨字段规则会返回 {"error": [...]}:权重总和不为 100、批准阈值高于审核阈值、未启用 save_api_request 却使用监控功能。此外,Idempotency-Key 超过 255 个字符也会触发此错误
401API 密钥已过期在 Developers > API keys 中轮换密钥或创建新密钥
403API 密钥缺失、错误或已撤销;受限密钥无权访问此端点;请求来自密钥 IP 允许列表之外;或额度不足查看 detail 或 error 中的信息:修正 x-api-key 请求头或密钥权限,或者充值
409使用不同请求正文重复使用了 Idempotency-Key,或使用该密钥提交的首个请求仍在运行新请求请使用新密钥;对于正在运行的请求,请等待 Retry-After 指定的时间,然后使用相同的密钥和请求正文重试
429速率限制:每个密钥每分钟最多 300 个 POST/PATCH/DELETE 请求和 600 个 GET 请求等待 Retry-After 指定的秒数,然后重试

额度检查会在验证和任何筛查之前运行:额度不足时返回 403,并附带 {"error": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"}。


匹配分数系统

match_score = 各组成部分的分数 × 对应权重之和;权重会根据双方都有数据的组成部分重新归一化(仅有姓名时,姓名权重变为 100%)。分数限制在 0-100 之间。

组成部分默认权重评分方式
姓名60模糊相似度 0-100(错别字、词序、中间名)
出生日期25完全相同的日期:100%。命中项仅有年份且年份匹配:100%。年份相同但月份或日期不同:50%。年份不同:-100%
国家/地区15匹配:100%。不匹配:-50%。比较前会对命中项中的国家/地区名称和 alpha-3 代码进行规范化

证件号码“黄金键”(不计权重;移除空格、-、. 和 _ 后转为大写再进行比较):

情况影响
你的 document_number 与某个命中项的号码相同match_score 设为 100(MATCH)
任一方缺少号码,或号码不同分数不变(NEUTRAL)。号码不同不会扣分,因为可能是不同类型的证件

目前,score_breakdown.document_number_match_type 的值为 MATCH 或 NEUTRAL;枚举中也列出了 HARD_MISMATCH,但当前评分不会产生此值。

分类: match_score < aml_match_score_threshold(93) -> "False Positive"(不计入 aml.score);>= 阈值 -> "Unreviewed"。分数低于 75 的命中不会返回。


风险评分系统

根据文档:risk_score = (Country x 0.30) + (Category x 0.50) + (Criminal records x 0.20),范围为 0–100。各维度的视图位于 hits[].risk_view。

类别评分(使用命中项中评分最高的类别):

类别(datasets 值)评分
Sanctions、PEP、PEP Level 1100
Warnings and Regulatory Enforcement95
Insolvency、PEP Level 280
SIE、SIP75
PEP Level 370
Fitness and Probity65
Adverse Media60
PEP Level 455

最终状态:aml.score = 非 "False Positive" 命中项中的最高 risk_score(没有此类命中项时为 0),然后应用 Status Values 中的阈值。之后更改命中项的审核状态(参见 Reviewing Hits)不会重新计算 aml.status。


警告标签

标签条件log_type
POSSIBLE_MATCH_FOUNDaml.score 非零且 >= aml_score_approve_threshold(评分恰好达到阈值时会发出警告,但状态仍为 "Approved")warning;当评分高于 aml_score_review_threshold 时为 error

警告对象:{feature, risk, additional_data, log_type, short_description, long_description}。COULD_NOT_PERFORM_AML_SCREENING 仅存在于工作流会话中(KYC 数据缺少全名、出生日期或签发州);独立 API 不会返回此项。


响应字段参考

顶层
字段类型描述
request_id字符串当 save_api_request 为 true 时为会话 ID,否则为关联 UUID
aml.status字符串"Approved"、"In Review"、"Declined"
aml.total_hits整数hits 中的条目数(包括 False Positive)
aml.entity_type字符串"person" 或 "company"
aml.score数字非 False Positive 命中项中的最高 risk_score
aml.screened_data对象已筛查的 {full_name, date_of_birth, nationality, document_number}(缺失时为 null)
aml.warnings数组参见 Warning Tags
vendor_data、metadata、created_at回显数据和响应时间戳
命中对象
字段类型描述
idstring命中 ID。审核时将其用作 hit_id
captionstring匹配实体的显示名称
match_scorenumber身份置信度,范围为 0–100
risk_scorenumber实体风险,范围为 0–100
scorenumber已弃用:0–1 范围内的匹配分数
matchboolean旧版标志。请使用 match_score + review_status
review_statusstring"False Positive"、"Unreviewed"、"Confirmed Match"、"Inconclusive"
datasetsarrayPEP、PEP Level 1–PEP Level 4、Sanctions、Adverse Media、Warnings and Regulatory Enforcement、Fitness and Probity、SIP、SIE、Insolvency
propertiesobject档案数组:name、alias、notes、gender、birthDate、birthPlace、nationality、position 等
rca_namestring与该实体匹配的相关密切关联人
urlstring可用时提供来源 URL
pep_matchesarray{list_name, publisher, source_url, description, matched_name, pep_position, date_of_birth, place_of_birth, aliases, education, other_sources}
sanction_matchesarray制裁名单条目(例如 list_name、matched_name、reason、legal_basis、sanction_program、sanctioning_authority、listed_on、source_url)
warning_matchesarray警告和监管执法条目
adverse_media_matchesarray仅在设置 include_adverse_media: true 时提供:{headline, summary, sentiment, sentiment_score, source_url, thumbnail, country, author_name, publication_date, adverse_keywords, other_sources}
adverse_media_detailsobject仅在设置 include_adverse_media: true 时提供:汇总后的 sentiment、sentiment_score、adverse_keywords
linked_entitiesarray关系:{name, relation, status, details, active}
risk_viewobject各维度的风险(crimes、countries、categories、custom_list),每项包含 score、weightage、risk_level、risk_scores
additional_informationobject额外背景信息,例如 flag_summary 数组
first_seen / last_seenstring在数据集中的首次出现时间和最近刷新时间
score_breakdownobject{name,dob,country}_score、_weight、_weight_normalized、_contribution、document_number_match_type、document_number_effect、total_score(= match_score)

审核命中项

已保存的筛查(save_api_request: true)和工作流会话可以审核其命中项。两个端点都需要具有 Sessions 写入权限(write:sessions)的 API 密钥,会触发 data.updated webhook,并在会话的审核记录中添加一条记录。它们不会更改会话或 AML 状态。持续监控重新筛查时会保留审核决定。仅当工作流会话包含多个 AML 检查时,才添加 ?node_id=<node>(或在请求正文中添加 node_id)。

单个命中项:

PATCH https://verification.didit.me/v3/session/{sessionId}/update-aml-hit-status/
{"hit_id": "hit-001", "review_status": "Confirmed Match"}
-> 200 {"message": "Hit status updated successfully", "hit_id": "hit-001", "review_status": "Confirmed Match"}

多个命中项(全部成功或全部不更改):

PATCH https://verification.didit.me/v3/session/{sessionId}/bulk-update-aml-hit-status/
{"hit_updates": [{"hit_id": "hit-001", "review_status": "Confirmed Match"},
                 {"hit_id": "hit-002", "review_status": "False Positive"}]}
-> 200 {"message": "Updated 2 hit(s) successfully", "updated_hits": ["hit-001", "hit-002"]}

review_status:Unreviewed、Confirmed Match、False Positive、Inconclusive。错误:400(hit_id 或 hit_updates 为空、状态无效)、403(密钥、权限)、404(未找到会话、没有 AML 检查,或 hit_id 未知;批量操作中不会更改任何内容)。

持续监控

默认关闭。开启后,系统会在观察名单更新时重新筛查该档案;状态变更时会触发 status.updated,命中项变更时会触发 data.updated。费用按 AML 监控计费(每个受监控档案每年 $0.07)。

开启方式:

  • 在 POST /v3/aml/ 中设置 include_ongoing_monitoring: true(并设置 save_api_request: true)。
  • 在工作流的 AML 功能配置中设置 is_aml_ongoing_monitoring_enabled,适用于从该工作流创建的会话(参见 didit-verification-management 技能)。
  • 批量为现有档案开启:POST /v3/users/aml-monitoring/ 或 POST /v3/businesses/aml-monitoring/(参见 didit-verification-management 技能)。

监控运行的证明(根据文档):GET /v1/session/{sessionId}/aml-screening-history/ 会按时间倒序列出每次已完成的重新筛查,包括 outcome: "NO_CHANGE" 的运行记录。


常见工作流

基本 AML 检查
1. POST /v3/aml/ -> {"full_name": "Jane Doe", "date_of_birth": "1985-03-15", "nationality": "US"}
2. If "Approved"  -> no credible watchlist match
   If "In Review" -> review hits with review_status "Unreviewed" (datasets, risk_score, score_breakdown)
   If "Declined"  -> block or escalate (only when you lowered aml_score_review_threshold)
3. Record the decision per hit: PATCH /v3/session/{request_id}/update-aml-hit-status/
全面的 KYC + AML
1. POST /v3/id-verification/ -> read name, date of birth, nationality and document number
2. Convert nationality from ISO alpha-3 (what ID verification returns, e.g. ESP) to alpha-2 (ES):
   /v3/aml/ returns 400 for an alpha-3 code
3. POST /v3/aml/ with all four fields -> more data means fewer False Positives;
   an exact document number match sets match_score to 100
4. Optional: include_ongoing_monitoring=true to keep the profile under monitoring
安全重试
1. POST /v3/aml/ with header Idempotency-Key: <unique per screening>
2. On timeout or 5xx, resend the same body with the same key -> stored response, no second charge
3. On 409 with Retry-After -> the first request is still running; wait and retry with the same key

实用脚本

screen_aml.py:从命令行对照 AML 观察名单进行筛查。

# Requires: pip install requests
export DIDIT_API_KEY="your_api_key"
python scripts/screen_aml.py --name "Jane Doe"
python scripts/screen_aml.py --name "Jane Doe" --dob 1985-03-15 --nationality US --doc-number AB1234567
python scripts/screen_aml.py --name "Acme Energy Ltd" --entity-type company --adverse-media
python scripts/screen_aml.py --name "Jane Doe" --approve-threshold 70 --review-threshold 90 --idempotency-key user-1234-aml

评论

支持 Markdown