SOLUTIONIAVerify

Documentation

API SOLUTIONIA Verify

Une API REST simple. Trois appels suffisent pour verifier l'identite d'un utilisateur mauritanien : creer la session, rediriger, recevoir le verdict signe.

Base URLhttps://verify.solutionia.work

1. Demarrage rapide

Trois etapes pour integrer SOLUTIONIA Verify a votre application :

  1. Depuis votre backend, appelez POST /v1/sessions avec votre cle API.
  2. Redirigez votre utilisateur vers l'URL hebergee renvoyee (url_hebergee).
  3. Recevez le verdict via un webhook signe HMAC-SHA256 sur l'URL configuree pour votre tenant.

2. Authentification

Les appels serveur utilisent une cle API portee par l'en-tete Authorization: Bearer sk_live_.... Deux environnements :

  • Test — sk_test_... : sessions bidons pour developper sans facturation.
  • Live — sk_live_... : verifications reelles biometriques AWS, facturees.

Ne jamais exposer la cle en front. Toujours l'utiliser depuis un backend.

3. Creer une session

Depuis votre backend :

curl -X POST https://verify.solutionia.work/v1/sessions \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "loa": "substantial",
    "langue": "fr",
    "documents_autorises": ["cni_mr", "passport_mr", "residence_permit"],
    "reference_externe": "user-12345",
    "redirect_url_ok": "https://mon-app.mr/kyc/succes",
    "redirect_url_ko": "https://mon-app.mr/kyc/echec",
    "webhook_url_override": "https://mon-app.mr/api/verify/webhook"
  }'

Reponse :

{
  "id": "a656c963-bee5-4155-8ea3-8b336156aec2",
  "url_hebergee": "https://verify.solutionia.work/s/a656c963-.../?t=eyJ...",
  "token_client": "eyJhbGciOi...",
  "expire_le": "2026-08-09T13:45:00Z",
  "statut": "created"
}
ChampTypeDescription
loabasic | substantial | highNiveau d'assurance.
languefr | arLangue du parcours.
documents_autorisesstring[]Sous-ensemble de cni_mr, passport_mr, residence_permit.
reference_externestring?Votre propre id utilisateur ou transaction. Renvoye dans le webhook.
redirect_url_okurl?Redirection apres approbation.
redirect_url_kourl?Redirection apres rejet.
webhook_url_overrideurl?Ecrase l'URL webhook du tenant pour cette session.
metaobject?Metadonnees libres associees a la session.

4. Rediriger l'utilisateur

L'URL renvoyee (url_hebergee) contient un JWT de 15 minutes. Redirigez l'utilisateur vers cette URL — le parcours (capture doc, liveness) s'execute chez nous, aucune installation d'app.

Exemple en Node.js :

import { createVerifySession } from '@/lib/verify'

const session = await createVerifySession({
  reference_externe: user.id,
  redirect_url_ok: `${SITE}/kyc/succes`,
  redirect_url_ko: `${SITE}/kyc/echec`,
})

return res.redirect(session.url_hebergee)

Apres decision, l'utilisateur est renvoye vers votre redirect_url_ok ou redirect_url_ko.

5. Recevoir le webhook

Des que la decision est prise, nous envoyons un POST HTTP a l'URL webhook de votre tenant. Signature HMAC-SHA256 dans l'en-tete X-Signature: t=<epoch>,v1=<hmac>. Retry automatique 3 fois (1s, 3s, 9s) si le tenant ne repond pas 2xx.

Corps typique :

{
  "event": "session.decided",
  "session_id": "a656c963-bee5-4155-8ea3-8b336156aec2",
  "tenant_id": "33ddd3a0-e464-4f63-b18a-c28bb02ee546",
  "reference_externe": "user-12345",
  "verdict": "approved",
  "motifs": [],
  "score_global": 0.93,
  "extraction": {
    "document_type": "PASSPORT",
    "issuing_country": "MRT",
    "last_name": "AHMED",
    "given_names": "MOHAMED ABDALLAHI",
    "document_number": "B02263198",
    "nni": "1234567890",
    "date_of_birth": "1988-06-12",
    "date_of_expiry": "2029-06-11",
    "sex": "M",
    "confidence": 0.92
  },
  "face_match": {
    "same_person": true,
    "similarity_pct": 99.9,
    "reasoning": "match_99.9"
  },
  "liveness": { "passed": true, "confidence": 85.2 },
  "decide_le": "2026-08-09T12:30:20Z"
}

6. Verifier la signature HMAC

Node.js :

import { createHmac, timingSafeEqual } from 'crypto'

function verifyWebhook(rawBody, signatureHeader, secret) {
  const parts = Object.fromEntries(
    signatureHeader.split(',').map(p => {
      const i = p.indexOf('=')
      return [p.slice(0, i), p.slice(i + 1)]
    })
  )
  const t = parts.t, v1 = parts.v1
  if (!t || !v1) return false

  // Rejet des webhooks vieux de plus de 5 min (anti-replay)
  if (Math.floor(Date.now() / 1000) - parseInt(t, 10) > 300) return false

  const expected = createHmac('sha256', secret)
    .update(`${t}.${rawBody}`)
    .digest('hex')
  return timingSafeEqual(
    Buffer.from(v1, 'hex'),
    Buffer.from(expected, 'hex')
  )
}

Puis dans votre route :

export async function POST(req) {
  const rawBody = await req.text()
  const sig = req.headers.get('X-Signature')
  if (!verifyWebhook(rawBody, sig, process.env.VERIFY_WEBHOOK_SECRET)) {
    return Response.json({ error: 'invalid_signature' }, { status: 401 })
  }
  const payload = JSON.parse(rawBody)
  // ... traiter payload.verdict, payload.extraction, etc.
  return Response.json({ ok: true })
}

7. Lire une session en polling

Si vous preferez le polling au webhook :

curl https://verify.solutionia.work/v1/sessions/<session_id> \
  -H "Authorization: Bearer sk_live_..."

Statuts possibles :

  • created — session cree, en attente de l'utilisateur
  • in_progress — parcours en cours
  • approved — verifie
  • rejected — refuse (voir motifs)
  • requires_review — zone grise, revue humaine requise
  • expired — token expire (15 min)

8. Codes de rejet (motifs)

MotifSignification
no_nniNNI absent ou non conforme (pas 10 chiffres).
not_mauritanianDocument emis par un autre pays que la Mauritanie.
face_mismatch:XXFace-match Rekognition sous 90 % de similarite.
face_borderline:XXSimilarite 90-99 %, revue humaine recommandee.
liveness_failed:XXAWS Face Liveness sous le seuil de confiance.
no_documentAucun document n'a ete uploade.
no_biometricAucun selfie/liveness enregistre.
attempts_exceeded:stepTrop de tentatives sur une etape (5 doc, 3 liveness, 1 face-match).
extract_mockExtract simule (mode test sans cle Anthropic reelle).

Besoin d'aide a l'integration ?

Notre equipe technique vous accompagne en 1 a 2 jours pour brancher Verify a votre systeme.