> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Webリダイレクト型KYC：ホスト型検証ページ

> Diditのホスト型検証ページへリダイレクトして本人確認を実施。クロスデバイスやコールバックURLに対応し、Webhookで全結果を受信できます。フルKYCは1件$0.33から、毎月$10の無料枠付き。



リダイレクト連携用プロンプト
        プロンプトをクリップボードにコピー



      
      

\<pre>

\`Integrate Didit identity verification into my web app using the redirect flow.

\## How It Works
1\. Backend creates a session via POST /v3/session/ → response includes "url"
2\. Frontend redirects user to that URL: window.location.href = url
3\. User completes verification on Didit's hosted page (https://verify.didit.me/...)
4\. Didit redirects user back to your callback URL with query params:
 ?verificationSessionId=<session_id>&status=<session status, for example Approved, Declined, In Review or Expired>
5\. Your backend receives the full, signed decision via webhook (status.updated)

\## Backend: Create Session
POST https://verification.didit.me/v3/session/
Headers: { "x-api-key": DIDIT_API_KEY, "Content-Type": "application/json" }
Body: {
"workflow_id": DIDIT_WORKFLOW_ID,
"callback": "https://myapp.com/verification-complete",
"callback_method": "both",      // "initiator" | "completer" | "both"
"vendor_data": "user-id-123"
}
201 response (all 10 fields, per OpenAPI):
\{
"session_id": "uuid",
"session_number": 43762,
"session_token": "3FaJ9wLqX2Mz",   // 12-char URL-safe token; valid until the session expires
"url": "https://verify.didit.me/session/3FaJ9wLqX2Mz",
"vendor_data": "user-id-123",
"metadata": null,
"status": "Not Started",
"workflow_id": "uuid",
"workflow_version": 3,
"callback": "https://myapp.com/verification-complete"
}
The field is named "url" — redirect the user there. Never build the URL from session_token
by hand (with "language" set, the URL gains a language segment: /es/session/...).

\## Frontend: Redirect User
window.location.href = session.url; // value of "url" from the API response

\## Callback Page: Handle Return
const params = new URLSearchParams(window.location.search);
const sessionId = params.get('verificationSessionId');
const status    = params.get('status'); // the session status, e.g. "Approved", "Declined", "In Review" or "Expired"
// IMPORTANT: Treat these query params as untrusted UI hints.
// Always confirm the final result on your backend via webhook OR by calling
// GET /v3/session/{session_id}/decision/

\## Callback Methods
\- "initiator": redirect only the device that started the flow
\- "completer": redirect the device that finished verification (e.g. mobile after QR hand-off)
\- "both": redirect whichever device is active (recommended for reliability)

\## Webhook: Receive Full Results
POST to your webhook URL with full decision data.
Verify HMAC-SHA256 signature with X-Signature-V2 header — see /integration/webhooks.

\## Rate Limits
600 session-create requests per minute per API key (falls back to bearer token, then client IP), plus a shared 300 write-requests/minute budget across all endpoints. HTTP 429 with Retry-After when exceeded.

\## Environment Variables
\- DIDIT_API_KEY — backend only (Didit Console > API & Webhooks)
\- DIDIT_WEBHOOK_SECRET — backend only (per-destination, Didit Console > API & Webhooks)
\- DIDIT_WORKFLOW_ID — backend only (Didit Console > Workflows)

\## Docs
\- Redirect flow: https://docs.didit.me/integration/web-sdks/web-redirect
\- Create Session: https://docs.didit.me/sessions-api/create-session
\- Retrieve Decision: https://docs.didit.me/sessions-api/retrieve-session
\- Webhooks: https://docs.didit.me/integration/webhooks`

\</pre>



      
      

貼り付け先

