Premiers pasDémarrage rapide

Démarrage rapide

Créez une clé d'API et soumettez votre première demande KYC en trois minutes.

C'est le chemin le plus rapide entre « j'ai un compte Certivant » et « une demande de vérification est en cours ». Si vous terminez cette page, vous disposez d'une intégration fonctionnelle de bout en bout.

Ce dont vous avez besoin

  • Une organisation Certivant (inscrivez-vous à l'URL de votre locataire : l'essai comprend des crédits gratuits).
  • Le rôle Propriétaire ou Administrateur dans cette organisation. Les membres ne peuvent pas créer de clés d'API.
  • Un moyen d'effectuer des requêtes HTTPS : curl, Postman ou le client HTTP de votre langage.

1 — Créer une clé d'API

Connectez-vous au tableau de bord et ouvrez votre organisation.
Accédez à KYC → Développeur dans la barre latérale de gauche.

Cliquez sur Nouvelle clé, donnez-lui un libellé, choisissez Production ou Test (par exemple un libellé tel que staging-server), puis sélectionnez les portées dont vous avez besoin :

  • kyc:read : lire les demandes, les documents et les signaux de fraude
  • kyc:write : créer des demandes, envoyer des documents
  • kyc:submit : soumettre une demande pour un traitement automatisé
  • kyc:manage : remplacer des décisions, supprimer des demandeurs (RGPD)
Cliquez sur Créer la clé API. La clé complète n'est affichée qu'une seule fois et commence par ck_live_ (ou ck_test_ si vous avez choisi l'environnement de test). Copiez-la maintenant : Certivant ne conserve qu'un haché, vous ne pourrez donc pas la récupérer plus tard. Si vous la perdez, révoquez la clé et créez-en une nouvelle.

Traitez les clés d'API comme des mots de passe. Conservez-les dans votre gestionnaire de secrets, ne les versionnez jamais dans git, et utilisez une clé distincte par environnement (préproduction et production). Révoquez une clé dès que vous soupçonnez une exposition.

2 — Créer une demande KYC

La charge utile minimale n'a besoin que d'un type. Ajoutez les données du demandeur directement si vous les avez ; sinon, le demandeur les remplit via une session hébergée. Le même parcours de bout en bout (création → envoi des documents → soumission → interrogation) dans huit langages :

# 1. Create a verification request
curl -X POST https://app.certivant.com/api/v1/kyc/requests \
  -H "Authorization: Bearer ck_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "INDIVIDUAL",
    "externalRef": "user_123",
    "applicant": {
      "fullName": "Jane Doe", "email": "jane@example.com", "nationality": "US",
      "emailVerified": false, "phoneVerified": false
    }
  }'
# -> { "id": "req_...", "status": "PENDING_UPLOAD", ... }

# 2 & 3. Upload an identity document (front) + a selfie
curl -X POST https://app.certivant.com/api/v1/kyc/requests/{requestId}/documents \
  -H "Authorization: Bearer ck_live_your_key_here" \
  -F "file=@passport.jpg" -F "documentType=PASSPORT" -F "side=front"
curl -X POST https://app.certivant.com/api/v1/kyc/requests/{requestId}/documents \
  -H "Authorization: Bearer ck_live_your_key_here" \
  -F "file=@selfie.jpg" -F "documentType=SELFIE"

# 4. Submit for AI processing (email + phone must already be verified if your org requires it)
curl -X POST https://app.certivant.com/api/v1/kyc/requests/{requestId}/submit \
  -H "Authorization: Bearer ck_live_your_key_here"

# 5. Poll for the decision (or just listen for the webhook)
curl https://app.certivant.com/api/v1/kyc/requests/{requestId} \
  -H "Authorization: Bearer ck_live_your_key_here"
const BASE = "https://app.certivant.com/api/v1/kyc";
const headers = { Authorization: "Bearer ck_live_your_key_here" };

// 1. Create
const { id } = await fetch(BASE + "/requests", {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({
    type: "INDIVIDUAL",
    externalRef: "user_123",
    applicant: { fullName: "Jane Doe", email: "jane@example.com", nationality: "US" },
  }),
}).then((r) => r.json());

// 2 & 3. Upload documents
async function upload(file, documentType, side) {
  const form = new FormData();
  form.append("file", file);
  form.append("documentType", documentType);
  if (side) form.append("side", side);
  await fetch(BASE + "/requests/" + id + "/documents", { method: "POST", headers, body: form });
}
await upload(passportFile, "PASSPORT", "front");
await upload(selfieFile, "SELFIE");

// 4. Submit
await fetch(BASE + "/requests/" + id + "/submit", { method: "POST", headers });

