跳到主要内容
Didit 融资 750 万美元,打造身份与欺诈基础设施
Didit
数字身份钱包

让用户使用
他们已有的身份登录。

通过用户已在使用的电子身份(eID)验证身份。在一个工作流中接入 MitID、瑞典 BankID、Finnish Trust Network、Smart-ID 和 Mobile-ID,必要时回退到证件验证。

投资方
Y CombinatorRobinhood Ventures
Firecrawl
Slash
Crnogorski Telekom
UCSF Neuroscape
Bit2Me

全球3,000多家组织信赖。

  • MitIDDenmark · Danish Agency for Digital GovernmentDenmark已上线
  • BankIDSweden · Finansiell ID-Teknik / bank consortiumSweden已上线
  • BankIDNorway · BankID BankAxept ASNorway即将上线
  • VippsNorway · Vipps MobilePay / BankID NONorway即将上线
  • Buypass IDNorway · Buypass ASNorway即将上线
  • itsmeBelgium, Luxembourg, Netherlands · Belgian Mobile IDBelgiumLuxembourgNetherlands即将上线
  • iDINNetherlands · Dutch banks (Currence iDIN)Netherlands即将上线
  • Finnish Trust NetworkFinland · Finnish banks and mobile operators (FTN)Finland已上线
  • PersonalausweisGermany · Bundesministerium des Innern (eID)Germany即将上线
  • Freja eIDSweden · Freja eID GroupSweden即将上线
  • UAE PASSUnited Arab Emirates · UAE Digital Government AuthorityUnited Arab Emirates即将上线
  • gov.brBrazil · Governo Federal do BrasilBrazil即将上线
  • OneIDUnited Kingdom · OneID (UK bank-verified identity)United Kingdom即将上线
  • GOV.UK WalletUnited Kingdom · UK Government Digital ServiceUnited Kingdom即将上线
  • Smart-IDEstonia, Latvia, Lithuania, Belgium · SK ID SolutionsEstoniaLatviaLithuaniaBelgium已上线
  • Mobile-IDEstonia, Lithuania · SK ID Solutions with the national mobile operatorsEstoniaLithuania已上线
  • Bank iDCzechia · Bankovní identita, a.s.Czechia即将上线
  • MojeIDCzechia · CZ.NICCzechia即将上线
  • DiiaUkraine · Ministry of Digital Transformation of UkraineUkraine即将上线
  • FranceConnectFrance · DINUM (French state)France即将上线
  • AuðkenniIceland · Auðkenni (Icelandic electronic ID)Iceland即将上线
  • ConnectIDAustralia · Australian Payments PlusAustralia即将上线
  • EUDI Wallet30 个欧盟和欧洲经济区国家 · The user's own member state; the issuer differs per countryAustriaBelgiumBulgariaCroatia+26即将上线

状态区分了生产可用性与集成测试。国家/地区覆盖范围描述了配置的电子钱包路由,而不是在每个国家/地区都完成了实时身份检查。不承诺发布日期。

集成状态

数字身份电子钱包。
清晰的推出状态。

MitID、瑞典 BankID、Finnish Trust Network、Smart-ID 和 Mobile-ID 现已可用。按国家选择接受的钱包,让用户使用已持有的合格身份完成认证。列表中的其他集成即将推出。

工作原理

从钱包登录到验证用户,仅需四步。

步骤 01 / 04

创建工作流

在控制台中,选择您环境中每个国家/地区可用的电子钱包。选择取消或失败的登录是回退到文档捕获还是拒绝。

专为开发者打造 · 专为防欺诈设计 · 开放式设计

六大功能。每个国家/地区一个接受列表。

数字钱包是身份验证中的一种方法,与文档捕获使用相同的返回契约。不同之处在于凭证:数字钱包使用发行方的签名,而非照片。
01 · 目录

接受特定国家/地区实际使用的数字钱包。

在一处查看每个钱包、覆盖国家、签发机构和可用状态。MitID、瑞典 BankID、Finnish Trust Network、Smart-ID 和 Mobile-ID 现已可用;计划中的集成都清楚标注为即将推出。
02 · 接受列表

勾选您接受的。用户选择。

选择在您的工作流中每个国家/地区接受哪些可用电子钱包。用户从该集合中选择。列为即将推出的电子钱包在您环境中的目录将其标记为可用之前无法启用。
03 · 移交

比较代码。在手机上批准。