リダイレクト方式では、ユーザーをDiditがホストするページに移動させて認証を行い、完了後にコールバックURL経由でアプリに戻します。| 機能 | 説明 |
| - | - |
| セットアップ時間 | 5分 |
| バックエンドの要否 | ✅ 必要（セッション作成のため） |
| 自社ドメインでの完結 | ❌ 不可（verify.didit.meまたはホワイトラベルのカスタムドメインにリダイレクト） |
| クロスデバイス対応 | ✅ 対応 |
| ブラウザ互換性 | ✅ すべてのブラウザ |***## リダイレクトを使用する場合- **クロスデバイス認証**: デスクトップで開始し、モバイルで完了
- **最大限の互換性**: 古いブラウザを含むすべてのブラウザで動作
- **シンプルな連携**: iframeの設定が不要
- **カメラの問題**: iframeでのカメラアクセスに問題がある場合***## 実装### ステップ1: セッションを作成する（バックエンド）セッション作成のレスポンスには**`url`**という名前のフィールドが含まれます。この値をブラウザに渡してください。```javascript theme={null}
// Node.js / Express
app.post('/api/create-verification', async (req, res) => {
  const { userId } = req.body;

  const response = await fetch('https://verification.didit.me/v3/session/', {
    method: 'POST',
    headers: {
      'x-api-key': process.env.DIDIT_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      workflow_id: process.env.DIDIT_WORKFLOW_ID,
      vendor_data: userId,
      callback: 'https://yourapp.com/verification-complete',
      callback_method: 'both', // most reliable across desktop ↔ mobile handoffs
    }),
  });

  if (!response.ok) {
    return res.status(response.status).send(await response.text());
  }

  const session = await response.json();
  // 201 per OpenAPI: { session_id, session_number, session_token, url, vendor_data,
  //                    metadata, status, workflow_id, workflow_version, callback }
  res.json({ sessionId: session.session_id, verificationUrl: session.url });
});
```### ステップ2: ユーザーをリダイレクトする（フロントエンド）**HTML:**```html theme={null}
<button onclick="startVerification()">Verify Identity</button>

<script>
  async function startVerification() {
    const response = await fetch('/api/create-verification', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ userId: 'user-123' })
    });
    
    const { verificationUrl } = await response.json();
    window.location.href = verificationUrl;
  }
</script>
```**React:**```tsx theme={null}
function VerifyButton() {
  const [loading, setLoading] = useState(false);

  const startVerification = async () => {
    setLoading(true);
    
    const response = await fetch('/api/create-verification', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ userId: 'user-123' })
    });
    
    const { verificationUrl } = await response.json();
    window.location.assign(verificationUrl);
  };

  return (
    <button onClick={startVerification} disabled={loading}>
      {loading ? 'Loading...' : 'Verify Identity'}
    </button>
  );
}
```**Vue:**```vue theme={null}
<template>
  <button @click="startVerification" :disabled="loading">
    {{ loading ? 'Loading...' : 'Verify Identity' }}
  </button>
</template>

<script setup>
import { ref } from 'vue';

const loading = ref(false);

async function startVerification() {
  loading.value = true;
  
  const response = await fetch('/api/create-verification', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ userId: 'user-123' })
  });
  
  const { verificationUrl } = await response.json();
  window.location.href = verificationUrl;
}
</script>
```***## コールバックの処理認証が完了すると、Diditはクエリパラメーター付きでコールバックURLにリダイレクトします。```
https://yourapp.com/verification-complete?verificationSessionId=abc123&status=Approved
```| パラメーター | 説明 |
| - | - |
| `verificationSessionId` | セッションの一意な識別子 |
| `status` | セッションの現在のステータス（例: `Approved`、`Declined`、`In Review`、`Expired`）。[認証ステータス](https://docs.didit.me/ja/integration/verification-statuses.md)を参照してください |### Next.jsの例```tsx theme={null}
// pages/verification-complete.tsx
import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';

export default function VerificationComplete() {
  const router = useRouter();
  const { verificationSessionId, status } = router.query;
  const [message, setMessage] = useState('Processing...');

  useEffect(() => {
    if (!router.isReady) return;

    async function handleResult() {
      // Optionally verify the result with your backend
      await fetch('/api/verify-session', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ 
          sessionId: verificationSessionId, 
          status 
        })
      });

      // Redirect based on status
      switch (status) {
        case 'Approved':
          setMessage('Verification successful! Redirecting...');
          setTimeout(() => router.push('/dashboard'), 2000);
          break;
        case 'Declined':
          setMessage('Verification was not successful.');
          setTimeout(() => router.push('/verification-failed'), 2000);
          break;
        case 'In Review':
          setMessage('Your verification is under review.');
          setTimeout(() => router.push('/verification-pending'), 2000);
          break;
        default:
          setMessage('Unknown status. Please contact support.');
      }
    }

    handleResult();
  }, [router.isReady, verificationSessionId, status]);

  return (
    <div className="flex flex-col items-center justify-center min-h-screen">
      <div className="animate-spin w-8 h-8 border-4 border-blue-500 border-t-transparent rounded-full mb-4" />
      <p className="text-lg">{message}</p>
    </div>
  );
}
```### Express.jsの例```javascript theme={null}
// routes/verification.js
app.get('/verification-complete', async (req, res) => {
  const { verificationSessionId, status } = req.query;
  
  // Optionally verify with Didit API
  // const session = await diditApi.getSession(verificationSessionId);
  
  // Update your database
  await db.users.update({
    where: { verificationSessionId },
    data: { verificationStatus: status }
  });
  
  // Redirect based on status
  switch (status) {
    case 'Approved':
      res.redirect('/dashboard?verified=true');
      break;
    case 'Declined':
      res.redirect('/verification-failed');
      break;
    case 'In Review':
      res.redirect('/verification-pending');
      break;
    default:
      res.redirect('/error');
  }
});
```### Vue Routerの例```typescript theme={null}
// router/index.ts
{
  path: '/verification-complete',
  component: () => import('@/views/VerificationComplete.vue'),
  beforeEnter: async (to, from, next) => {
    const { verificationSessionId, status } = to.query;
    
    // Store result and redirect
    await store.dispatch('verification/handleResult', { 
      sessionId: verificationSessionId, 
      status 
    });
    
    if (status === 'Approved') {
      next('/dashboard');
    } else if (status === 'Declined') {
      next('/verification-failed');
    } else {
      next('/verification-pending');
    }
  }
}
```***## 新しいタブで開くユーザーが認証している間もアプリを開いたままにしておきたい場合は、次のようにします。```javascript theme={null}
// Open in new tab
window.open(verificationUrl, '_blank');

