Didit 类型脚本 / JavaScript SDK
官方Didit TypeScript和JavaScript库. 身份验证(KYC),业务验证(KYB),AML筛选,生物鉴别,交易监测,出行规则和客户认证,从你的后端.
- 每个服务器端点 Didit API (英语),带有完整类型,由OpenAPI合同生成.
- 使用已键入事件进行 Webhook 校验, 以及 Didit 认证符 校验 .
- 没有运行时间依赖 。 运行在节点.js 18或以后, Bun, Deno 和边缘运行时间
fetch和网络加密(Cloudflare Workers, Vercel Edge). - 无害环境管理和普通JS, TypeScript严格.
安装
npm install @didit-protocol/sdk-node
# or: pnpm add @didit-protocol/sdk-node / yarn add @didit-protocol/sdk-node / bun add @didit-protocol/sdk-node
快速启动
创建一个校验会话,发送用户到其URL,读取决定,并在状态变化时验证webhook Didit发送.
import Didit from "@didit-protocol/sdk-node";
const didit = new Didit(); // reads DIDIT_API_KEY
// 1. Create a session and send the user to session.url.
const session = await didit.sessions.create({
workflow_id: "11111111-2222-3333-4444-555555555555",
vendor_data: "user-42",
callback: "https://example.com/verification/done",
});
console.log(session.url);
// 2. Later, read the decision.
const decision = await didit.sessions.retrieveDecision(session.session_id);
console.log(decision.status, decision.created_at); // "Approved", a Date
// 3. Verify the webhook (Express). Pass the raw body, not parsed JSON.
import express from "express";
import { webhooks, WebhookVerificationError } from "@didit-protocol/sdk-node";
const app = express();
app.post("/webhooks/didit", express.raw({ type: "application/json" }), async (req, res) => {
// express.raw leaves req.body empty for other content types.
if (!Buffer.isBuffer(req.body)) return res.status(400).send("expected a JSON body");
try {
const event = await webhooks.verify(req.body, req.headers, process.env.DIDIT_WEBHOOK_SECRET!);
if (event.webhook_type === "status.updated") {
console.log(event.session_id, event.status);
}
res.sendStatus(200);
} catch (error) {
if (error instanceof WebhookVerificationError) return res.status(400).send(error.reason);
throw error;
}
});
更多可操作的例子,包括快递、快递、Hono、Next.js、Cloudflare Workers、Bun和Deno的网络接收器 examples/。 。 。 .
配置
const didit = new Didit({
apiKey: "...", // default: DIDIT_API_KEY
organizationId: "...", // default: DIDIT_ORGANIZATION_ID
applicationId: "...", // default: DIDIT_APPLICATION_ID
timeout: 60_000, // milliseconds per attempt
maxRetries: 2,
});
| 选项 | 默认 | 页:1 |
|---|---|---|
apiKey | DIDIT_API_KEY | 发送为 x-api-key时,仅改为 baseURL。没有密钥的客户端仍然可以使用 didit.account 并校验网友. |
baseURL | https://verification.didit.me | |
organizationId, (中文(简体) ), applicationId | DIDIT_ORGANIZATION_ID, (中文(简体) ), DIDIT_APPLICATION_ID | 需要应用范围的方法(案例、网络、持续监测等);见 日记) (中文(简体) ). |
accountBaseURL | https://apx.didit.me/auth/v2 | 账户管理didit.account) (中文(简体) ). |
accountToken | 无 | 这个 access_token 从 didit.account.login(...)。 。 。 . |
timeout | 60_000 | 毫秒,每次尝试,包括阅读身体. |
maxRetries | 2 | 见 检索。 。 。 . |
defaultHeaders | 无 | 添加到每个请求中. 他们不能取代全权证书(第2段)x-api-key, (中文(简体) ), Authorization) (中文(简体) ). |
fetch | 全球 fetch | 属于你的 fetch (代,仪也. |
fetchOptions | 无 | 额外 fetch 每个请求的选项,例如undici dispatcherA级 signal 在此取消每个请求. |
logLevel, (中文(简体) ), logger | DIDIT_LOG, (中文(简体) ), console | debug 每个请求记录一行. |
环境变量在Node.js、Bun和Deno(与 --allow-env) (中文(简体) ). Cloudflare Workers等边缘运行时间将配置传递给处理器,所以交给客户端: new Didit({ apiKey: env.DIDIT_API_KEY })。 。 。 .
创建一个客户端并重用它 . didit.withOptions({ ... }) 返回带有一些选项的新客户端。 每种方法还把请求选项作为其最后的论点:
await didit.sessions.create(
{ workflow_id },
{
timeout: 10_000,
maxRetries: 0,
idempotencyKey: "order-123",
headers: { "X-Trace": "abc" },
signal,
},
);
signal 取消请求、其重复和之间的等待; a signal 内 fetchOptions 做同样的.
使用 API
资源和方法遵循API: didit.<resource>.<method>(...),有巢资源,例如 didit.sessions.imports 或者说 didit.cases.notes。 。 。 .
路径参数是位置;其他所有东西都是在一个参数中运行的对象,其字段保留了API的名称(snake case).
日记 以 HTTP 路由和类型列出从 openapi/。 。 。 .
import { fileFromPath } from "@didit-protocol/sdk-node";
await didit.idVerification.verify({ front_image: await fileFromPath("id-front.jpg") });
await didit.aml.screen({ full_name: "Ada Lovelace", date_of_birth: "1815-12-10" });
await didit.users.updateStatus("user-42", { status: "FLAGGED" });
await didit.cases.notes.create(caseUuid, { comment: "Checked with the customer" });
每个请求和响应都有一个类型,从包中导出:
import type {
SessionsCreateParams,
SessionsCreateResponse,
TransactionDetail,
} from "@didit-protocol/sdk-node";
Enums 打开("Approved" | "Declined" | (string & {}): API的附加值后来从未突破你的构建.
以后添加的 API 字段会保存在您收到的对象上 .
可选领域是 ?:; 字段 API 可发送为 null 包含 | null。 。 。 .
日期字段为 Date 对象(没有时区的 API 发送日期- 时间读取为 UTC); 在参数中, 您可以通过一个 Date 或 ISO 8601 字符串.
账户管理 API(组织和应用程序) didit.account数字 :
const { access_token } = await didit.account.login({ email, password });
const account = didit.withOptions({ accountToken: access_token });
const organizations = await account.account.organizations.list();
倾斜
分页列表方法(在 日记返回页与 count, (中文(简体) ), next, (中文(简体) ), previous 财务报告和审定财务报表 results. Iterate with for await 以行走每页的每一行:
for await (const session of didit.sessions.list({ limit: 100 })) {
console.log(session.session_id);
}
const page = await didit.sessions.list({ limit: 100 });
if (page.hasNextPage()) {
const next = await page.getNextPage();
}
SDK跟着API的 next 链接并拒绝链接到另一个来源,因此您的 API 密钥永远不会离开 API .
文件
上传参数接受 a Blob 或者说 File页:1 Uint8Array 或者说 ArrayBuffer网络 ReadableStream,如: fs.createReadStream("id.jpg"),或 { data, filename, contentType }。 。 。 .
fileFromPath(path) (一) 在Node.js、Bun和Deno上读取文件; toFile(bytes, filename) 名称字节.
无名称的上传发送为 file 加上其内容类型或第一个字节给定的扩展名(file.jpg, (中文(简体) ), file.pdf) (中文(简体) ).
附有文件的请求作为多部分形式数据发送:其中的对象作为JSON文本运行,以及 null 字段被忽略(多块不为空).
二进制响应(会话和用户PDF、网络报告、钱包筛选PDF、导入模板、大小写附件)返回 a Blob数字 :
import { writeFile } from "node:fs/promises";
const pdf = await didit.sessions.generatePdf(sessionId);
await writeFile("report.pdf", new Uint8Array(await pdf.arrayBuffer()));
错误
| 错误 | 何时 |
|---|---|
DiditError | 下面每个错误的基级. |
APIConnectionError 编号 : APITimeoutError | 无响应( 网络失败, 超时) . |
APIStatusError | 任何非-2xx的答复,与 status, (中文(简体) ), body (如果可能的话,分出JSON), headers 财务报告和审定财务报表 requestId。 。 。 . |
BadRequestError 400块, AuthenticationError 401 (英语), PermissionDeniedError 403号, NotFoundError 404号, ConflictError 409号, UnprocessableEntityError 422号, RateLimitError 429号, InternalServerError 5 (简体中文) | 子类 APIStatusError。 。 。 . |
APIResponseValidationError | 2xx 回答 SDK 无法使用(不是 JSON,一个与另一个来源的 pagination 链接). |
WebhookVerificationError | Webhook 验证失败 ; reason 说为什么. |
TokenVerificationError | 验证符号失败 ; reason 说为什么. |
ConfigurationError | 缺少 API 密钥, 组织或应用程序 ID, 一个空的 Webhook 密钥, 一个无效的选项 。 抛出之前,任何东西发送. |
import { APIStatusError, NotFoundError } from "@didit-protocol/sdk-node";
try {
await didit.sessions.retrieveDecision(sessionId);
} catch (error) {
if (error instanceof NotFoundError) {
// ...
} else if (error instanceof APIStatusError) {
console.error(error.status, error.body, error.requestId);
} else {
throw error;
}
}
API 密钥从不出现在错误消息,日志行或已登录的客户端中.
检索
失败请求被重审到 maxRetries 乘数( 默认 2) , 由 0. 5 s 的指数后退, 满时焦, 封顶为 8 s , 遵守 Retry-After (封顶为60 s.
GET, (中文(简体) ), HEAD, (中文(简体) ), PUT 财务报告和审定财务报表 DELETE 在连接错误、超时、408、429和5xx上重审.
POST 财务报告和审定财务报表 PATCH 一旦请求可能已经到达服务器,就永远不会再被重审:仅在429年或在发送任何信息之前连接失败.
原始回应
const { data, response, requestId } = await didit.sessions.create({ workflow_id }).withResponse();
const raw: Response = await didit.sessions.generatePdf(sessionId).asResponse(); // unread, for streaming
网络呼号
webhooks.verify(rawBody, headers, secret, options?) 检查签名和时间戳并返回一个已键入的事件; 它扔出 WebhookVerificationError 否则.
该表还作为 didit.webhooks.verify(...)。 。 。 .
rawBody: 确切的身体字节(a)Buffer, (中文(简体) ),Uint8Array, (中文(简体) ),ArrayBuffer或字符串)。 配置您的框架, 以赋予您原始的身体 .headers(单位:千美元)Headers对象,节点.jsreq.headers,或[name, value]双人.secret:目的地的秘密,或旋转时的秘密清单.options.tolerance: 交货时间戳与现在之间的秒(默认为300).
它有三种标志: X-Signature (生的躯体), X-Signature-V2 (一种能活过重编码JSON的中件的Canonic JSON形式)和被腐烂的 X-Signature-Simple; 在秘密旋转时 -Previous 变体与旧密相签. 任何前两个,有 任何一个秘密,被接受.
const event = await webhooks.verify(rawBody, headers, [currentSecret, previousSecret]);
switch (event.webhook_type) {
case "status.updated":
case "data.updated":
console.log(event.session_id, event.status, event.decision?.status);
break;
case "transaction.status.updated":
console.log(event.transaction_id, event.status, event.score);
break;
default:
console.log("unhandled event", event.webhook_type);
}
活动是受歧视的工会 webhook_type: 会 议status.updated, (中文(简体) ), data.updated),用户,业务,交易和旅行规则事件, activity.created, (中文(简体) ), workflow.compliance_changed, (中文(简体) ), kyb.registry_search.resolved,以及 UnknownEvent 用于任何其他类型.
每次活动也都有 event.verifiedBy (签名匹配)和 event.bodyAuthenticated。 。 。 .
该活动是所发送的机构,但会议 decision 是生成的决定类型,所以日期时间是 Date 对象.
KYB 注册检索回调( E)kyb.registry_search.resolved)今天未签署(X-Didit-Unsigned-Callback: true),这样 verify 拒绝它 missing_signature。不要信任它的身体:用它的 request_id 换句话说.
如果你的框架只给你解剖过的JSON身体, webhooks.verifyParsed(payload, headers, secret) 检查 X-Signature-V2 2^53以上的整数失败 JSON.parse 已经四舍五入。 偏取生体相.
X-Signature-Simple 只签信封,不签尸体;它被接受 { allowSimple: true },然后则 event.bodyAuthenticated 实值 false:在采取行动之前,从API中重排记录.
交易、钱包筛选和旅行规则
const txn = await didit.transactions.create({
transaction_id: "txn-1001",
transaction_category: "finance",
transaction_details: { direction: "outbound", amount: 2500, currency: "EUR" },
subject: { vendor_data: "user-42", full_name: "Ada Lovelace" },
});
console.log(txn.status, txn.score); // "APPROVED" | "IN_REVIEW" | "DECLINED" | ...
const screening = await didit.walletScreening.screen({
wallet_address: "0x...",
blockchain: "ETH",
});
for await (const rule of didit.transactions.rules.list()) console.log(rule.title, rule.mode);
const settings = await didit.travelRule.retrieveSettings();
const vasps = await didit.travelRule.listVasps({ limit: 20 });
这个 transaction.created, (中文(简体) ), transaction.status.updated 财务报告和审定财务报表 travel_rule.status.updated webhooks是被键入的事件.
认证
Didit认证给每个应用程序自己的OpenID Connect发行器,供终端用户使用. 这个 Authentication 帮助者验证它标记的ES256符号,并从后端调取它的符号,会话和起步端点. 它从来不用你的API密钥.
import { Authentication, TokenVerificationError } from "@didit-protocol/sdk-node";
const auth = Authentication.fromPublishableKey(process.env.DIDIT_PUBLISHABLE_KEY!, {
clientId: process.env.DIDIT_APPLICATION_ID!,
});
// or: new Authentication({ issuer: "https://acme.auth.didit.me", clientId: "<application id>" })
try {
const claims = await auth.verifyAccessToken(accessToken);
console.log(claims.sub, claims.org?.role);
} catch (error) {
if (error instanceof TokenVerificationError)
console.log(error.reason); // e.g. "expired"
else throw error;
}
- 选项 :
issuer(或可公布的密钥),clientId(应用程序编号:默认受众,并作为client_id以符号结尾,leeway(秒,默认为60),timeout(每期发行人申请毫升,默认为一万元),fetch, (中文(简体) ),logLevel, (中文(简体) ),logger。 。 。 . verifyAccessToken(token, { audience? })财务报告和审定财务报表verifyIdToken(token, { nonce, audience? }):仅ES256;发行者,观众,到期后,不在并发后使用60s回放. 密钥出自发行人的JWKS,当新密钥出现后被缓存并刷新. 过nonce: null当没有寄出非ce时(从refresh;然后,标志必须携带一无所有。 用于某人的代理工具还验证:act声称是代理人.createPkce(), (中文(简体) ),createState()财务报告和审定财务报表createNonce()属于独立职能(import { createPkce } from "@didit-protocol/sdk-node"用于授权代码流;然后auth.exchangeCode({ code, codeVerifier, redirectUri })。 。 。 .refresh(refreshToken):一个会话的序列式刷新;重新使用已消耗的刷新令牌取消会话.getSession(accessToken)即时撤销检查,revokeSession(accessToken)。 。 。 .createStepUp(accessToken, { action, amount?, currency?, returnTo? })财务报告和审定财务报表retrieveStepUp(accessToken, id): 只按地位行事approved。当前需要returnTo并回答400没有它.submitAgentConsent(accessToken, { challenge, decision, assertion?, scopes?, organizationIds?, lifetime? })批准或拒绝代理请求(核准返回){ code, redirect_uri, state },拒绝{ status: "denied" }; 测试"code" in result和createAgentApprovalOptions(accessToken, { challenge })返回 WebAuthn 数据options仅限人类申请的新密码(403)passkey_required没有它。 也没有经过复审;质疑和断言从未记录在案.
认证在早期进入,随着2026-11-01 Didit发行而达到生产.
日志
设定 DIDIT_LOG=debug (或 logLevel: "debug")以每HTTP请求记录一行:方法,路径,状态,持续时间和请求id. 机构,信头,查询字符串和证书从未被记录.
支持的运行时间
| 运行时间 | 版本数 |
|---|---|
| 节点.js | 第18、20、22、24条 |
| 阿宝 | 1.x 运算 |
| 德诺 | 2.x 数据 |
| 边缘运行时间 | Cloudflare工人、Vercel Edge和其他运行时间 fetch,网络加密和网络流 |
CI运行着每个Node.js版本的测试套件,并在Node.js 18, Bun, Deno 和workd(Cloudflare Workers runtime)上运行了已建成的套件的烟雾测试.
SDK拒绝将您的 API 密钥发送到除了 API 以外的任何地方,但它是一个服务器侧库: 永远不要将您的 API 密钥传送到浏览器 .
语言说明
SDK的选择是共享设计留给每种语言:
- 名称. 资源和方法为骆驼 Case(第1款)
didit.idVerification.verify, (中文(简体) ),retrieveDecision); 请求和响应字段保留API的蛇名 case name. 类似正文字段命名的查询参数需要_query参数对象中的后缀(node_id_query) (中文(简体) ). SDK添加的字段为骆驼Case:requestId关于错误和原始答复,verifiedBy财务报告和审定财务报表bodyAuthenticated在网络上的活动. - 选项. 选项是对象,而不是位置参数 :
new Didit({ apiKey }), (中文(简体) ),new Authentication({ issuer }), (中文(简体) ),verifyIdToken(token, { nonce, audience }), (中文(简体) ),exchangeCode({ code, codeVerifier, redirectUri }), (中文(简体) ),createStepUp(token, { action, ... })设计http_client这是fetch选项(加)fetchOptions(三);logLevel财务报告和审定财务报表logger选择调试行去向。 在边缘运行时,通过API键作为选项(环境变量只在Node.js,Bun和Deno上被读取). - 错误.
APITimeoutError扩展APIConnectionError。 。 。 .TokenVerificationError(核证)和APIResponseValidationError(a 2xx 回答 SDK 无法使用) 完成设计表. - 时代.
timeout以毫秒为单位; webhooktolerance和认证leeway几秒钟,就像他们比对的时间戳. - 约会. 答复日期
Date对象,保持毫秒精度(API发送微秒);没有时区的一个读取为UTC. 只约会字段( O)format: date留下来YYYY-MM-DD字符串。 Webhook事件和认证主张是JSON有效载荷的发送,所以它们的时间戳是数字或字符串,除了会话事件decision,是生成的决定类型Date对象. - Async (英语). 每个API方法,
webhooks.verify认证帮助者返回承诺(Web Crypto是同步的).createPkce, (中文(简体) ),createState财务报告和审定财务报表createNonce也是因为同样的原因. - 结果. 方法返回 a
APIPromise:等待数据,或打电话.withResponse()编号 :.asResponse()。 。 。 . - 缺席而无所取. 可选领域是
?:; 无效字段添加| null; 离开的字段undefined未发送. - 大整数. 在生体上检查Webhook的签名, 并用一个解析器来保存每个数字的位数, 因此2^53以上的整数被精确验证 。 您返回的已键入事件解析
JSON.parse就像每个反应. - 常见JS.
const { Didit } = require("@didit-protocol/sdk-node");无害环境管理默认出口也是require(...).default。 。 。 . - 档案. 路径读取方式
fileFromPath(path);其他的都以字节, Blob 或一行来传递. - 客户端头.
User-Agent: didit-node/<version> (<runtime> <version>; <os>)财务报告和审定财务报表X-Didit-Client: node/<version>,在寄存器名称之后,在每次运行时间.
版本
此软件包随后 语义版本中,每个 Didit 服务器 SDK 共享一个 API 更改规则(文件/DESIGN.md 第13节:
- 反射 Didit API 的更改是一个次要版本,即使它可以打破打入的代码: 类型更改,一个字段现在可以是无效的,或者一个已删除的字段,操作或enum值. API已经对每个呼叫者都这样了,所以这个软件包的更老版本并不安全. 发行注释在"API更改可以打出代码"下列出此类更改.
- 一个主要版本仅用于更改SDK自己的设计:重命名或去除API仍然拥有的一种方法或资源,改变客户端配置,出错,重试,页码或webhook校验,或丢弃所支持的运行时版本.
- API更新,只更改文档不会单独发布任何内容.
版本编号是本套件自有:在更早的规则下于2026-11-05被移动到 2.x,并从那里继续.
释放和 CHANGELOG.md 由常规承诺释放产生.
当API去掉或重命名一个端点时,SDK保留了旧方法为再一个小版本的去皮.
链接
- API 参考和指南 : https://docs.didit.me (英语)
- 每个 Didit 服务器 SDK 共享的设计合同( Python, TypeScript, Go, Java, PHP, Ruby,. NET) : 文件/DESIGN.md
- 贡献(再生、测试、释放): 捐款额
- 警卫: 警卫
许可证
麻省理工学院