Smart-ID 使用您的个人代码;Mobile-ID 还需要您的电话号码。当您在设备上批准请求时,Didit 会显示一个比较代码。您的 PIN 码绝不会输入到 Didit 中。取消和失败遵循您的工作流回退设置。
04 · 签名属性

读取发行方签名的属性。

姓名、出生日期和数字钱包公开的国家/地区标识符,以及签名断言本身。取消勾选任何您不想存储的可选属性,它将永远不会写入会话。
05 · 保障

达到三个保障等级中的最高级别。

文档提供文档保障。注册表查询提供数据匹配。数字钱包提供加密保障,因为发行方签署了属性,Didit 会检查该签名。
06 · 覆盖范围

每个已上线钱包的国家覆盖范围。

在丹麦接受 MitID,在瑞典接受 BankID,在芬兰接受 Finnish Trust Network,在爱沙尼亚、拉脱维亚、立陶宛和比利时接受 Smart-ID,在爱沙尼亚和立陶宛接受 Mobile-ID。用户使用所选钱包的合格凭证完成认证。
集成

一次调用。一次签名结果返回。

创建会话,将用户发送到该会话,并在结果到达时验证签名的 webhook。用户登录所用的数字钱包将随结果返回。
POST /v3/session/托管 UI
$ curl -X POST https://verification.didit.me/v3/session/ \
  -H "x-api-key: <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "workflow_id": "<your-workflow-uuid>",
    "vendor_data": "user_42"
  }'
201已创建{ "url": "https://verify.didit.me/..." }
Didit 显示接受的数字钱包并执行移交。文档
POST /webhooks/diditWebhook
// 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);
});
200确定{ "verification_method": "wallet", "assurance": "cryptographic" }
在信任有效载荷之前验证签名。文档
代理就绪集成

一键实现数字钱包登录。

将以下代码块粘贴到 Claude Code、Cursor、Codex、Devin、Aider 或 Replit Agent 中。用您的框架、语言和用例填充 my_stack 占位符。代理将配置 Didit,接受每个国家/地区的数字钱包,连接 webhook,并发布。
didit-integration-prompt.md
# Didit digital ID wallets — integrate in 5 minutes

You are adding digital ID wallet sign-in to my_stack. The user signs in with a
government or bank digital identity and the wallet returns signed attributes.
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 (no credit card required).
- Grab the API key for your application from the console.

## 2. Read the methods catalog first
Wallet availability is server-driven per country. Never hard-code a wallet list.

Read the catalog one of these ways:
  - 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").

The catalog gives you, per wallet id: the display name, the countries it
covers, the issuing authority, the level of assurance, the availability state,
and the attributes it returns. When this prompt was generated it 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
Finnish Trust Network has its own integration guide:
https://docs.didit.me/core-technology/id-verification/finnish-trust-network
iDIN and other wallets remain coming soon until the catalog in
your environment marks them available. Check it; do not hard-code a date.

## 3. Create a workflow with the ID Verification (OCR) feature
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 enum;
there is no ID_VERIFICATION alias and the API rejects it). Wallets are its
wallet method, accepted per country under config.methods on that same
feature entry, in the same request. Keys are ISO 3166-1 alpha-3.

