didit-liveness-detection について
本人確認にパッシブなライブネス検出を組み込む開発者向けのスキルです。動画やユーザー操作を使わず、1 枚の顔画像で実在性を判定します。結果の保存と顔の登録により、後続の重複チェックにも利用できます。
主な機能
- 011 枚の画像によるパッシブなライブネス検出
- 02スコアによる拒否しきい値の設定
- 03顔のブロックリスト照合と重複チェック
- 04セッション保存と顔登録の任意設定
- 05応答での警告と判定ステータスの提示
活用シーン
- 01ユーザー登録時の自撮り画像の確認
- 02本人確認における提示攻撃の検出
- 03顔とブロックリストや過去の検査結果との照合
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ didit-protocol/ skills --skill didit-liveness-detectionインストール後、Claude Code で/didit-liveness-detectionを入力して読み込まれたか確認します。
同梱ファイルscripts/check_liveness.py
詳細
Didit Passive Liveness API
概要
1枚の撮影画像を分析して、ユーザーが実際にその場にいることを確認します。動画や動作、ユーザーによる操作は不要です。
主な制約:
- 使用可能なファイル拡張子:tiff、jpg、jpeg、png、webp(PDFは不可)
- 最大ファイルサイズ:5 MB(処理前に画像は約0.5 MBまで圧縮されるため、解像度を高くしても精度は向上しません)
- 顔が1つはっきりと見えること。複数の顔がある場合は最も大きな顔を評価し、
MULTIPLE_FACES_DETECTEDが追加されます - オリジナルのリアルタイム撮影画像であること(スクリーンショット、印刷物、画面を撮影した写真は不可)
料金: $0.05(成功した呼び出し1回あたり。単独の呼び出しには無料枠はありません)。これらの定価は2026年11月1日まで適用されます。同日、Diditの料金体系が変更され、月500回の無料チェックは月$10分の無料クレジットになります。最新の料金はdidit.me/pricingをご確認ください。
精度: ライブネス検知精度99.9%、誤受入率(FAR)0.1%未満。
判定: いずれかの error 警告が発生した場合(顔がない、スコアがしきい値以下、提示型攻撃、ブロックリストとの一致)、status は Declined になり、それ以外の場合は Approved になります。このエンドポイントには In Review はありません。設定可能なのはスコアのしきい値のみです。
ブロックリストと重複のスクリーニング: save_api_request=false の場合も含め、すべての呼び出しで実行されます。顔はアプリケーションの顔検索インデックス(顔ブロックリストと許可リスト、承認済みセッションの顔、ユーザープロフィールにアップロードされた顔、保持されている生体テンプレート)と照合されます。重複チェックでは、同じ vendor_data を持つ過去の顔はスキップされるため、同じユーザーを再検証しても DUPLICATED_FACE は発生しません。同じ vendor_data を持つ場合でも、ブロックリストに登録された顔は検出されます。顔の許可リストに一致すると、重複に関する警告は抑制されます。
保存と登録(save_api_request、デフォルトは true): 呼び出しはAPIセッションとして保存され(Business Console、GET /v3/session/{request_id}/decision/、status.updated webhook)、画像と顔の切り抜き画像が保存されます。また、顔は顔検索インデックスに登録され、以降のFace Search呼び出しや重複チェックで照合できるようになります。false の場合は何も保存されず、顔も登録されず、request_id を使った検索もできません。
サンドボックス: サンドボックスAPIキーは、リクエストの検証後に静的な Approved ペイロードを返します。データは保存されず、課金もされません。
ライブネス方式: このエンドポイントは常に PASSIVE(単一フレームCNN)を使用します。ホスト型ワークフローでは、face_liveness_method ワークフロー設定により、ACTIVE_3D(3D Action & Flash、最高レベルのセキュリティ)と FLASHING(3D Flash、高レベルのセキュリティ)も使用できます。
APIリファレンス: https://docs.didit.me/standalone-apis/passive-liveness 機能ガイド: https://docs.didit.me/core-technology/liveness/overview
認証
すべてのリクエストには x-api-key ヘッダーが必要です。Didit Business ConsoleのDevelopers > API keysからアプリケーションのAPIキーを使用するか、プログラムでアカウントとキーを作成してください(「Getting Started」を参照)。カスタムアクセス権を持つ名前付きキーで単独チェックを実行するには、Sessions の書き込み権限が必要です。一部のワークフローまたは承認済みセッションのみに制限されたキーでは実行できません。
はじめに(まだアカウントをお持ちでない場合)
Didit APIキーをお持ちでない場合は、2回のAPI呼び出しで作成できます。
- 登録:
POST https://apx.didit.me/auth/v2/programmatic/register/に{"email": "[email protected]", "password": "MyStr0ng!Pass"}を指定します - メールを確認して、6文字の確認コードを取得します
- 確認:
POST https://apx.didit.me/auth/v2/programmatic/verify-email/に{"email": "[email protected]", "code": "A3K9F2"}を指定します。キーはレスポンスのapplication.api_keyにあります。
クレジットを追加するには: 残高を確認するには GET /v3/billing/balance/ を実行し、Stripeのチェックアウトリンクを取得するには {"amount_in_dollars": 50} を指定して POST /v3/billing/top-up/ を実行します。
プラットフォーム管理(ワークフロー、セッション、ユーザー、請求)の詳細は、didit-verification-management スキルをご覧ください。
エンドポイント
POST https://verification.didit.me/v3/passive-liveness/
ヘッダー
| ヘッダー | 値 | 必須 |
|---|---|---|
x-api-key | API キー | はい |
Content-Type | multipart/form-data(HTTP クライアントによって設定) | はい |
リクエストパラメーター(multipart/form-data)
| パラメーター | 型 | 必須 | デフォルト | 制約 | 説明 |
|---|---|---|---|---|---|
user_image | ファイル | はい | - | tiff/jpg/jpeg/png/webp、最大 5 MB | 正面を向いた顔写真(セルフィー) |
face_liveness_score_decline_threshold | float | いいえ | 30 | 0-100 | スコアがこの値以下の場合、LOW_LIVENESS_SCORE が発生し、拒否されます。なりすまし対策をより厳格にするには、この値を上げてください |
rotate_image | boolean | いいえ | false | - | 90 度ずつ回転させて、顔検出の結果が最も良い向きを使用します。遅延が増加します |
save_api_request | boolean | いいえ | true | - | API セッションとして保存し、顔を登録します(概要を参照) |
vendor_data | string | いいえ | - | - | ユーザー識別子です。保存され、レスポンスに含めて返されます。また、重複チェックで同じユーザーの以前の顔をスキップするために使用されます |
metadata | JSON object | いいえ | - | multipart 内の JSON エンコードされた文字列 | セッションとともに保存され(保存時)、レスポンスに含めて返されます |
例
import json
import requests
with open("selfie.jpg", "rb") as f:
response = requests.post(
"https://verification.didit.me/v3/passive-liveness/",
headers={"x-api-key": "YOUR_API_KEY"},
files={"user_image": ("selfie.jpg", f, "image/jpeg")},
data={
"face_liveness_score_decline_threshold": "50",
"vendor_data": "user-123",
"metadata": json.dumps({"flow": "withdrawal"}),
},
timeout=60,
)
response.raise_for_status()
liveness = response.json()["liveness"]
print(liveness["status"], liveness["score"], [w["risk"] for w in liveness["warnings"]])
const formData = new FormData();
formData.append("user_image", selfieFile);
formData.append("face_liveness_score_decline_threshold", "50");
formData.append("vendor_data", "user-123");
formData.append("metadata", JSON.stringify({ flow: "withdrawal" }));
const response = await fetch("https://verification.didit.me/v3/passive-liveness/", {
method: "POST",
headers: { "x-api-key": "YOUR_API_KEY" },
body: formData,
});
const { liveness } = await response.json();
レスポンス(200 OK)
{
"request_id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
"liveness": {
"status": "Approved",
"method": "PASSIVE",
"score": 95.0,
"user_image": {
"entities": [
{"bbox": [661, 728, 1688, 2188], "confidence": 0.732973, "age": 26.91, "gender": "male"}
],
"best_angle": 0
},
"warnings": [],
"face_quality": 84.21,
"face_luminance": 50.33
},
"vendor_data": "user-123",
"metadata": {"flow": "withdrawal"},
"created_at": "2026-06-12T01:04:42.763237+00:00"
}
なりすましの顔やブロックリストに登録された顔でも、HTTP 200 が返されます。必ず liveness.status と liveness.warnings を確認してください。
ステータス値と対応方法
| ステータス | 意味 | 対応方法 |
|---|---|---|
"Approved" | error 警告が発生していません | 続行してください。ただし、warnings で DUPLICATED_FACE/POSSIBLE_DUPLICATED_FACE/MULTIPLE_FACES_DETECTED も確認してください |
"Declined" | 1 つ以上の error 警告が発生しました | warnings[].risk を確認してください。撮影時の問題であれば撮り直し、攻撃やブロックリスト該当であればブロックまたは確認してください |
エラーレスポンス
| コード | 意味 | 対応方法 |
|---|---|---|
400 | 無効なリクエスト | レスポンス本文でフィールドエラーを確認してください |
400 | {"error": "Invalid user image format."}:許可されている拡張子ですが、ファイルをデコードできません | 画像を再エンコード(JPEG または PNG)して再試行してください |
401 | API キーの有効期限が切れています | キーをローテーションするか、Developers > API keys で新しいキーを作成してください |
403 | API キーがない、誤っている、または取り消されている、このエンドポイントへのアクセス権がないスコープ付きキーが使われている、キーの IP 許可リスト外からのリクエスト、またはクレジット不足 | detail または error のメッセージを確認してください。x-api-key ヘッダーまたはキーのアクセス権を修正するか、クレジットを追加してください |
429 | レート制限:キーごとに 1 分あたり POST/PATCH/DELETE リクエストは 300 件、GET リクエストは 600 件 | Retry-After の秒数だけ待ってから再試行してください |
レスポンスフィールドのリファレンス
| フィールド | 型 | 説明 |
|---|---|---|
request_id | uuid | save_api_request=true の場合はセッション ID(GET /v3/session/{request_id}/decision/ で使用)。それ以外の場合は単発の相関 ID |
liveness.status | string | "Approved" または "Declined" |
liveness.method | string | 常に "PASSIVE" |
liveness.score | float または null | 0-100(小数点以下 2 桁)。値が高いほど、生きている人物である可能性が高いことを示します。モデルが信頼度を返さなかった場合は null です。null のスコアは、しきい値との比較では 0 として扱われます |
liveness.user_image.entities[] | array | 検出された顔ごとに 1 つのエントリー:bbox [x_min, y_min, x_max, y_max]、confidence(0-1)、age、gender。年齢と性別は参考情報であり、判定には影響しません |
liveness.user_image.best_angle | integer または null | 最良の検出結果が得られた回転角度(度)。rotate_image=true によって向きが補正された場合のみ 0 以外になります |
liveness.warnings[] | array | {risk, feature, additional_data, log_type, short_description, long_description}。feature は常に LIVENESS です |
liveness.face_quality | float または null | 顔の撮影品質(0-100)。信頼できる値がない場合は null です |
liveness.face_luminance | float または null | 顔の明るさ(0-100)。値を取得できない場合は null です |
vendor_data | string または null | 送信した値が返されます |
metadata | object または null | 送信した値が返されます |
created_at | string | レスポンスの ISO 8601 UTC 時刻 |
警告タグ
| タグ | 重大度 | 拒否 | 発生条件 |
|---|---|---|---|
NO_FACE_DETECTED | error | はい | ライブネスモデルが顔を検出できなかった場合 |
LOW_LIVENESS_SCORE | error | はい | score が face_liveness_score_decline_threshold 以下の場合。NO_FACE_DETECTED と同時には発生しません |
LIVENESS_FACE_ATTACK | error | はい | プレゼンテーション攻撃(印刷物、画面の再生、マスク、ディープフェイク)が検出された場合 |
FACE_IN_BLOCKLIST | error | はい | 顔のブロックリストに登録された顔と強く一致した場合。additional_data には blocklisted_session_id、blocklisted_session_number、api_service が含まれます |
POSSIBLE_FACE_IN_BLOCKLIST | error | はい | ブロックリストに登録された顔と弱く一致した場合。このエンドポイントでは拒否されます(ワークフローではレビューに回されます) |
MULTIPLE_FACES_DETECTED | warning | いいえ | 顔が複数検出された場合。最も大きい顔がスコア判定されます |
DUPLICATED_FACE | information | いいえ | 別の承認済みセッションの顔(またはインポートされた顔、保持されたテンプレート)と強く一致した場合。additional_data には duplicated_session_id、duplicated_session_number、api_service が含まれます |
POSSIBLE_DUPLICATED_FACE | information | いいえ | 同じ種類の一致が弱い場合 |
LOW_FACE_QUALITY、LOW_FACE_LUMINANCE、HIGH_FACE_LUMINANCEは、このエンドポイントでは決して発生しません(これらはワークフローの警告です)。必要に応じて、face_quality/face_luminanceに独自のルールを適用してください。- 判定は
statusとwarnings[].riskに基づいてください。上記の重大度はこのエンドポイントのルールです。各警告に含まれるlog_typeは参考情報として扱ってください。
よくあるワークフロー
基本的なライブネスチェック
1. Capture the user's selfie
2. POST /v3/passive-liveness/ with user_image and vendor_data=<your user id>
3. "Approved" -> the user is live, proceed
"Declined" -> check warnings[].risk:
NO_FACE_DETECTED / LOW_LIVENESS_SCORE -> ask for a retake: one well-lit, centered face
LIVENESS_FACE_ATTACK -> suspected spoof, do not approve
FACE_IN_BLOCKLIST / POSSIBLE_FACE_IN_BLOCKLIST -> block or send to manual review
4. "Approved" with DUPLICATED_FACE -> this face already passed under another vendor_data:
look up additional_data.duplicated_session_id before creating a new account
ライブネス+顔照合(組み合わせ)
1. POST /v3/passive-liveness/ -> verify the selfie is live
2. If Approved -> POST /v3/face-match/ with user_image=selfie, ref_image=ID portrait
3. Both Approved -> the live person matches the document photo
ブロックリスト/重複判定ではなく、類似する顔をすべて順位付きで取得したいですか?didit-face-search スキルを使用し、ここで同じ自撮り画像を保存する前に実行してください(保存されたライブネス顔自体も検索対象になります)。
ユーティリティスクリプト
export DIDIT_API_KEY="your_api_key"
python scripts/check_liveness.py selfie.jpg
python scripts/check_liveness.py selfie.jpg --threshold 50 --vendor-data user-123
python scripts/check_liveness.py selfie.jpg --rotate --no-save --metadata '{"flow": "withdrawal"}'