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

# Vérification KYC par redirection : page hébergée

> Vérification par redirection avec Didit : multi-appareils, URL de rappel, webhooks. Dès $0.33 par KYC complet, $10 offerts/mois.



Prompt d'intégration par redirection
        Copier le prompt dans le presse-papiers



      
      

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



      
      

Coller dans

La méthode par redirection envoie les utilisateurs vers une page de vérification hébergée par Didit, puis les renvoie vers votre application via une URL de rappel.| Fonctionnalité | Description |
| - | - |
| Temps de configuration | 5 minutes |
| Backend requis | ✅ Oui (pour créer des sessions) |
| Reste sur votre domaine | ❌ Non (redirige vers verify.didit.me ou vers votre domaine personnalisé en marque blanche) |
| Prise en charge multi-appareil | ✅ Oui |
| Compatibilité avec les navigateurs | ✅ Tous les navigateurs |***## Quand utiliser la redirection- **Vérification multi-appareil** : commencez sur ordinateur et terminez sur mobile
- **Compatibilité maximale** : fonctionne dans tous les navigateurs, y compris les plus anciens
- **Intégration simple** : aucune configuration d'iframe nécessaire
- **Problèmes de caméra** : lorsque l'accès à la caméra dans une iframe pose problème***## Implémentation### Étape 1 : créer une session (backend)La réponse de création de session contient un champ nommé **`url`** : transmettez cette valeur au navigateur.```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 });
});
```### Étape 2 : rediriger l'utilisateur (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>
```***## Gestion du callbackLorsque la vérification se termine, Didit redirige vers votre URL de rappel avec des paramètres de requête :```
https://yourapp.com/verification-complete?verificationSessionId=abc123&status=Approved
```| Paramètre | Description |
| - | - |
| `verificationSessionId` | Identifiant unique de la session |
| `status` | Le statut actuel de la session, par exemple `Approved`, `Declined`, `In Review` ou `Expired`. Voir [statuts de vérification](https://docs.didit.me/fr/integration/verification-statuses.md) |### Exemple 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>
  );
}
```### Exemple 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');
  }
});
```### Exemple 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');
    }
  }
}
```***## Ouvrir dans un nouvel ongletSi vous préférez garder votre application ouverte pendant que l'utilisateur effectue la vérification :```javascript theme={null}
// Open in new tab
window.open(verificationUrl, '_blank');

// Poll for completion or use webhooks
```> [!TIP]
>
> Lorsque vous utilisez de nouveaux onglets, combinez cette méthode avec les [webhooks](https://docs.didit.me/fr/integration/webhooks.md) pour savoir quand la vérification se termine.***## Bonnes pratiques de sécurité### Vérifier le callback côté serveurConsidérez les paramètres de requête `verificationSessionId` et `status` comme des indications d'interface non fiables. Confirmez toujours la décision finale sur votre backend, soit en traitant le [webhook](https://docs.didit.me/fr/integration/webhooks.md) (méthode recommandée), soit en récupérant à nouveau la décision via l'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');
});
```### Utiliser les webhooksPour une intégration plus fiable, utilisez les [webhooks](https://docs.didit.me/fr/integration/webhooks.md) afin de recevoir directement les résultats de vérification sur votre backend, quel que soit le comportement du navigateur de l'utilisateur.***## Flux multi-appareilLa méthode par redirection prend naturellement en charge la vérification multi-appareil :1) L'utilisateur clique sur « Vérifier » sur ordinateur
2) L'utilisateur est redirigé vers la page de vérification
3) Si nécessaire, l'utilisateur peut scanner un code QR pour continuer sur mobile
4) Une fois la vérification terminée, l'utilisateur est redirigé vers votre URL de rappel. L'appareil qui effectue la redirection est déterminé par `callback_method` (`initiator`, `completer` ou `both`)***## Dépannage### Le callback n'est pas reçu1) Vérifiez que l'URL de rappel est correctement définie lors de la création de la session
2) Assurez-vous que votre URL de rappel est accessible depuis Internet
3) Vérifiez que l'URL ne contient ni fautes de frappe ni problèmes d'encodage### Le statut est toujours « Declined »1) Vérifiez les paramètres de votre workflow dans la Didit Console
2) Vérifiez que les documents de test que vous utilisez sont valides
3) Consultez les détails de la session via l'API pour connaître les motifs de refus précis### Boucle de redirection1) Assurez-vous que votre gestionnaire de callback ne redirige pas vers la vérification
2) Vérifiez s'il existe des problèmes de cache sur votre page de callback
3) Videz le cache du navigateur et réessayez***## Dépôt d'exemples> [card] [Dépôt GitHub](https://github.com/didit-protocol/didit-full-demo)
>
> Consultez le code source et les exemples sur GitHub


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