{
  "workflow_label": "Wallet onboarding",
  "features": [
    {
      "feature": "OCR",
      "config": {
        "methods": {
          "DNK": {
            "document": { "enabled": true },
            "wallet": {
              "enabled": true,
              "providers": ["mitid"],
              "on_failure": "fallback_to_document"
            }
          },
          "FIN": {
            "document": { "enabled": true },
            "wallet": {
              "enabled": true,
              "providers": ["ftn"],
              "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.
Use that id as workflow_id in step 4. The ID Verification node id of a
workflow made by this call is "ocr".

Rules that the API enforces:
  - providers is an accept-list, not a ranking. Order carries no meaning and
    the end user picks
  - on_failure is either fallback_to_document or decline. It covers all three
    cases: no wallet, cancelled, sign-in failed
  - a wallet id the catalog does not mark available for that country is
    rejected, and the rejection fails the whole save — including any lookup
    configuration next to it. For unavailable wallets, keep wallet.enabled
    false (or omit the wallet block) so the save succeeds. A sandbox
    application accepts coming-soon wallets, so this only shows on live
  - unknown wallet ids already saved on a workflow are preserved untouched, so
    a config written by a newer console version is never silently dropped
  - a country with no method enabled is rejected at publish time

## 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.
Didit shows the accepted wallets for the user's country with their brand marks,
hands off to the wallet, and waits for the signed assertion to come back.

## 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
               — the sender's Python json.dumps(sort_keys=True,
               separators=(",", ":"), ensure_ascii=False) after whole-valued
               floats become ints. Reproduce those bytes EXACTLY; do NOT
               "parse, sort keys, JSON.stringify", which fails in four ways:
               numbers come from the wire TEXT, never from parsed doubles
               (read the body with express.text, not express.json(),
               registered ABOVE any global app.use(express.json()), and
               re-emit integers through BigInt(source) — JSON.parse rounds
               1000000000000000129); floats use Python's repr (1e-05, not
               0.00001; 27.0 becomes 27); keys sort by Unicode CODE POINT as
               strings ("10" before "2", U+FF21 before U+1F642, which
               JavaScript's default .sort() reverses); and the bytes come
               straight from the sorted entries, never from a rebuilt object.
               Do NOT hash the raw request bytes — that is the v1
               X-Signature algorithm and fails for V2 whenever whitespace or
               key order differs from the canonical form.
  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. The header is not
               covered by the signature, so it must never be the only replay
               check: a captured delivery replays with just that header
               refreshed.
  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);
});

Body fields you will use: event_id, session_id, status, webhook_type,
workflow_id, vendor_data, timestamp, decision.
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. Reading the 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.

The decision is the V3 shape: every feature result is a plural array with one
entry per workflow node. ID Verification results live in
id_verifications[]: there is no singular kyc (that is the V2 shape) and no
id_verification. The decision's features list names the step
ID_VERIFICATION, while the workflow body takes OCR. Select your entry by node_id (the
id of your ID Verification node in the workflow graph); with a single ID step,
take index 0. Each entry carries, next to the document fields:

  verification_method    "document" | "id_lookup" | "wallet"
  assurance              "documentary" | "data_match" | "cryptographic"
  wallet_provider        the catalog wallet id the user signed in with; null
                         on document and id_lookup entries
  wallet_verification    provider, provider_name, issuing_authority,
                         issuing_country, credential_type, level_of_assurance
                         (low | substantial | high), verified_at,
                         signature_valid, attributes (what the wallet shared),
                         portrait when the wallet shares one; null otherwise
  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

A wallet entry that succeeds is assurance cryptographic: an identity provider
authenticated the person and signed the attributes. The normalised full_name
and date_of_birth sit on the entry itself; attributes holds the wallet's own
claims. On a live application, check wallet_verification.signature_valid
before you trust attributes.
Field-by-field reference: https://docs.didit.me/reference/data-models#id-verification

## 7. Billing
  - published customer prices in USD per completed wallet verification:
    - MitID personal: $0.25; production availability: Available
    - BankID Sweden: $0.20; production availability: Available
    - Finnish Trust Network: $0.25; production availability: Available
    - Smart-ID: $0.20; production availability: Available
    - Mobile-ID: $0.20; production availability: Available
    - BankID Norway High: $0.35; production availability: Coming soon
    - Vipps Plus: $0.25; production availability: Coming soon
    - Buypass ID: Coming soon; production availability: Coming soon
    - itsme: Coming soon; production availability: Coming soon
    - iDIN full identification: $0.85; production availability: Coming soon
    - Personalausweis Profile 2: $0.45; production availability: Coming soon
    - Freja eID: $0.25; production availability: Coming soon
    - UAE PASS: Coming soon; production availability: Coming soon
    - gov.br: Coming soon; production availability: Coming soon
    - OneID: $2.50; production availability: Coming soon
    - GOV.UK Wallet: Coming soon; production availability: Coming soon
    - Bank iD: Coming soon; production availability: Coming soon
    - MojeID: Coming soon; production availability: Coming soon
    - Diia: Coming soon; production availability: Coming soon
    - FranceConnect: Coming soon; production availability: Coming soon
    - Auðkenni: Coming soon; production availability: Coming soon
    - ConnectID: Coming soon; production availability: Coming soon
    - EUDI Wallet: Coming soon; production availability: Coming soon
    - Estonian ID-card: $0.55; production availability: Coming soon
    - eParaksts mobile: $0.55; production availability: Coming soon
  - an announced price does not enable a wallet; check the live workflow catalog
  - wallet checks are outside the document free tier; other checks are billed separately
  - full pricing: https://docs.didit.me/core-technology/id-verification/digital-id-wallets#pricing
  - document capture bills its own price when the user falls back

## 8. Hard rules — do not change
  - base URL for v3 endpoints: verification.didit.me
  - auth header: x-api-key (lowercase, hyphenated)
  - webhook headers: X-Signature-V2 plus X-Timestamp; canonical JSON, never
    raw bytes; freshness from the signed body timestamp
  - feature enum: OCR (uppercase) — the ID Verification feature; per-country
    methods go under its config.methods
  - method keys: document, id_lookup, wallet (lowercase, snake_case)
  - wallet ids come from the catalog verbatim, lowercase, snake_case
  - country keys: ISO 3166-1 alpha-3, uppercase
  - result path: decision.id_verifications[] in the webhook body and
    id_verifications[] on the GET decision response, never kyc

## 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 session per accepted wallet in sandbox through the hosted flow
  - assert the id_verifications[] entry for your node has verification_method
    wallet and wallet_provider set to the wallet you picked
  - run one session with sandbox_scenario "wallet_cancelled" and assert your
    on_failure setting actually fires
  - on a live application, assert wallet_verification.signature_valid is true
  - assert your webhook accepts a correctly signed payload with reordered
    keys, whitespace and integer-like metadata keys ("10" before "2"), and
    rejects a wrong X-Signature-V2, a payload whose signed timestamp is older
    than 300 seconds, and that same stale payload with only the X-Timestamp
    header refreshed

Docs: https://docs.didit.me/integration/integration-prompt
合规性设计

一键开启新国家/地区业务。 我们为您解决难题。

我们负责设立当地子公司、获取许可证、进行渗透测试、获得认证,并与所有新法规保持一致。要在新国家/地区发布验证服务,只需轻点开关。已覆盖220多个国家/地区,每个季度进行审计和渗透测试, 是唯一一个被欧盟成员国政府正式认定比线下验证更安全的身份提供商。
阅读安全与合规性档案
SOC 2 · Type II — AICPA · 2026
SOC 2 · Type I — AICPA · 2026
ISO/IEC 27001 — 信息安全 · 2026
欧盟金融沙盒 — Tesoro · SEPBLAC · BdE
FIDO Alliance — 准会员 · 2026
iBeta Level 1 PAD — NIST / NIAP · 2026
GDPR — EU 2016/679
HIPAA — 45 CFR §160 · §164
DORA — EU 2022/2554
MiCA — EU 2023/1114
EBA 远程入驻 — EBA/GL/2022/15
AMLD6 · eIDAS 2.0 — 原生符合欧盟标准
Jugendschutz geprüft — FSM · JMStV §4(2) · 2026

证明数据

证明数据
  • 23
    方法目录中的数字钱包
  • 35
    目录中的国家/地区
  • 10
    达到 eIDAS 高级保障的数字钱包
  • $0.15
    当用户回退时,文档捕获

数字身份钱包定价与可用性

以下价格为每完成一次钱包验证的美元价格。这些价格涵盖了指定的身份产品;其他工作流程检查和文档回退将单独计费。每月 500 次免费文档检查不包括钱包。已公布的价格不代表钱包已上线:可用性单独显示。没有公布费率的可用钱包显示“按需报价”;没有公布费率的计划中钱包显示“即将推出”。身份钱包用于验证个人身份;加密钱包筛选是单独的产品。

“可用”表示已在生产环境中启用。“即将推出”表示尚未在生产环境中启用,即使已开始集成测试。可用的钱包将优先显示。

ConnectID(澳大利亚)、爱沙尼亚身份证(爱沙尼亚)和 eParaksts mobile(拉脱维亚)已集成用于沙盒测试。请查看表格,了解每个钱包的公布价格和生产可用性。

阅读详细文档
数字身份钱包定价与可用性
身份钱包美元/次完成验证国家/地区生产可用性
MitID personalUS$0.25
  • Denmark
可用
BankID SwedenUS$0.20
  • Sweden
可用
Finnish Trust NetworkUS$0.25
  • Finland
可用
Smart-IDUS$0.20
  • Estonia
  • Latvia
  • Lithuania
  • Belgium
可用
Mobile-IDUS$0.20
  • Estonia
  • Lithuania
可用
BankID Norway HighUS$0.35
  • Norway
即将推出
Vipps PlusUS$0.25
  • Norway
即将推出
Buypass ID即将推出
  • Norway
即将推出
itsme即将推出
  • Belgium
  • Luxembourg
  • Netherlands
即将推出
iDIN full identificationUS$0.85
  • Netherlands
即将推出
Personalausweis Profile 2US$0.45
  • Germany
即将推出
Freja eIDUS$0.25
  • Sweden
即将推出
UAE PASS即将推出
  • United Arab Emirates
即将推出
gov.br即将推出
  • Brazil
即将推出
OneIDUS$2.50
  • United Kingdom
即将推出
GOV.UK Wallet即将推出
  • United Kingdom
即将推出
Bank iD即将推出
  • Czechia
即将推出
MojeID即将推出
  • Czechia
即将推出
Diia即将推出
  • Ukraine
即将推出
FranceConnect即将推出
  • France
即将推出
Auðkenni即将推出
  • Iceland
即将推出
ConnectID即将推出
  • Australia
即将推出
EUDI Wallet即将推出
  • Austria
  • Belgium
  • Bulgaria
  • Croatia
  • Cyprus
  • Czechia
  • Denmark
  • Estonia
  • Finland
  • France
  • Germany
  • Greece
  • Hungary
  • Ireland
  • Italy
  • Latvia
  • Lithuania
  • Luxembourg
  • Malta
  • Netherlands
  • Poland
  • Portugal
  • Romania
  • Slovakia
  • Slovenia
  • Spain
  • Sweden
  • Iceland
  • Liechtenstein
  • Norway
即将推出
Estonian ID-cardUS$0.55
  • Estonia
即将推出
eParaksts mobileUS$0.55
  • Latvia
即将推出
三个层级,一份价目表

免费开始,按需付费,可扩展至企业版。

每月500次免费验证,永久有效。之后仅按模块运行付费。企业版提供定制合同、数据驻留和SLA服务。

免费

$0/ 月 · 无需信用卡

适用于构建、测试和您的首批用户。

开始所需的一切:
  • 每月500次完整KYC验证
  • 身份、活体、人脸匹配、设备和IP验证
  • 200+欺诈信号、黑名单、重复项检测
  • Didit网络内可复用KYC
  • 工作流构建器、案件管理、SDK
  • AI 支持 控制台内 AI 助手、文档和社区支持。
最受欢迎

按需付费

$0.33每次完整 KYC

25+ 模块,价格公开透明。自动享受批量折扣。

包含 免费 的所有功能,以及:
  • AML 筛选和监控,低至 $0.07
  • 按国家/地区和数据层级划分的商业注册定价
  • 交易监控 $0.02 / 次
  • 钱包筛选 $0.15 / 次
  • 自有品牌白标流程
  • AI 支持 控制台内 AI 助手、文档和社区支持。

企业版

定制年度合同

适用于大批量和受监管项目。

包含 按需付费 的所有功能,以及:
  • 年度合同,承诺用量定价
  • 定制法律条款和99.99%正常运行时间SLA
  • 数据驻留、保留、安全审查
  • 按需提供人工审核员
  • 经销商和白标条款
  • 优先人工支持 24/7 共享 Slack 频道,专属客户成功经理。

使用量增长时自动享受批量折扣——无需谈判,无需销售电话。

FAQ

常见问题

Didit 是什么?

Didit 是身份和欺诈基础设施,是我们自己构建产品时希望拥有的平台:开放、灵活且对开发者友好,因此它可以作为您技术栈的真正一部分,而不是一个需要您围绕其集成的黑盒。

一个 API 涵盖了人员验证(KYC,了解您的客户)、企业验证(KYB,了解您的业务)、加密钱包筛选(KYT,了解您的交易)以及实时监控交易,其技术栈旨在实现:

  • 快速,每次会话的 p99 响应时间低于 2 秒
  • 可靠,已在 220 多个国家/地区的 3,000 多家公司投入生产
  • 安全,符合 SOC 2 Type 1 和 Type 2、ISO 27001、GDPR 原生,并经西班牙金融监管机构正式证明比亲自验证更安全

其底层支持:48 种以上语言的 14,000 多种证件类型、1,000 多个数据源以及每次会话的 200 多个欺诈信号。Didit 基础设施从每次会话中动态学习并日益完善。

什么是数字身份钱包核验?

用户使用现有的电子身份 (eID) 进行身份验证,Didit 在将结果写入会话之前检查签名的身份证据。交互方式取决于电子钱包:Smart-ID 要求输入个人代码,而 Mobile-ID 还需要输入电话号码。两者都使用比较代码并在用户设备上进行批准。

电子钱包身份验证是身份验证中的一种方法,与文档捕获和非文档查找并行。在工作流 API 中,该功能名为 OCR。可用的电子钱包取决于国家和环境。请从电子钱包文档开始。

我可以在生产环境中启用哪些数字身份电子钱包?

MitID、瑞典 BankID、Finnish Trust Network、Smart-ID 和 Mobile-ID 现已可用。MitID 服务丹麦,BankID 覆盖瑞典,Finnish Trust Network 覆盖芬兰;Smart-ID 覆盖爱沙尼亚、拉脱维亚、立陶宛和比利时;Mobile-ID 覆盖爱沙尼亚和立陶宛。列表中的其他钱包,包括 iDIN、挪威 BankID、Freja eID、ConnectID 和 EUDI 钱包,即将推出。

在控制台中为每个国家/地区选择接受的钱包。工作流程 API 使用您环境和国家/地区的目录。使用集成指南配置文档回退。

Smart-ID 和 Mobile-ID 用户如何验证其身份?

用户选择一个接受的钱包,输入其个人代码,并为 Mobile-ID 提供电话号码。Didit 显示一个比较代码。用户检查该代码是否与手机上的代码匹配,并在手机上批准身份验证请求。PIN 码仅在用户设备上输入,绝不会输入到 Didit 中。

Didit 等待签名响应,检查签名和证书状态,并将已验证的身份属性返回给会话。完成时间取决于用户和钱包响应。请遵循 Smart-ID 和 Mobile-ID 指南。

Didit 如何验证 Smart-ID 和 Mobile-ID 身份验证?

Didit 针对该会话的挑战检查身份验证签名,根据受信任的颁发者验证证书,并检查其撤销状态。返回的身份必须与请求中使用的个人代码和国家/地区匹配。托管流程还会验证其会话令牌并拒绝重复的完成尝试。

这些检查将签名响应与预期的用户和请求关联起来。它们不能替代用户比较代码和保护其设备的需要。请在会话结果中读取验证方法、电子钱包提供商和签名属性,并在您的应用程序中使用结果之前验证 webhook 签名。请参阅技术指南。

如果用户没有钱包、取消或登录失败,会发生什么?

一个开关处理所有三种情况:无钱包、已取消或登录失败。它会回退到文档捕获或拒绝会话,您可以按国家/地区设置。

结果会记录回退方法和原因,因此被放弃的钱包登录不会被忽视。

Didit 支持哪些国家/地区的 Smart-ID 和 Mobile-ID?

Smart-ID 适用于爱沙尼亚、拉脱维亚、立陶宛和比利时。Mobile-ID 适用于爱沙尼亚和立陶宛。拉脱维亚不支持 Mobile-ID。用户需要为其选择的钱包提供符合条件的凭证。

在您的工作流程中为相应国家/地区启用每个钱包。阅读 Smart-ID 和 Mobile-ID 指南以了解身份验证步骤、已验证的身份字段和文档回退。

我的客户数据存储在哪里,如何受到保护?

在您选择的区域内,数据在传输和静态时均已加密,并符合 SOC 2 Type 1 和 Type 2、ISO 27001 和 GDPR 标准。

钱包仅共享请求所需的属性,您可以取消勾选任何可选属性,使其完全不被存储。必需属性始终存储,以及审计员所需的签名断言引用。

完整详情请参见 /security-compliance。

Didit 是否符合我所在行业的规定?

Didit 已在受监管行业(金融科技、银行、iGaming、加密货币、市场、医疗保健和政府)的 3,000 多家公司中投入生产。

钱包登录达到加密级别的保障,这是三种方法中最强的证据,并且每个会话都会记录保障级别。如果监管机构指定了特定的国家/地区 eID,接受该钱包通常是满足要求的最佳方式。

备忘录请参见 /security-compliance。

我能多快集成并开始验证用户?

几分钟,三种方式。

  • 无需代码 — 在控制台中构建工作流程,勾选您按国家/地区接受的钱包,然后向用户发送链接。
  • SDK 或重定向 — Web、iOS、Android、React Native 和 Flutter,或托管页面。
  • AI 代理 — 将此页面上的集成提示粘贴到 Claude Code、Cursor 或 Codex 中,让它连接所有内容,包括 webhook。

从 business.didit.me 开始,或阅读 docs.didit.me/integration/integration-prompt。

身份与欺诈基础设施。

一个 API 即可实现 KYC、KYB、交易监控和钱包筛选。5 分钟即可集成。

让 AI 总结此页面