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

# Redirecció web KYC: pàgina de verificació allotjada

> Verificació d'identitat per redirecció amb Didit: multidispositiu, URLs de callback i webhooks. Des de $0.33 per KYC complet, $10 gratis/mes.



Prompt d'integració amb redirecció
        Copia el prompt al porta-retalls



      
      

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



      
      

Enganxa a

El mètode de redirecció envia els usuaris a una pàgina de verificació allotjada per Didit i, després, els torna a la teva aplicació mitjançant una URL de callback.| Funcionalitat | Descripció |
| - | - |
| Temps de configuració | 5 minuts |
| Cal backend | ✅ Sí (per crear sessions) |
| Es manté al teu domini | ❌ No (redirigeix a verify.didit.me o al teu domini personalitzat de marca blanca) |
| Suport entre dispositius | ✅ Sí |
| Compatibilitat amb navegadors | ✅ Tots els navegadors |***## Quan utilitzar la redirecció- **Verificació entre dispositius**: comença a l'ordinador i completa-la al mòbil
- **Compatibilitat màxima**: funciona en tots els navegadors, inclosos els més antics
- **Integració senzilla**: no cal configurar cap iframe
- **Problemes amb la càmera**: quan l'accés a la càmera des d'un iframe dóna problemes***## Implementació### Pas 1: crear una sessió (backend)La resposta de creació de la sessió conté un camp anomenat **`url`**. Envia aquest valor al navegador.```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 });
});
```### Pas 2: redirigir l'usuari (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>
```***## Gestió del callbackQuan acaba la verificació, Didit redirigeix a la teva URL de callback amb paràmetres de consulta:```
https://yourapp.com/verification-complete?verificationSessionId=abc123&status=Approved
```| Paràmetre | Descripció |
| - | - |
| `verificationSessionId` | Identificador únic de la sessió |
| `status` | L'estat actual de la sessió, per exemple `Approved`, `Declined`, `In Review` o `Expired`. Consulta [estats de verificació](https://docs.didit.me/ca/integration/verification-statuses.md) |### Exemple amb 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 amb 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 amb 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');
    }
  }
}
```***## Obrir en una pestanya novaSi prefereixes mantenir la teva aplicació oberta mentre l'usuari fa la verificació:```javascript theme={null}
// Open in new tab
window.open(verificationUrl, '_blank');

// Poll for completion or use webhooks
```> [!TIP]
>
> Quan utilitzis pestanyes noves, combina-ho amb [webhooks](https://docs.didit.me/ca/integration/webhooks.md) per saber quan acaba la verificació.***## Bones pràctiques de seguretat### Verifica el callback al servidorTracta els paràmetres de consulta `verificationSessionId` i `status` com a pistes d'interfície no fiables. Confirma sempre la decisió final al teu backend, ja sigui gestionant el [webhook](https://docs.didit.me/ca/integration/webhooks.md) (opció preferida), ja sigui tornant a obtenir la decisió a través de 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');
});
```### Utilitza webhooksPer a la integració més fiable, utilitza [webhooks](https://docs.didit.me/ca/integration/webhooks.md) per rebre els resultats de la verificació directament al teu backend, independentment del comportament del navegador de l'usuari.***## Flux entre dispositiusEl mètode de redirecció admet de manera natural la verificació entre dispositius:1) L'usuari fa clic a «Verifica» a l'ordinador
2) L'usuari és redirigit a la pàgina de verificació
3) Si cal, l'usuari pot escanejar el codi QR per continuar al mòbil
4) Quan acaba, l'usuari és redirigit a la teva URL de callback; el dispositiu des del qual es fa la redirecció ve determinat per `callback_method` (`initiator`, `completer` o `both`)***## Resolució de problemes### No es rep el callback1) Verifica que la URL de callback s'hagi definit correctament en crear la sessió
2) Assegura't que la teva URL de callback sigui accessible des d'internet
3) Comprova que la URL no tingui errors tipogràfics ni problemes de codificació### L'estat és sempre "Declined"1) Revisa la configuració del flux de treball a la Didit Console
2) Verifica que els documents de prova que fas servir siguin vàlids
3) Revisa els detalls de la sessió a través de l'API per consultar els motius concrets de rebuig### Bucle de redirecció1) Assegura't que el gestor de callback no redirigeixi de nou cap a la verificació
2) Comprova si hi ha problemes de memòria cau a la pàgina de callback
3) Esborra la memòria cau del navegador i torna-ho a provar***## Repositori d'exemples> [card] [Repositori de GitHub](https://github.com/didit-protocol/didit-full-demo)
>
> Consulta el codi font i els exemples a GitHub


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