// Poll for completion or use webhooks
```> [!TIP]
>
> 新しいタブを使う場合は、[Webhook](https://docs.didit.me/ja/integration/webhooks.md)と組み合わせて認証の完了を把握してください。***## セキュリティのベストプラクティス### コールバックをサーバー側で検証するクエリパラメーターの`verificationSessionId`と`status`は、信頼できないUI用のヒントとして扱ってください。最終的な判定は必ずバックエンドで確認してください。[Webhook](https://docs.didit.me/ja/integration/webhooks.md)を処理する方法（推奨）か、APIで判定を再取得する方法があります。```javascript theme={null}
// Backend: re-fetch the canonical decision before granting access
app.get('/verification-complete', async (req, res) => {
  const { verificationSessionId } = req.query;

  const response = await fetch(
    `https://verification.didit.me/v3/session/${verificationSessionId}/decision/`,
    {
      headers: { 'x-api-key': process.env.DIDIT_API_KEY },
    }
  );

  if (!response.ok) {
    return res.status(response.status).send(await response.text());
  }

  const decision = await response.json();

  // decision.status uses the canonical enum:
  // Not Started | In Progress | Awaiting User | In Review | Approved |
  // Declined   | Resubmitted | Expired | Kyc Expired | Abandoned
  if (decision.status === 'Approved') {
    // Grant access. Per-feature reports are plural arrays:
    //   decision.id_verifications[], decision.face_matches[], decision.aml_screenings[], ...
  }

  res.redirect('/dashboard');
});
```### Webhookを使用する最も信頼性の高い連携を実現するには、[Webhook](https://docs.didit.me/ja/integration/webhooks.md)を使用して、ユーザーのブラウザの挙動に関係なく認証結果をバックエンドで直接受け取ってください。***## クロスデバイスフローリダイレクト方式は、クロスデバイス認証に標準で対応しています。1) ユーザーがデスクトップで「Verify」をクリックします
2) ユーザーが認証ページにリダイレクトされます
3) 必要に応じて、ユーザーはQRコードをスキャンしてモバイルで続行できます
4) 完了後、ユーザーはコールバックURLにリダイレクトされます。どのデバイスでリダイレクトされるかは`callback_method`（`initiator`、`completer`、または`both`）で制御します***## トラブルシューティング### コールバックを受信できない1) セッション作成時にコールバックURLが正しく設定されているか確認してください
2) コールバックURLがインターネットからアクセス可能であることを確認してください
3) URLに誤字やエンコードの問題がないか確認してください### ステータスが常に「Declined」になる1) Didit Consoleでワークフローの設定を確認してください
2) 使用しているテスト用の書類が有効であるか確認してください
3) APIでセッションの詳細を確認し、具体的な却下理由を確認してください### リダイレクトループが発生する1) コールバックハンドラーが認証ページにリダイレクトし直していないか確認してください
2) コールバックページのキャッシュに問題がないか確認してください
3) ブラウザのキャッシュをクリアして再試行してください***## サンプルリポジトリ> [card] [GitHubリポジトリ](https://github.com/didit-protocol/didit-full-demo)
>
> GitHubでソースコードとサンプルを確認できます


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.