> ## 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-Redirect-KYC: Gehostete Verifizierungsseite

> Gehostete Identitätsverifizierung per Web-Redirect mit Didit: geräteübergreifend, Callback-URLs, Webhooks. Ab $0.33/KYC-Check, $10 gratis/Monat.



Prompt für die Redirect-Integration
        Prompt in die Zwischenablage kopieren



      
      

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



      
      

Einfügen in

Die Redirect-Methode leitet Benutzer für die Verifizierung auf eine von Didit gehostete Seite weiter und führt sie anschließend über eine Callback-URL zu Ihrer Anwendung zurück.| Funktion | Beschreibung |
| - | - |
| Einrichtungszeit | 5 Minuten |
| Backend erforderlich | ✅ Ja (zum Erstellen von Sitzungen) |
| Bleibt auf Ihrer Domain | ❌ Nein (leitet zu verify.didit.me oder Ihrer benutzerdefinierten White-Label-Domain weiter) |
| Geräteübergreifende Unterstützung | ✅ Ja |
| Browser-Kompatibilität | ✅ Alle Browser |***## Wann Sie den Redirect nutzen sollten- **Geräteübergreifende Verifizierung**: Auf dem Desktop beginnen, auf dem Smartphone abschließen
- **Maximale Kompatibilität**: Funktioniert in allen Browsern, auch in älteren Versionen
- **Einfache Integration**: Keine iframe-Konfiguration erforderlich
- **Kameraprobleme**: Wenn der Kamerazugriff im iframe problematisch ist***## Implementierung### Schritt 1: Sitzung erstellen (Backend)Die Antwort beim Erstellen der Sitzung enthält ein Feld namens **`url`** – übergeben Sie diesen Wert an den Browser.```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 });
});
```### Schritt 2: Benutzer weiterleiten (Frontend)**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>
```***## Callback verarbeitenSobald die Verifizierung abgeschlossen ist, leitet Didit mit Query-Parametern zu Ihrer Callback-URL weiter:```
https://yourapp.com/verification-complete?verificationSessionId=abc123&status=Approved
```| Parameter | Beschreibung |
| - | - |
| `verificationSessionId` | Eindeutige Sitzungskennung |
| `status` | Der aktuelle Status der Sitzung, zum Beispiel `Approved`, `Declined`, `In Review` oder `Expired`. Siehe [Verifizierungsstatus](https://docs.didit.me/de/integration/verification-statuses.md) |### Next.js-Beispiel```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-Beispiel```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-Beispiel```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');
    }
  }
}
```***## In neuem Tab öffnenWenn Sie Ihre Anwendung geöffnet lassen möchten, während sich der Benutzer verifiziert:```javascript theme={null}
// Open in new tab
window.open(verificationUrl, '_blank');

// Poll for completion or use webhooks
```> [!TIP]
>
> Wenn Sie neue Tabs verwenden, kombinieren Sie dies mit [Webhooks](https://docs.didit.me/de/integration/webhooks.md), um zu erfahren, wann die Verifizierung abgeschlossen ist.***## Best Practices für die Sicherheit### Callback serverseitig verifizierenBehandeln Sie die Query-Parameter `verificationSessionId` und `status` als nicht vertrauenswürdige UI-Hinweise. Bestätigen Sie die endgültige Entscheidung stets auf Ihrem Backend – entweder durch die Verarbeitung des [Webhooks](https://docs.didit.me/de/integration/webhooks.md) (bevorzugt) oder durch erneutes Abrufen der Entscheidung über die 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');
});
```### Webhooks verwendenVerwenden Sie für eine möglichst zuverlässige Integration [Webhooks](https://docs.didit.me/de/integration/webhooks.md), um Verifizierungsergebnisse direkt an Ihr Backend zu übermitteln – unabhängig davon, wie sich der Browser des Benutzers verhält.***## Geräteübergreifender AblaufDie Redirect-Methode unterstützt von Natur aus geräteübergreifende Verifizierungen:1) Der Benutzer klickt auf dem Desktop auf „Verifizieren“
2) Der Benutzer wird zur Verifizierungsseite weitergeleitet
3) Bei Bedarf kann der Benutzer einen QR-Code scannen, um auf dem Smartphone fortzufahren
4) Nach Abschluss wird der Benutzer zu Ihrer Callback-URL weitergeleitet – welches Gerät die Weiterleitung ausführt, wird über `callback_method` gesteuert (`initiator`, `completer` oder `both`)***## Fehlerbehebung### Callback nicht empfangen1) Prüfen Sie, ob die Callback-URL beim Erstellen der Sitzung korrekt festgelegt wurde
2) Stellen Sie sicher, dass Ihre Callback-URL über das Internet erreichbar ist
3) Überprüfen Sie, dass die URL keine Tippfehler oder Probleme bei der Zeichenkodierung aufweist### Status immer „Declined“1) Überprüfen Sie Ihre Workflow-Einstellungen in der Didit Console
2) Stellen Sie sicher, dass die von Ihnen verwendeten Testdokumente gültig sind
3) Prüfen Sie die Sitzungsdetails über die API auf spezifische Ablehnungsgründe### Weiterleitungsschleife1) Stellen Sie sicher, dass Ihr Callback-Handler nicht wieder zur Verifizierung weiterleitet
2) Prüfen Sie, ob Caching-Probleme auf Ihrer Callback-Seite vorliegen
3) Leeren Sie den Browser-Cache und versuchen Sie es erneut***## Beispiel-Repository> [card] [GitHub-Repository](https://github.com/didit-protocol/didit-full-demo)
>
> Quellcode und Beispiele auf GitHub ansehen


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