> ## 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.

# KYC через редирект: размещённая страница верификации

> Верификация личности через редирект в Didit: кросс-девайс, callback URL, webhook-результаты. От $0.33 за KYC-проверку, $10 бесплатно в месяц.



Промпт для интеграции Redirect
        Скопировать промпт в буфер обмена



      
      

\<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>



      
      

Вставьте в

Метод Redirect отправляет пользователей на страницу верификации, размещённую Didit, а затем возвращает их в ваше приложение через URL обратного вызова.| Функция | Описание |
| - | - |
| Время настройки | 5 минут |
| Требуется бэкенд | ✅ Да (для создания сессий) |
| Остаётся на вашем домене | ❌ Нет (перенаправляет на verify.didit.me или на ваш пользовательский домен White label) |
| Поддержка нескольких устройств | ✅ Да |
| Совместимость с браузерами | ✅ Все браузеры |***## Когда использовать Redirect- **Верификация на нескольких устройствах**: начните на компьютере, завершите на телефоне
- **Максимальная совместимость**: работает во всех браузерах, включая старые версии
- **Простая интеграция**: не требуется настройка 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/ru/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/ru/integration/webhooks.md), чтобы узнавать, когда верификация завершена.***## Рекомендации по безопасности### Проверяйте обратный вызов на стороне сервераОтноситесь к параметрам запроса `verificationSessionId` и `status` как к ненадёжным подсказкам для интерфейса. Всегда подтверждайте итоговое решение на бэкенде: либо обрабатывая [webhook](https://docs.didit.me/ru/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/ru/integration/webhooks.md), чтобы получать результаты верификации напрямую на ваш бэкенд независимо от того, как ведёт себя браузер пользователя.***## Сценарий с несколькими устройствамиМетод redirect естественным образом поддерживает верификацию на нескольких устройствах:1) Пользователь нажимает «Верифицировать» на компьютере
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.