免费
适用于构建、测试和您的首批用户。
- 每月500次完整KYC验证
- 身份、活体、人脸匹配、设备和IP验证
- 200+欺诈信号、黑名单、重复项检测
- Didit网络内可复用KYC
- 工作流构建器、案件管理、SDK
- AI 支持 控制台内 AI 助手、文档和社区支持。
全球3,000多家组织信赖。
eID 登录为您带来什么
eID(电子身份识别)登录用方案签名的数据取代了文件照片。Didit 检查签名并将结果记录在会话中。
在工作流程构建器中,打开“ID 验证”步骤,选择一个国家,并在“接受的钱包”下勾选您接受的 eID。然后选择登录失败时的处理方式:回退到文件捕获,或拒绝。
直接来自方法目录
目录中
覆盖国家/地区
eIDAS 高级
MitID · Danish Agency for Digital Government
至少有一个钱包的国家
国家
EUDI 钱包覆盖
覆盖范围按国家/地区遵循目录。此处显示国旗表示该国家/地区列出了钱包,而非已上线。
已显示 136 个,共 136 个方案
MitID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Mobile-ID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Smart-ID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Estonian ID card and Digi-ID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Finnish Trust Network (bank IDs)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
FINeID citizen certificate (ID card)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Mobiilivarmenne
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Auðkenni (app, SIM and card)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Mobile-ID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Smart-ID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Asmens tapatybės kortelė (identity card)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Smart-ID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
eParaksts mobile
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
eID karte (identity card)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
eParaksts karte
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
BankID (Norway)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Buypass ID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Vipps
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Commfides eID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
MinID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
BankID Sweden
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Freja eID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
SverigeID
尚未上线
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
ID Austria
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Smart-ID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
itsme
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Belgian eID card
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
MyGov.be key
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Swiss E-ID (swiyu)
尚未上线
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
SwissID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Online-Ausweisfunktion (Personalausweis)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
d-you
尚未上线
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
FranceConnect
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
France Identité
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
L'Identité Numérique La Poste
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
eID.li
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
itsme
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Luxembourg eID card
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
LuxTrust
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
iDIN
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
itsme
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
DigiD
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
eHerkenning (business login)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Yivi
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
GOV.UK Wallet
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
OneID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
GOV.UK One Login
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Government Digital Wallet
尚未上线
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
MyGovID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Digital Identity (IdentiTek)
尚未上线
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
e-Albania
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
B-Trust Mobile
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
eAuth
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Electronic identity certificate (identity card)
尚未上线
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Evrotrust eID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Cyprus national eID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Bank iD
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
MojeID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
eDoklady
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
eObčanka (identity card)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Identita občana (NIA)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Mobilní klíč eGovernmentu
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Cartera Digital Beta
尚未上线
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Cl@ve
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
DNIe (DNI 3.0 and 4.0)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
MiDNI
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Gov.gr Wallet
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
TAXISnet credentials
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Certilia mobile.ID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
eOI (identity card)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
NIAS (e-Građani)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
DÁP (Digitális Állampolgárság)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Ügyfélkapu+
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
CIE and CieID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
IT-Wallet
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
SPID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Carte de identitate (identity card)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
EVO
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
EVOSign
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
MPass
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Semnătura Mobilă
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Evrotrust eID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
m.Uslugi
尚未上线
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
OneID (KIBS)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
uslugi.gov.mk eID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Maltese e-ID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
e-dowód (identity card)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
login.gov.pl
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
mObywatel
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Profil Zaufany
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Autenticação.gov
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Cartão de Cidadão
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Chave Móvel Digital
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Carte electronică de identitate
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
ROeID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
eID.gov.rs (ConsentID)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Lična karta (identity card)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
eOI and eOsebna
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
SI-PASS
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
eID karta (identity card)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
MeID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Slovensko v mobile
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
e-Devlet
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
T.C. Kimlik Kartı (identity card)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Diia
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
BankID NBU
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
UAE PASS
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Kuwait Mobile ID (Hawyti)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Absher
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Nafath
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
ConnectID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
myID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
National Online Identity Authentication
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Identitas Kependudukan Digital (IKD)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Aadhaar e-KYC
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
DigiLocker
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
My Number Card (JPKI)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Mobile ID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
RealMe verified identity
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
PhilSys (PhilID, ePhilID)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Singpass (Myinfo)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
NDID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
ThaID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Mi Argentina
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
gov.br
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Service d'authentification gouvernementale
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Llave MX
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
DNIe 3.0
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Apple Wallet Digital ID
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Google Wallet ID Pass
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
ID.me
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Login.gov
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
State mobile driver's licences (mDL)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Cédula digital wallet
尚未上线
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
National Identification Number (NIN)
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
Smart ID card
国家/地区
Didit 状态
保障级别
用户操作
返回给您的数据
每次登录价格
最后审阅日期:2026年10月5日。非法律建议。保障级别指该方案依据 eIDAS(欧盟电子身份识别法规)或国家规定所享有的级别,由发行方或欧盟已通告方案清单公布。价格按每次成功登录计算。对于任何标记为“按需提供”的方案,请联系我们:该国家/地区已支持带芯片读取的文档验证方式。
01
选择器会列出您为用户所在国家/地区接受的电子身份,并显示其官方标志。
02
用户检查代码是否匹配,然后使用其电子身份应用中的 PIN 码确认。Didit 绝不会看到 PIN 码。
03
流程会将用户返回给您,并通过 webhook 发送签名结果。
{
"workflow_label": "eID onboarding",
"features": [
{
"feature": "OCR",
"config": {
"methods": {
"DNK": {
"document": { "enabled": true },
"wallet": { "enabled": true, "providers": ["mitid"], "on_failure": "fallback_to_document" }
},
"SWE": {
"document": { "enabled": true },
"wallet": { "enabled": true, "providers": ["bankid_se"], "on_failure": "fallback_to_document" }
}
}
}
}
]
}{ "uuid": "…" }{
"node_id": "ocr",
"status": "Approved",
"verification_method": "wallet",
"assurance": "cryptographic",
"wallet_provider": "mitid",
"wallet_verification": {
"provider": "mitid",
"issuing_country": "DNK",
"level_of_assurance": "substantial",
"signature_valid": true,
"attributes": {
"full_name": "Freja Nielsen",
"date_of_birth": "1988-03-02",
"cpr_alias": "b0f1c2d3-e4f5-4678-9abc-def012345678"
},
"portrait": null
}
}id_verifications[0]# Didit eID verification, integrate in 5 minutes
You are adding national eID sign-in to my_stack: the user verifies with the
eID they already use (a bank or government digital identity), and anyone
without one falls back to document capture in the same flow. Every URL,
header and enum value below is canonical. Do not paraphrase or "improve" them.
## 1. Provision an account
- Sign up: https://business.didit.me
- Create an application and copy its API key from the console.
## 2. Check which eIDs are live, per country
Availability is server-driven. Never hard-code a wallet list.
- Business Console: your application -> Workflows -> the ID Verification
step -> Countries -> "Wallets accepted". Coming-soon wallets are listed
but cannot be switched on. https://docs.didit.me/console/id-verification-methods
- Didit MCP server (https://mcp.didit.me/mcp), tool
didit_workflow_get_id_verification_methods_catalog; pass country as ISO
3166-1 alpha-3 to narrow it. The MCP server signs in with "Log in with
Didit" (OAuth). It does not accept the x-api-key.
https://docs.didit.me/integration/mcp/tools
- Public coverage table (no sign-in, read-only):
https://docs.didit.me/core-technology/id-verification/digital-id-wallets#supported-wallets
If your code holds only an API key, it cannot read the catalog itself: use the
wallet ids listed in this prompt, and treat the answer of the workflow save as
the check. A live application answers 400 for a wallet that is not available
in that country ("<wallet> is not offered in <ISO3>", "unknown wallet").
At the time this prompt was generated, the catalog marked these available:
- MitID: wallet id mitid, country keys DNK
- BankID: wallet id bankid_se, country keys SWE
- Finnish Trust Network: wallet id ftn, country keys FIN
- Smart-ID: wallet id smart_id, country keys EST, LVA, LTU, BEL
- Mobile-ID: wallet id mobile_id, country keys EST, LTU
Coming soon (cannot be enabled yet): BankID, Vipps, Buypass ID, itsme, iDIN, Personalausweis, Freja eID, UAE PASS, gov.br, OneID, GOV.UK Wallet, Bank iD, MojeID, Diia, FranceConnect, Auðkenni, ConnectID, EUDI Wallet, Estonian ID-card, eParaksts.
Check the catalog for your environment before you go live.
## 3. Create the workflow
POST https://verification.didit.me/v3/workflows/
-H "x-api-key: <your-api-key>"
-H "Content-Type: application/json"
The ID Verification feature's enum value is OCR (uppercase, strict). eIDs are
its wallet method, set per country under config.methods. Keys are ISO 3166-1
alpha-3. Keep document capture on, so a user without an eID can still finish.
{
"workflow_label": "eID onboarding",
"features": [
{
"feature": "OCR",
"config": {
"methods": {
"DNK": {
"document": { "enabled": true },
"wallet": { "enabled": true, "providers": ["mitid"], "on_failure": "fallback_to_document" }
},
"SWE": {
"document": { "enabled": true },
"wallet": { "enabled": true, "providers": ["bankid_se"], "on_failure": "fallback_to_document" }
}
}
}
}
]
}
Response: 201. The workflow id is uuid (workflow_id carries the same value);
the workflow is published straight away. Create it once and keep the id:
every call to this endpoint makes a new workflow.
is_desktop_allowed defaults to false: on a desktop browser the hosted flow
then shows a QR code to continue on a phone. Add "is_desktop_allowed": true
next to workflow_label to let people finish on desktop.
Rules the API enforces:
- providers is an accept-list, not a ranking; the user picks
- on_failure is fallback_to_document or decline; it covers a cancelled,
timed-out or failed sign-in
- fallback_to_document where document.enabled is false declines instead
- a wallet the catalog does not mark available in that country rejects the
whole save (400), including every other method in the same request
- enabled true with an empty providers list is rejected
- add { "feature": "LIVENESS" } and { "feature": "FACE_MATCH" } to features
if you need a selfie: the live eIDs do not share a portrait
## 4. Create a session
POST https://verification.didit.me/v3/session/
-H "x-api-key: <your-api-key>"
-H "Content-Type: application/json"
-d '{ "workflow_id": "<id from step 3>", "vendor_data": "<your user id>" }'
Response: 201 with session_id, session_token, url and status "Not Started".
Redirect the user to url (hosted flow) or open it in the Web, iOS, Android,
React Native or Flutter SDK. The field is named url on this response.
One unfinished session exists per workflow_id and vendor_data pair: calling
create again with the same pair answers 201 again with that same session.
The user picks their eID, then approves in the eID app: same-device hand-off
or a QR code on desktop for MitID, BankID and Finnish Trust Network; a
comparison code approved on the phone for Smart-ID and Mobile-ID. Didit never
asks for the user's PIN. A started sign-in stays valid for 10 minutes by
default.
## 5. Webhooks
Register a destination in the console (API & Webhooks), or over the API:
POST https://verification.didit.me/v3/webhook/destinations/
-H "x-api-key: <your-api-key>"
-H "Content-Type: application/json"
-d '{
"label": "Verification webhooks",
"url": "https://<your-public-host>/webhooks/didit",
"webhook_version": "v3",
"subscribed_events": ["status.updated", "data.updated"]
}'
label, url and subscribed_events are required. url must be a public HTTPS
address: Didit does not deliver to localhost or private addresses. Response:
201 with uuid and secret_shared_key. Store secret_shared_key as the webhook
secret (DIDIT_WEBHOOK_SECRET); it is unique to this destination. Remove a
destination with DELETE /v3/webhook/destinations/{uuid}/ (204).
What arrives:
- webhook_type is "status.updated" (the session changed status) or
"data.updated" (verification data was corrected after the fact)
- a destination receives the events of every session of the application,
so filter on workflow_id or vendor_data when several flows share it
- creating a session already sends status.updated with status
"Not Started". The decision key is present only when status is Approved,
Declined, In Review or Abandoned.
Verify every delivery:
Header: X-Signature-V2 (not X-Signature, not X-Signature-Simple)
Algorithm: HMAC-SHA256, hex digest, over the canonical JSON of the payload
(Python json.dumps(sort_keys=True, separators=(",", ":"),
ensure_ascii=False) after whole-valued floats become ints).
Use the reference handler below as written: it rebuilds those
bytes from the raw body text. Never hash the raw request bytes.
Freshness: the signed body field timestamp is the dispatch time (Unix
seconds, refreshed on every retry). Reject when
abs(now - timestamp) > 300 seconds, and reject when the
X-Timestamp header does not equal it.
Idempotency: event_id is the same on every retry of one event, so store it
and skip a delivery you already processed. One session can
still send the same status under two event ids, and the
console's Try Webhook test deliveries carry no event_id, so
also make the handler safe to run twice for one
(session_id, status, webhook_type).
Compare: constant-time (crypto.timingSafeEqual)
Reference handler (Express). Keep the verification lines as written.
The handler is a fragment. Put this above it and app.listen(process.env.PORT)
below it. It needs Express and Node 21 or newer (an older Node rejects
every delivery). It expects a JSON body: answer 400 yourself if you accept
anything else on this route, and refuse to start without the secret.
const express = require("express");
const app = express();
const SECRET = process.env.DIDIT_WEBHOOK_SECRET; // secret_shared_key of the destination
// Your endpoint receives a signed payload
const crypto = require("node:crypto"); // ESM: import crypto from "node:crypto"
// X-Signature-V2 = HMAC over the canonical JSON, never the raw bytes. Match the sender byte for
// byte: keys sorted by code point, integers digit for digit, floats in Python's repr.
class Num { constructor(src) { this.src = src; } } // a number as written on the wire, not a double
const num = (s) => { if (/^-?\d+$/.test(s)) return BigInt(s).toString(); const n = +s; // ints stay exact
if (Number.isInteger(n)) return BigInt(n).toString(); const [m, e] = n.toExponential().split("e"); // 27.0 -> 27
return +e >= -4 ? String(n) : `${m}e-${String(-e).padStart(2, "0")}`; }; // 1e-05, not 0.00001
const byCodePoint = (a, b) => Buffer.compare(Buffer.from(a), Buffer.from(b)); // UTF-8 order = Python's
const canon = (v) => Array.isArray(v) ? `[${v.map(canon)}]` : v instanceof Num ? num(v.src)
: v && typeof v === "object" ? `{${Object.keys(v).sort(byCodePoint).map((k) => `${JSON.stringify(k)}:${canon(v[k])}`)}}`
: JSON.stringify(v);
// Read the body as text: express.json() would round 1000000000000000129 to a double first.
// Register this route ABOVE any global app.use(express.json()): the first parser to run
// consumes the stream, and a body it already parsed has lost the digits the signature covers.
app.post("/webhooks/didit", express.text({ type: "application/json" }), (req, res) => {
const exact = JSON.parse(req.body, (k, v, c) => typeof v === "number" ? new Num(c.source) : v); // Node 21+
const body = JSON.parse(req.body);
const mac = crypto.createHmac("sha256", SECRET).update(canon(exact), "utf8").digest("hex");
const sig = Buffer.from(String(req.headers["x-signature-v2"] ?? ""));
// Freshness comes from the signed body timestamp; the header alone is unsigned and replayable.
const ts = body.timestamp, fresh = String(ts) === req.headers["x-timestamp"]
&& Math.abs(Date.now() / 1000 - ts) <= 300;
if (!fresh || sig.length !== mac.length
|| !crypto.timingSafeEqual(sig, Buffer.from(mac))) return res.sendStatus(401);
const { status, decision } = body;
// One entry per ID Verification node; pick yours by node_id when you run several.
const [idv] = decision?.id_verifications ?? [];
// idv.verification_method: "document" | "id_lookup" | "wallet"
res.sendStatus(200);
});
Status values (exact strings): Not Started, In Progress, Approved, Declined,
In Review, Resubmitted, Expired, Abandoned, Kyc Expired. Awaiting User only
appears on business verification sessions.
## 6. Read the eID result
The same V3 decision reaches you two ways:
- webhook body: body.decision.id_verifications[]
- GET https://verification.didit.me/v3/session/{session_id}/decision/
-H "x-api-key: <your-api-key>"
This response IS the decision object. Read id_verifications at the top
level: there is no decision wrapper here.
Until the user finishes the ID step, status is "Not Started" or "In Progress"
and id_verifications is null, not an empty array. Guard for it.
id_verifications[] has one entry per ID Verification node; with a single step
take index 0 (its node_id is "ocr" on a workflow made by the call in step 3).
The decision's features list names the step ID_VERIFICATION; the workflow
body still takes OCR. Each entry carries:
status Approved, Declined, In Review or Not Finished
verification_method "wallet" for an eID sign-in, "document" after a
fallback
assurance "cryptographic" for a wallet entry, "documentary"
for a document one
full_name, the normalised identity fields, on the entry itself
date_of_birth
wallet_provider the catalog wallet id, for example "mitid"
wallet_verification provider, provider_name, issuing_authority,
issuing_country, credential_type,
level_of_assurance (low | substantial | high),
verified_at, signature_valid, attributes, portrait,
face_match_score
fallback_from { method, reason, action } when the wallet sign-in failed
and on_failure declined the session; otherwise
null. After a document fallback that succeeds the
entry reads verification_method "document" with
fallback_from null
attributes holds what the scheme shares, and the names vary by scheme: MitID
returns cpr_alias (a pseudonymised identifier, not the CPR number), BankID
Sweden personal_number, Finnish Trust Network personal_identity_code, Smart-ID
and Mobile-ID personal_code. Use full_name and date_of_birth on the entry for
the normalised identity fields. No live eID returns an address or a portrait.
Check wallet_verification.level_of_assurance when your rules depend on it. If
a scheme returns a weaker level than the one requested, the sign-in fails
instead of downgrading.
## 7. Billing
- only a completed eID sign-in is billed; cancelled, timed-out, refused
and failed sign-ins are free
- a document fallback is billed as its own document check
- eID checks are outside the document free tier
- published prices per completed sign-in (USD):
- MitID personal: $0.25
- BankID Sweden: $0.20
- Finnish Trust Network: $0.25
- Smart-ID: $0.20
- Mobile-ID: $0.20
- full pricing: https://docs.didit.me/core-technology/id-verification/digital-id-wallets#pricing
## 8. Hard rules
- base URL for v3 endpoints: verification.didit.me
- auth header: x-api-key
- feature enum: OCR; methods: document, id_lookup, wallet
- wallet ids come from the catalog verbatim (mitid, bankid_se, ftn,
smart_id, mobile_id)
- country keys: ISO 3166-1 alpha-3, uppercase
- webhook: X-Signature-V2 plus X-Timestamp, canonical JSON, freshness from
the signed body timestamp
## 9. Verify your integration
Sandbox (an application in sandbox mode: nothing is billed and no real eID is
called). https://docs.didit.me/integration/sandbox-testing
- a sandbox application can enable every wallet in the catalog, the
coming-soon ones included. A workflow that saves in sandbox can still be
refused on a live application, so only use wallets marked available.
- open the session url, pick the wallet and confirm: the default approve
scenario simulates the sign-in. The entry then has verification_method
"wallet", assurance "cryptographic" and wallet_provider set, and the
normalised full_name and date_of_birth are filled. But
wallet_verification.signature_valid and level_of_assurance are null and
attributes is { "sandbox": true }: no real credential was checked.
Assert signature_valid === true and the level of assurance only against
a live application.
- to exercise on_failure, create the session with
"sandbox_scenario": "wallet_cancelled" (also wallet_timeout and
wallet_provider_error). The wallet sign-in then fails and the flow moves
to document capture or declines, as on_failure says. A fallback that
ends in an approved document reads verification_method "document".
- POST /v3/session/{session_id}/simulate/ forces a final status but writes
no id_verifications entry, so it cannot stand in for a sign-in.
Checks:
- create the workflow, create a session, and read its decision: expect 201,
201 with url, and 200 with status "Not Started"
- run one sandbox session per accepted eID through the hosted flow and
assert verification_method is "wallet" and wallet_provider is the eID you
picked
- run one session with sandbox_scenario "wallet_cancelled" and assert the
flow offers document capture
- assert your webhook accepts a correctly signed payload and rejects a
wrong X-Signature-V2, a changed body, and a payload whose signed
timestamp is older than 300 seconds, even when X-Timestamp is refreshed
- on a live application, assert wallet_verification.signature_valid is true
Docs: https://docs.didit.me/core-technology/id-verification/digital-id-wallets
适用于构建、测试和您的首批用户。
25+ 模块,价格公开透明。自动享受批量折扣。
适用于大批量和受监管项目。
使用量增长时自动享受批量折扣——无需谈判,无需销售电话。
Didit 是身份验证和欺诈防护的基础设施,是我们自己构建产品时梦寐以求的平台:开放、灵活、对开发者友好,能真正融入您的技术栈,而不是一个需要您围绕其进行集成的黑盒。
一个 API 即可覆盖个人验证(KYC,了解您的客户)、企业验证(KYB,了解您的业务)、加密钱包筛选(KYT,了解您的交易)以及实时交易监控。我们的技术栈旨在实现:
底层支持:14,000 多种文档类型,支持 48 种以上语言,1,000 多个数据源,每次会话提供 200 多个欺诈信号。Didit 基础设施通过每次会话动态学习,并日益优化。
eID 验证(电子身份识别)是指通过个人已持有的、由政府或银行签发或批准的数字身份来核实身份,而不是要求提供证件照片。用户使用其国家 eID 登录,在 eID 应用中批准共享数据,然后系统会返回带有数字签名的身份属性。
对于企业而言,区别在于您收到的信息。证件检查提供的是需要分析的图像。eID 登录提供的是发行方已验证并签名的数据:姓名、出生日期、方案标识符(例如瑞典的 personnummer;MitID 返回的是假名化标识符)和保障级别。
Didit 在工作流的身份验证步骤中运行 eID 登录。目前已支持五种国家 eID(MitID、BankID Sweden、Finnish Trust Network、Smart-ID 和 Mobile-ID),没有 eID 的用户可在同一会话中通过证件检查完成验证。本页面的覆盖范围表列出了按国家/地区划分的所有方案。
目前有五种国家 eID 已在七个国家/地区上线:
更多 eID 即将推出:iDIN、德国 eID 卡 (Personalausweis)、Freja eID、爱沙尼亚 ID 卡、eParaksts、BankID Norway、Vipps、Buypass、itsme、OneID、ConnectID、UAE PASS、gov.br、GOV.UK Wallet、Bank iD、MojeID、Diia、FranceConnect 和 Auðkenni,以及 EUDI 钱包支持。您可以在控制台中查看即将推出的 eID,但在它们上线之前无法启用。
对于覆盖范围表中列出的其他方案,请联系我们:Didit 可根据需求添加方案,并且在这些国家/地区,带芯片读取功能的证件验证路线已可用。
您将收到方案签名的属性,并已标准化到会话中。每个已上线的 eID 都会返回全名和出生日期,以及方案自身的识别码:
每个结果还会记录方案声明的保障级别以及 signature_valid,即 Didit 对签名断言的检查。目前没有已上线的 eID 返回地址或肖像,因此如果您的政策需要自拍,请添加活体检测和人脸匹配步骤;如果需要地址,请添加第二个数据源。
在 API 中,结果位于决策的身份验证条目中的 wallet_verification,其中 verification_method 设置为 wallet。
保障级别(LoA)表示 eID 对个人身份声明的信任程度。欧盟 eIDAS 电子身份识别法规定义了三个级别:低、实质性和高。每个方案的级别都来自欧盟已通知方案列表或方案自身的规则,许多国家方案根本未获得欧盟通知。
您需要的级别取决于您遵循的规则,而非 Didit。例如,AMLR(欧盟反洗钱法规)接受实质性或高级别的电子身份识别用于客户检查。
Didit 会在 wallet_verification.level_of_assurance 中记录每次登录实际声明的级别。如果方案返回的级别低于请求的级别,登录将失败,而不会悄悄降级。Didit 将 MitID、BankID Sweden 和 Finnish Trust Network 登录标记为实质性,将 Smart-ID 和 Mobile-ID 登录标记为高级别。
对于身份部分,这可能是足够的。AMLR(欧盟法规 2024/1624,自 2027 年 7 月 10 日起适用)第 22(6) 条允许义务实体使用身份证明文件或 eIDAS 下的电子身份识别来验证客户身份。AMLA(欧盟反洗钱管理局)于 2026 年 9 月 30 日发布的客户尽职调查最终草案标准,将 eID 视为默认的远程途径,并将基于文件的远程验证视为合理的替代方案。这些是提交给欧盟委员会的最终草案,并非法律。
身份验证是 KYC(了解您的客户)的一部分。您仍然需要制裁和 PEP 筛选、公司受益所有人、持续监控和记录,并且决策权仍在您手中。Didit 在同一工作流中运行这些检查,AML 筛选每次检查 $0.20,持续监控每人每年 $0.07。
这不是法律建议。AMLR 页面将每篇文章映射到 Didit 提供的内容。
他们将在同一会话中完成证件检查。对于每个国家/地区,您可以选择当 eID 登录被取消、超时或失败时发生的情况:回退到证件采集或拒绝。
证件验证路线涵盖 220 多个国家和地区的 14,000 多种证件类型。它会采集 ID,通过原生 SDK 读取电子护照和 eID 卡的芯片 (NFC),运行被动活体检测并将人脸与证件照片进行匹配。一次完整的 KYC 检查,包括证件、活体检测、人脸匹配以及设备和 IP 分析,费用为 $0.33。
由于回退是工作流的一部分,您的集成无需更改:您创建一个会话,结果会告诉您用户采取了哪种路线(verification_method 是 wallet 或 document)。只有完成的 eID 登录才按 eID 检查计费,回退则按其自身的证件检查计费。
可以。eID 登录会返回方案签名的出生日期,因此无需提供证件照片即可证明年龄。
对于大批量验证,推荐的设计是先进行年龄估算:自拍估算年龄每次检查 $0.10,包含被动活体检测,整体平均绝对误差为 3.5 岁,18 岁以下为 1.5 岁。明确通过和明确失败的在此结束,只有临界结果才会进行更严格的检查,例如 eID 登录或证件检查。
监管机构对这些方法的处理方式不同。在英国,Ofcom 将面部年龄估算和数字 ID 列为高效方法。在欧盟,数字服务法 (DSA) 下的指南将 18 岁以上内容的估算视为临时过渡方案,并倾向于使用欧盟年龄验证应用或 EUDI 钱包。年龄验证页面涵盖了按国家/地区划分的规则。
eID 登录按每个方案、每次完成的登录计费。本页面的覆盖范围表显示了每个已上线 eID 的当前公布价格,这些价格与定价页面上的数据相同。标记为“按需”的方案将单独报价。
您只需在登录完成时付费。已取消、超时、拒绝和失败的登录是免费的,重复的回调或状态检查不会产生额外费用。eID 检查不属于免费证件层级。
工作流的其余部分按公布价格计费:完整的 KYC 检查(含证件)费用为 $0.33,NFC 芯片读取 $0.15,年龄估算 $0.10,AML 筛选 $0.20,持续监控每人每年 $0.07。证件回退按其自身的证件检查计费。您可以在承诺任何事情之前创建账户并在沙盒中进行测试。
不,对于已上线的方案不需要。Didit 拥有 MitID、BankID Sweden、Finnish Trust Network、Smart-ID 和 Mobile-ID 的方案连接,因此您无需与每个方案、银行或证书提供商单独签订协议即可接受它们。您只需在工作流中启用 eID,并按每次完成的登录向 Didit 付费。
选择器和比较代码屏幕会继承您的会话品牌和自定义域名,因此用户会留在您的流程中。方案仍会显示其自己的应用和同意步骤,因为这是用户批准共享数据的地方。
有些方案对谁可以接受它们有自己的规则;一些政府登录仅对公共服务开放。对于尚未上线的任何方案,请与我们讨论其要求以及 Didit 如何连接它。
两者都依赖于密码学,但它们证明的是不同的事情。NFC 芯片读取使用手机读取电子护照或 eID 卡内部的芯片,并检查发行方对该数据的签名,这表明证件是真实的且未被篡改。它仍然需要活体检测和人脸匹配来证明持有者是其所有者。在 Didit 中,它在原生 iOS 和 Android SDK 中运行,费用为 $0.15。
eID 登录表明用户控制着他们的国家数字身份:他们通过 PIN 或生物识别在 eID 应用中批准,方案会签署他们的属性。不涉及证件,已上线的 eID 不共享肖像。
两者配合得很好。在有 eID 的地方提供 eID,对于其他所有人,在同一工作流中,按国家/地区回退到带芯片读取功能的证件采集。
根据 eIDAS 2(欧盟法规 2024/1183),欧盟各成员国必须在 2026 年 12 月 24 日前提供 EUDI 钱包(欧盟数字身份钱包)。法律或合同要求使用强用户认证的私营企业,必须在 2027 年 12 月 24 日前应用户要求接受 EUDI 钱包。微型和小型企业可豁免。该期限为首批实施法案于 2024 年 12 月 24 日生效后的 36 个月,即 2027 年 12 月 24 日。
意大利的 IT-Wallet 和丹麦的 AltID 是目前最先进的国家级应用,德国的钱包应用预计将于 2027 年初推出。
Didit 即将支持 EUDI 钱包:我们的钱包目录已列出 30 个 EEA 国家/地区,与国家 eID 采用相同的工作流程。在此之前,您可以使用现有的国家 eID 和文档验证方式来服务客户。EUDI 钱包页面详细解释了企业接受 EUDI 钱包的具体要求。
可以。Didit 可根据需求添加方案,因此请告诉我们您的客户使用哪些国家 eID、银行 ID 或政府登录,以及在哪些国家/地区。我们会研究方案对接受它的企业有什么要求(有些对私营公司开放,有些仅对公共服务开放)以及它返回什么,然后向您反馈连接它所需的一切。
同时,这并不妨碍您在该国家/地区上线。证件验证路线目前在那里可用:涵盖 14,000 多种证件类型的证件采集、电子护照和 eID 卡的芯片 (NFC) 读取、被动活体检测和人脸匹配,以及对 1,300 多个列表的 AML 筛选。
当方案上线时,您只需在该国家/地区的工作流中勾选它,您的集成保持不变。请使用“联系我们”开始。
您当天即可测试。在 business.didit.me 创建账户,打开您的工作流,在“身份验证”步骤中进入“国家/地区”,选择一个国家/地区,然后勾选“接受的钱包”下的 eID。设置回退,然后保存并发布。
最快的方式是托管流程:通过一个 API 调用 (POST /v3/session/) 创建会话,并将用户重定向到返回的 URL。Didit 会显示 eID 选择器,然后交给 eID 应用处理,并将签名结果发送到您的 webhook。如果您希望用户留在您的应用内,Web、iOS、Android、React Native 和 Flutter SDK 均可开启相同的流程。
请先使用沙盒应用程序进行测试,然后切换到您的实时应用程序。本页面的集成提示可让编码代理为您构建整个流程。