// 5. Poll (production: listen for the webhook instead)
let result;
do {
  await new Promise((r) => setTimeout(r, 3000));
  result = await fetch(BASE + "/requests/" + id, { headers }).then((r) => r.json());
} while (result.status === "PROCESSING");
console.log(result.status, result.riskScore);
const BASE = "https://app.certivant.com/api/v1/kyc";
const headers = { Authorization: "Bearer ck_live_your_key_here" };

type KycStatus = "PENDING_UPLOAD" | "DOCUMENTS_READY" | "PROCESSING"
  | "APPROVED" | "REJECTED" | "ESCALATED" | "CANCELLED";

interface KycRequest {
  id: string;
  status: KycStatus;
  riskScore?: { overallScore: number; decision: string } | null;
}

const created: KycRequest = await fetch(BASE + "/requests", {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({
    type: "INDIVIDUAL",
    externalRef: "user_123",
    applicant: { fullName: "Jane Doe", email: "jane@example.com", nationality: "US" },
  }),
}).then((r) => r.json());

await fetch(BASE + "/requests/" + created.id + "/submit", { method: "POST", headers });
import time, requests

BASE = "https://app.certivant.com/api/v1/kyc"
headers = {"Authorization": "Bearer ck_live_your_key_here"}

# 1. Create
r = requests.post(f"{BASE}/requests", headers=headers, json={
    "type": "INDIVIDUAL",
    "externalRef": "user_123",
    "applicant": {"fullName": "Jane Doe", "email": "jane@example.com", "nationality": "US"},
})
request_id = r.json()["id"]

# 2 & 3. Upload documents
def upload(path, document_type, side=None):
    data = {"documentType": document_type}
    if side:
        data["side"] = side
    with open(path, "rb") as f:
        requests.post(f"{BASE}/requests/{request_id}/documents",
                      headers=headers, files={"file": f}, data=data)

upload("passport.jpg", "PASSPORT", "front")
upload("selfie.jpg", "SELFIE")

# 4. Submit
requests.post(f"{BASE}/requests/{request_id}/submit", headers=headers)

# 5. Poll
while True:
    result = requests.get(f"{BASE}/requests/{request_id}", headers=headers).json()
    if result["status"] != "PROCESSING":
        break
    time.sleep(3)
print(result["status"])
<?php
$BASE = "https://app.certivant.com/api/v1/kyc";
$auth = ["Authorization: Bearer ck_live_your_key_here"];

// 1. Create
$ch = curl_init("$BASE/requests");
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_HTTPHEADER => array_merge($auth, ["Content-Type: application/json"]),
  CURLOPT_POSTFIELDS => json_encode([
    "type" => "INDIVIDUAL",
    "externalRef" => "user_123",
    "applicant" => ["fullName" => "Jane Doe", "email" => "jane@example.com", "nationality" => "US"],
  ]),
]);
$req = json_decode(curl_exec($ch), true);
$id = $req["id"];

// 2. Upload a document
$ch = curl_init("$BASE/requests/$id/documents");
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST => true,
  CURLOPT_HTTPHEADER => $auth,
  CURLOPT_POSTFIELDS => [
    "file" => new CURLFile("passport.jpg"),
    "documentType" => "PASSPORT",
    "side" => "front",
  ],
]);
curl_exec($ch);

// 4. Submit
$ch = curl_init("$BASE/requests/$id/submit");
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => $auth]);
curl_exec($ch);
using System.Net.Http;
using System.Net.Http.Json;
using System.Net.Http.Headers;

var http = new HttpClient { BaseAddress = new Uri("https://app.certivant.com/api/v1/kyc/") };
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "ck_live_your_key_here");

// 1. Create
var created = await http.PostAsJsonAsync("requests", new {
    type = "INDIVIDUAL",
    externalRef = "user_123",
    applicant = new { fullName = "Jane Doe", email = "jane@example.com", nationality = "US" }
});
var request = await created.Content.ReadFromJsonAsync<Dictionary<string, object>>();
var id = request["id"].ToString();

// 2. Upload a document
using var form = new MultipartFormDataContent();
form.Add(new ByteArrayContent(File.ReadAllBytes("passport.jpg")), "file", "passport.jpg");
form.Add(new StringContent("PASSPORT"), "documentType");
form.Add(new StringContent("front"), "side");
await http.PostAsync($"requests/{id}/documents", form);

// 4. Submit
await http.PostAsync($"requests/{id}/submit", null);
import java.net.http.*;
import java.net.URI;

