# $RESULT is the saved JSON body from POST /v3/wallet-screening/
curl -X POST 'https://verification.didit.me/v3/wallet-screening/pdf/' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d "$RESULT" \
-o wallet_screening_report.pdffrom didit import Didit
# Reads DIDIT_API_KEY.
client = Didit()
content = client.wallet_screening.screen_pdf(
provider="your-provider",
screening_type="WALLET_SCREENING",
risk_score=1,
severity="UNKNOWN",
status="SCREENED",
summary="your-summary",
wallet_address="your-wallet-address",
blockchain="your-blockchain",
source_of_funds=[{}],
destination_of_funds=[{}],
counterparty_connections=[{}],
sanctions_hit=True,
dominant_risk_category="your-dominant-risk-category",
report_signature="your-report-signature",
)
with open("download.pdf", "wb") as file:
file.write(content)import { writeFile } from "node:fs/promises";
import Didit from "@didit-protocol/sdk-node";
// Reads DIDIT_API_KEY.
const didit = new Didit();
const content = await didit.walletScreening.screenPdf({
provider: "your-provider",
screening_type: "WALLET_SCREENING",
risk_score: 1,
severity: "UNKNOWN",
status: "SCREENED",
summary: "your-summary",
wallet_address: "your-wallet-address",
blockchain: "your-blockchain",
source_of_funds: [{}],
destination_of_funds: [{}],
counterparty_connections: [{}],
sanctions_hit: true,
dominant_risk_category: "your-dominant-risk-category",
report_signature: "your-report-signature",
});
await writeFile("download.pdf", Buffer.from(await content.arrayBuffer()));ctx := context.Background()
// Reads DIDIT_API_KEY.
client := didit.NewClient()
resp, err := client.WalletScreening.ScreenPDF(ctx, didit.WalletScreeningResultParam{
Provider: "your-provider",
ScreeningType: "WALLET_SCREENING",
RiskScore: 1,
Severity: "UNKNOWN",
Status: "SCREENED",
Summary: "your-summary",
WalletAddress: "your-wallet-address",
Blockchain: "your-blockchain",
SourceOfFunds: []didit.WalletScreeningResultParamSourceOfFunds{{}},
DestinationOfFunds: []didit.WalletScreeningResultParamDestinationOfFunds{{}},
CounterpartyConnections: []didit.WalletScreeningResultParamCounterpartyConnections{{}},
SanctionsHit: true,
DominantRiskCategory: didit.String("your-dominant-risk-category"),
ReportSignature: "your-report-signature",
})
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
file, err := os.Create("download.pdf")
if err != nil {
log.Fatal(err)
}
defer file.Close()
if _, err := io.Copy(file, resp.Body); err != nil {
log.Fatal(err)
}import java.nio.file.Path;
import java.util.List;
import me.didit.Didit;
import me.didit.types.WalletScreeningResult;
// Reads DIDIT_API_KEY.
Didit client = new Didit();
client.walletScreening().screenPdf(WalletScreeningResult.builder()
.provider("your-provider")
.screeningType(WalletScreeningResult.ScreeningType.of("WALLET_SCREENING"))
.riskScore(1L)
.severity(WalletScreeningResult.Severity.of("UNKNOWN"))
.status(WalletScreeningResult.Status.of("SCREENED"))
.summary("your-summary")
.walletAddress("your-wallet-address")
.blockchain("your-blockchain")
.sourceOfFunds(List.of(WalletScreeningResult.SourceOfFunds.builder()
.build()))
.destinationOfFunds(List.of(WalletScreeningResult.DestinationOfFunds.builder()
.build()))
.counterpartyConnections(List.of(WalletScreeningResult.CounterpartyConnections.builder()
.build()))
.sanctionsHit(true)
.dominantRiskCategory("your-dominant-risk-category")
.reportSignature("your-report-signature")
.build())
.writeTo(Path.of("download.pdf"));<?php
require 'vendor/autoload.php';
use Didit\DiditClient;
// Reads DIDIT_API_KEY.
$didit = new DiditClient();
$content = $didit->walletScreening->screenPdf([
'provider' => 'your-provider',
'screening_type' => 'WALLET_SCREENING',
'risk_score' => 1,
'severity' => 'UNKNOWN',
'status' => 'SCREENED',
'summary' => 'your-summary',
'wallet_address' => 'your-wallet-address',
'blockchain' => 'your-blockchain',
'source_of_funds' => [[]],
'destination_of_funds' => [[]],
'counterparty_connections' => [[]],
'sanctions_hit' => true,
'dominant_risk_category' => 'your-dominant-risk-category',
'report_signature' => 'your-report-signature',
]);
$content->saveTo('download.pdf');require "didit"
# Reads DIDIT_API_KEY.
didit = Didit::Client.new
content = didit.wallet_screening.screen_pdf(
provider: "your-provider",
screening_type: "WALLET_SCREENING",
risk_score: 1,
severity: "UNKNOWN",
status: "SCREENED",
summary: "your-summary",
wallet_address: "your-wallet-address",
blockchain: "your-blockchain",
source_of_funds: [{}],
destination_of_funds: [{}],
counterparty_connections: [{}],
sanctions_hit: true,
dominant_risk_category: "your-dominant-risk-category",
report_signature: "your-report-signature"
)
File.binwrite("download.pdf", content)using System;
using Didit;
// Reads DIDIT_API_KEY.
using var client = new DiditClient();
var content = await client.WalletScreening.ScreenPdfAsync(new WalletScreeningResult
{
Provider = "your-provider",
ScreeningType = "WALLET_SCREENING",
RiskScore = 1,
Severity = "UNKNOWN",
Status = "SCREENED",
Summary = "your-summary",
WalletAddress = "your-wallet-address",
Blockchain = "your-blockchain",
SourceOfFunds = new WalletScreeningResultSourceOfFunds[] { new() },
DestinationOfFunds = new WalletScreeningResultDestinationOfFunds[] { new() },
CounterpartyConnections = new WalletScreeningResultCounterpartyConnections[] { new() },
SanctionsHit = true,
DominantRiskCategory = "your-dominant-risk-category",
ReportSignature = "your-report-signature",
});
await content.SaveToAsync("download.pdf");"<string>"钱包筛查 PDF 报告 API
Didit 可将钱包筛查结果渲染为带 Didit 品牌标识的 PDF:将筛查接口返回的 JSON 原样回传即可。无状态,不调用服务商,也不产生额外费用。
# $RESULT is the saved JSON body from POST /v3/wallet-screening/
curl -X POST 'https://verification.didit.me/v3/wallet-screening/pdf/' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d "$RESULT" \
-o wallet_screening_report.pdffrom didit import Didit
# Reads DIDIT_API_KEY.
client = Didit()
content = client.wallet_screening.screen_pdf(
provider="your-provider",
screening_type="WALLET_SCREENING",
risk_score=1,
severity="UNKNOWN",
status="SCREENED",
summary="your-summary",
wallet_address="your-wallet-address",
blockchain="your-blockchain",
source_of_funds=[{}],
destination_of_funds=[{}],
counterparty_connections=[{}],
sanctions_hit=True,
dominant_risk_category="your-dominant-risk-category",
report_signature="your-report-signature",
)
with open("download.pdf", "wb") as file:
file.write(content)import { writeFile } from "node:fs/promises";
import Didit from "@didit-protocol/sdk-node";
// Reads DIDIT_API_KEY.
const didit = new Didit();
const content = await didit.walletScreening.screenPdf({
provider: "your-provider",
screening_type: "WALLET_SCREENING",
risk_score: 1,
severity: "UNKNOWN",
status: "SCREENED",
summary: "your-summary",
wallet_address: "your-wallet-address",
blockchain: "your-blockchain",
source_of_funds: [{}],
destination_of_funds: [{}],
counterparty_connections: [{}],
sanctions_hit: true,
dominant_risk_category: "your-dominant-risk-category",
report_signature: "your-report-signature",
});
await writeFile("download.pdf", Buffer.from(await content.arrayBuffer()));ctx := context.Background()
// Reads DIDIT_API_KEY.
client := didit.NewClient()
resp, err := client.WalletScreening.ScreenPDF(ctx, didit.WalletScreeningResultParam{
Provider: "your-provider",
ScreeningType: "WALLET_SCREENING",
RiskScore: 1,
Severity: "UNKNOWN",
Status: "SCREENED",
Summary: "your-summary",
WalletAddress: "your-wallet-address",
Blockchain: "your-blockchain",
SourceOfFunds: []didit.WalletScreeningResultParamSourceOfFunds{{}},
DestinationOfFunds: []didit.WalletScreeningResultParamDestinationOfFunds{{}},
CounterpartyConnections: []didit.WalletScreeningResultParamCounterpartyConnections{{}},
SanctionsHit: true,
DominantRiskCategory: didit.String("your-dominant-risk-category"),
ReportSignature: "your-report-signature",
})
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
file, err := os.Create("download.pdf")
if err != nil {
log.Fatal(err)
}
defer file.Close()
if _, err := io.Copy(file, resp.Body); err != nil {
log.Fatal(err)
}import java.nio.file.Path;
import java.util.List;
import me.didit.Didit;
import me.didit.types.WalletScreeningResult;
// Reads DIDIT_API_KEY.
Didit client = new Didit();
client.walletScreening().screenPdf(WalletScreeningResult.builder()
.provider("your-provider")
.screeningType(WalletScreeningResult.ScreeningType.of("WALLET_SCREENING"))
.riskScore(1L)
.severity(WalletScreeningResult.Severity.of("UNKNOWN"))
.status(WalletScreeningResult.Status.of("SCREENED"))
.summary("your-summary")
.walletAddress("your-wallet-address")
.blockchain("your-blockchain")
.sourceOfFunds(List.of(WalletScreeningResult.SourceOfFunds.builder()
.build()))
.destinationOfFunds(List.of(WalletScreeningResult.DestinationOfFunds.builder()
.build()))
.counterpartyConnections(List.of(WalletScreeningResult.CounterpartyConnections.builder()
.build()))
.sanctionsHit(true)
.dominantRiskCategory("your-dominant-risk-category")
.reportSignature("your-report-signature")
.build())
.writeTo(Path.of("download.pdf"));<?php
require 'vendor/autoload.php';
use Didit\DiditClient;
// Reads DIDIT_API_KEY.
$didit = new DiditClient();
$content = $didit->walletScreening->screenPdf([
'provider' => 'your-provider',
'screening_type' => 'WALLET_SCREENING',
'risk_score' => 1,
'severity' => 'UNKNOWN',
'status' => 'SCREENED',
'summary' => 'your-summary',
'wallet_address' => 'your-wallet-address',
'blockchain' => 'your-blockchain',
'source_of_funds' => [[]],
'destination_of_funds' => [[]],
'counterparty_connections' => [[]],
'sanctions_hit' => true,
'dominant_risk_category' => 'your-dominant-risk-category',
'report_signature' => 'your-report-signature',
]);
$content->saveTo('download.pdf');require "didit"
# Reads DIDIT_API_KEY.
didit = Didit::Client.new
content = didit.wallet_screening.screen_pdf(
provider: "your-provider",
screening_type: "WALLET_SCREENING",
risk_score: 1,
severity: "UNKNOWN",
status: "SCREENED",
summary: "your-summary",
wallet_address: "your-wallet-address",
blockchain: "your-blockchain",
source_of_funds: [{}],
destination_of_funds: [{}],
counterparty_connections: [{}],
sanctions_hit: true,
dominant_risk_category: "your-dominant-risk-category",
report_signature: "your-report-signature"
)
File.binwrite("download.pdf", content)using System;
using Didit;
// Reads DIDIT_API_KEY.
using var client = new DiditClient();
var content = await client.WalletScreening.ScreenPdfAsync(new WalletScreeningResult
{
Provider = "your-provider",
ScreeningType = "WALLET_SCREENING",
RiskScore = 1,
Severity = "UNKNOWN",
Status = "SCREENED",
Summary = "your-summary",
WalletAddress = "your-wallet-address",
Blockchain = "your-blockchain",
SourceOfFunds = new WalletScreeningResultSourceOfFunds[] { new() },
DestinationOfFunds = new WalletScreeningResultDestinationOfFunds[] { new() },
CounterpartyConnections = new WalletScreeningResultCounterpartyConnections[] { new() },
SanctionsHit = true,
DominantRiskCategory = "your-dominant-risk-category",
ReportSignature = "your-report-signature",
});
await content.SaveToAsync("download.pdf");"<string>"为什么是无状态的
独立的钱包筛查不会向 transactions 表写入任何记录,因此 endpoint 没有可供渲染的已存储记录。取而代之,您需要重新提交POST /v3/wallet-screening/ 已返回给您的完全相同的 JSON。Didit 会将该 payload 渲染为 PDF,无需再次调用服务提供方。
report_signature 字段
每个 POST /v3/wallet-screening/ 响应现在都包含 report_signature 字段,这是一个限定于您应用的不透明签名。endpoint 在渲染前会验证该签名,因此调用方无法修改 risk_score、severity、sanctions_hit 或任何其他字段,从而获得一份外观正常、带有 Didit 品牌的 PDF,而其内容并非 Didit 实际生成的结果。
请始终原样重新提交完整的响应正文,包括 report_signature。调整键的顺序没有问题;更改任何已签名的值则不行。
# 1. Run the screening and save the full response
RESULT=$(curl -s -X POST https://verification.didit.me/v3/wallet-screening/ \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"wallet_address": "0x28c6c06298d514db089934071355e5743bf21d60", "blockchain": "ETH"}')
# 2. Repost it verbatim to render the PDF
curl -X POST https://verification.didit.me/v3/wallet-screening/pdf/ \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d "$RESULT" \
-o wallet_screening_report.pdf
计费
不会调用服务提供方,也不产生任何费用。endpoint 仅重新渲染您在调用POST /v3/wallet-screening/ 时已付费获得的结果。
错误
| 状态码 | 含义 |
|---|---|
400 | 请求正文不是符合钱包筛查结果结构的 JSON 对象,或 report_signature 缺失,或与重新提交的字段不匹配。 |
401 | 缺少 x-api-key,或其无效。 |
后续步骤
筛查钱包
按需钱包筛查
授权
您的应用 API 密钥,可在 Business Console 的“开发者 -> API 密钥”中获取。主密钥拥有完整访问权限。指定名称的密钥可设置作用域:针对每个资源设为无权限、只读或读写,限定于特定工作流或已通过的会话、限定于 IP 地址列表,以及设置到期日期。401 表示密钥错误、已撤销或已过期;403 表示未发送密钥、密钥无权访问该资源或操作,或请求来自其 IP 列表之外的地址;在会话路由上返回 404 表示该会话不在该密钥允许的工作流或状态范围内。没有媒体访问权限的密钥获取到的图片、视频和 PDF URL 将为 null;没有会话写入权限的密钥获取到的会话链接和 token 将为 null。请参阅 https://docs.didit.me/console/api-keys。
请求体
由 POST /v3/wallet-screening/ 返回的未经修改的 JSON 对象,包括 report_signature。
数据结构与 POST /v3/wallet-screening/ 响应相同,请逐字传回该响应主体,包括 report_signature。
执行筛查的提供商(例如 merklescience、crystal)。
对于此 endpoint 始终为 WALLET_SCREENING。
WALLET_SCREENING 归一化的 0-100 风险评分。分值越高表示对高风险实体的暴露越大。Merkle Science 将地址评为 0-5 级,分别对应 0、15、35、55、75 或 95。
根据 risk_score 派生的风险区间:0-9 为 UNKNOWN,10-39 为 LOW,40-69 为 MEDIUM,70-89 为 HIGH,90-100 为 CRITICAL。UNKNOWN 是最低区间,并非单独的无数据状态:risk_score 为 0(常见的无风险地址情况)表示无负面评估,而 1-9 范围内的非零分数是真实存在但低于 LOW 的信号,请读取 risk_score,而不仅仅是查看区间。切勿将 UNKNOWN 视为明确的低风险或通过评级;请勿将其显示为通过。
UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL 筛查结果状态。
SCREENED, PENDING, ERROR 易于阅读的筛查结果摘要。
已筛查的地址,原样回显。
已进行筛查的区块链。
该地址从何处接收资金,按实体归因。每个条目都是一个风险敞口明细。
Show child attributes
Show child attributes
该地址向何处发送资金,按实体归因。条目格式与 exposure_direction = outgoing 的 source_of_funds 相同。
Show child attributes
Show child attributes
提供商将筛查地址归属到的实体。对于 Merkle Science,这些信息来自地址自身的所有者和用户标签,因此同一实体可能会出现两次,并且它们不携带资金流:received_usd、sent_usd、received_hops 和 sent_hops 均为 null,且 percentage 为 0。请勿在此根据 risk_level 或 is_direct 进行路由:请使用 sanctions_hit、dominant_risk_category 和 risk_factors[].is_high_risk 获取判定结果,并在 source_of_funds/destination_of_funds 中使用 exposure_type 判断直接性。
Show child attributes
Show child attributes
如果该地址存在直接或间接的制裁敞口,则为 true。
权重最高的高风险类别,若无主导类别则为 null(例如 sanctioned、mixer、stolen_funds)。
针对此确切结果的不透明 HMAC-SHA256 签名,作用域限定于您的应用。该字段本身无单独意义,请将未经修改且包含此字段的完整响应体重新发送至 POST /v3/wallet-screening/pdf/ 以将其渲染为 PDF。如果缺失 report_signature 或在重新发送前修改了任何已签名字段(例如 risk_score、severity、sanctions_hit),PDF endpoint 将拒绝请求并返回 400。
交易筛查字段,与结果结构共用。在钱包筛查结果中始终为 null。
交易筛查字段,与结果结构共用。在钱包筛查结果中始终为 null。
交易筛查字段,与结果结构共用。在钱包筛查结果中始终为 null。
交易筛查字段,与结果结构共用。在钱包筛查结果中始终为 null。
交易筛查字段,与结果结构共用。在钱包筛查结果中始终为空。
交易筛查字段,与结果结构共用。在钱包筛查结果中始终为空。
交易筛查字段,与结果结构共用。在钱包筛查结果中始终为空。
交易筛查字段,与结果结构共用。在钱包筛查结果中始终为 null。
交易筛查字段,与结果结构共用。在钱包筛查结果中始终为 null。
用于交易筛查的暴露图谱节点。在钱包筛查结果中为空。
用于交易筛查的暴露图谱边。在钱包筛查结果中为空。
政治公众人物暴露情况。当无可用的 PEP 发现结果时为 null(由于目前没有任何提供商报告此项,今天的所有结果均为该值);仅在筛查结果明确为阴性时为 false。切勿将 null 视为已完成的 PEP 检查。
risk_score 的排序解释:导致该判定的原因。数据源会根据自身模型对地址进行评分,且仅返回判定结果(Merkle Science 返回 0-5 的整数),因此仅凭该分数无法采取操作。按高风险优先排序,随后按流经各驱动因素的价值排序,最多保留五个影响最大的因素;source_of_funds 和 destination_of_funds 始终包含完整的明细。若 risk_score 较高但没有 is_high_risk 条目,则表示数据源未报告任何制裁或归属实体匹配,纯粹根据其自身的风险敞口模型对该地址进行了评级,summary 会对此进行明确说明。
Show child attributes
Show child attributes
服务商自身的 payload。其格式因服务商而异,且可能随时更改:请读取规范化字段,而不是直接解析它。
响应
渲染生成的 PDF 文档,直接以二进制 application/pdf 形式返回,没有 JSON 包装。
The response is of type file.