var http = HttpClient.newHttpClient();
String BASE = "https://app.certivant.com/api/v1/kyc";
String auth = "Bearer ck_live_your_key_here";

// 1. Create
var createBody = """
  {"type":"INDIVIDUAL","externalRef":"user_123",
   "applicant":{"fullName":"Jane Doe","email":"jane@example.com","nationality":"US"}}""";
var created = http.send(HttpRequest.newBuilder(URI.create(BASE + "/requests"))
    .header("Authorization", auth).header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(createBody)).build(),
    HttpResponse.BodyHandlers.ofString());
// parse created.body() -> id with your JSON library (Jackson/Gson)

// 4. Submit
http.send(HttpRequest.newBuilder(URI.create(BASE + "/requests/" + id + "/submit"))
    .header("Authorization", auth).POST(HttpRequest.BodyPublishers.noBody()).build(),
    HttpResponse.BodyHandlers.ofString());
package main

import (
	"bytes"
	"net/http"
)

const base = "https://app.certivant.com/api/v1/kyc"
const auth = "Bearer ck_live_your_key_here"

func main() {
	// 1. Create
	body := []byte(`{"type":"INDIVIDUAL","externalRef":"user_123",
		"applicant":{"fullName":"Jane Doe","email":"jane@example.com","nationality":"US"}}`)
	req, _ := http.NewRequest("POST", base+"/requests", bytes.NewReader(body))
	req.Header.Set("Authorization", auth)
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
	// decode resp.Body -> { "id": "..." }

	// 4. Submit
	submit, _ := http.NewRequest("POST", base+"/requests/"+id+"/submit", nil)
	submit.Header.Set("Authorization", auth)
	http.DefaultClient.Do(submit)
}

Une réponse réussie ressemble à ceci :

{
  "id": "req_01HXY...",
  "status": "PENDING_UPLOAD",
  "type": "INDIVIDUAL",
  "externalRef": "order-12345",
  "pendingDocTypes": ["GOVERNMENT_ID", "SELFIE"],
  "applicant": { "fullName": "Jane Doe", "email": "jane@example.com" },
  "createdAt": "2026-05-27T10:00:00.000Z"
}

Conservez l'id : chaque appel suivant en a besoin.

Le champ externalRef est votre clé étrangère. Utilisez votre identifiant de commande, votre identifiant utilisateur, tout ce qui vous permet de relier la demande Certivant à une ligne de votre propre base de données. Il est renvoyé dans chaque événement webhook.

3 — Donner au demandeur une session hébergée

La façon la plus simple de recueillir les documents est d'envoyer au demandeur une URL à courte durée de vie. Certivant gère la capture des documents, la vérification de la vivacité et l'interface d'envoi ; il vous suffit de lui transmettre le lien.

curl -X POST https://app.certivant.com/api/v1/kyc/requests/req_01HXY.../session-url \
  -H "Authorization: Bearer ck_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "expiresInHours": 72,
    "redirectUrl": "https://yourapp.example.com/onboarding/complete"
  }'

Retourne :

{
  "sessionUrl": "https://app.certivant.com/s/01HZ...",
  "expiresAt": "2026-05-30T10:00:00.000Z"
}

Envoyez-la par courriel au demandeur, intégrez-la à votre propre parcours d'accueil ou ouvrez-la dans un iframe, selon ce qui convient à votre expérience utilisateur. Lorsque le demandeur soumet, Certivant fait passer la demande en PROCESSING, exécute les contrôles et déclenche le webhook.

Sur ce parcours par session hébergée, le demandeur complète aussi la vérification du courriel et du téléphone lorsque votre organisation l'exige ; vous n'avez donc pas besoin de transmettre vous-même emailVerified / phoneVerified. Sur le parcours serveur à serveur (voir Votre première requête), vérifiez chaque canal requis, ou définissez ces indicateurs lors de la création, avant d'appeler submit.

4 — Écouter le résultat

Configurez un point de terminaison webhook dans KYC → Paramètres → Webhooks avec une URL que vous contrôlez. Certivant enverra une requête POST à cette URL chaque fois que l'état de la demande change.

{
  "event": "kyc.request.approved",
  "requestId": "req_01HXY...",
  "organizationId": "org_01HW...",
  "externalRef": "order-12345",
  "status": "APPROVED",
  "timestamp": "2026-05-27T10:04:21.000Z",
  "data": { "score": 92, "decision": "approve" }
}

Utilisez l'externalRef pour retrouver la ligne dans votre base de données et poursuivre l'intégration. Consultez Webhooks pour la vérification des signatures, le comportement des nouvelles tentatives et le catalogue complet des événements.

Et ensuite