Quickstart en 5 minutes
Créez un candidat, lancez un dossier, déposez les documents, envoyez l'invitation et récupérez le rapport.
- Créez une clé API depuis le dashboard (
Développeur → Clés API). - Créez un candidat (
POST /candidates). - Créez un dossier de vérification (
POST /verification-cases). - Envoyez l'invitation (
PATCH /verification-cases/:id/send-invitation). - Le candidat remplit son dossier → statut passe à
CANDIDATE_SUBMITTED. - CertiCV effectue les vérifications → statut passe à
REPORT_READY. - Recevez l'événement webhook
report.readyet récupérez le rapport.
# 1. Créer un candidat
curl -X POST "https://api.certicv.com/api/v1/candidates" \
-H "X-API-Key: ccv_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"firstName": "Alice",
"lastName": "Dubois",
"email": "alice.dubois@example.com",
"country": "FR",
"language": "fr"
}'
# 2. Créer un dossier de vérification
curl -X POST "https://api.certicv.com/api/v1/verification-cases" \
-H "X-API-Key: ccv_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"candidateId": "cand_01ABC",
"jobTitle": "Product Manager",
"sector": "tech",
"sensitivityLevel": 3,
"modules": [
{ "type": "IDENTITY" },
{ "type": "EDUCATION" },
{ "type": "EXPERIENCE" }
]
}'
# 3. Envoyer l'invitation au candidat
curl -X PATCH "https://api.certicv.com/api/v1/verification-cases/case_01DEF/send-invitation" \
-H "X-API-Key: ccv_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# 4. Récupérer le rapport une fois REPORT_READY
curl -X GET "https://api.certicv.com/api/v1/reports/report_01GHI/full" \
-H "X-API-Key: ccv_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"Authentification
Envoyez votre clé API dans le header X-API-Keysur chaque requête. La clé brute n'est affichée qu'une seule fois à la création — stockez-la immédiatement côté serveur. Ne l'exposez jamais dans le frontend ou dans du code versé dans Git.
curl -X GET "https://api.certicv.com/api/v1/integrations/test-auth" \ -H "X-API-Key: ccv_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Réponse attendue : { "authenticated": true, "organizationId": "org_...", "scopes": ["read:cases", "write:cases"] }
Cycle de vie d'un dossier
Un dossier de vérification passe par les statuts suivants. Utilisez le filtre ?status= pour interroger les dossiers à un stade précis.
DRAFT ↓ send-invitation INVITATION_SENT ↓ le candidat accède au portail CANDIDATE_STARTED ↓ le candidat soumet son dossier CANDIDATE_SUBMITTED ↓ traitement IA AI_ANALYSIS_DONE ↓ revue manuelle VERIFICATION_IN_PROGRESS ↓ rapport généré REPORT_READY ↓ archivage ARCHIVED
Candidats
Un candidat représente la personne vérifiée. Créez d'abord le candidat, puis rattachez-le à un dossier de vérification.
/candidatesCréer un candidat./candidatesLister les candidats./candidates/{id}Détail d'un candidat./candidates/{id}Mettre à jour un candidat.# Créer un candidat
curl -X POST "https://api.certicv.com/api/v1/candidates" \
-H "X-API-Key: ccv_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"firstName": "Alice",
"lastName": "Dubois",
"email": "alice.dubois@example.com",
"phone": "+33612345678",
"country": "FR",
"language": "fr",
"linkedinUrl": "https://linkedin.com/in/alicedubois"
}'
# Réponse
{
"id": "cand_01ABC",
"firstName": "Alice",
"lastName": "Dubois",
"email": "alice.dubois@example.com",
"country": "FR",
"language": "fr",
"createdAt": "2026-05-18T18:30:00.000Z"
}Dossiers de vérification
Un dossier regroupe les modules de vérification, les documents, les résultats et le rapport final. Filtrez les dossiers avec les paramètres search et status.
/verification-casesLister les dossiers (filtres: search, status, limit)./verification-casesCréer un dossier de vérification./verification-cases/{id}Détail d'un dossier./verification-cases/{id}/send-invitationEnvoyer l'invitation au candidat./verification-cases/{id}/archiveArchiver un dossier.# Créer un dossier
curl -X POST "https://api.certicv.com/api/v1/verification-cases" \
-H "X-API-Key: ccv_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"candidateId": "cand_01ABC",
"jobTitle": "Product Manager",
"sector": "tech",
"sensitivityLevel": 3,
"legalBasis": "LEGITIMATE_INTEREST",
"modules": [
{ "type": "IDENTITY" },
{ "type": "EDUCATION" },
{ "type": "EXPERIENCE" },
{ "type": "DOCUMENT_ANALYSIS" }
]
}'
# Réponse
{
"id": "case_01DEF",
"candidateId": "cand_01ABC",
"jobTitle": "Product Manager",
"status": "DRAFT",
"modules": [...],
"createdAt": "2026-05-18T18:35:00.000Z"
}Documents
Les documents sont envoyés en multipart/form-data. Formats acceptés : PDF, PNG, JPG, JPEG, DOC, DOCX. Limite : 10 Mo. Les fichiers sont chiffrés (AES-256-GCM) et scannés par antivirus avant stockage.
/documentsTéléverser un document (multipart/form-data, max 10 Mo)./documents/{id}/downloadTélécharger le fichier original.# Téléverser un document
curl -X POST "https://api.certicv.com/api/v1/documents" \
-H "X-API-Key: ccv_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-F "file=@/path/to/diplome.pdf" \
-F "candidateId=cand_01ABC" \
-F "caseId=case_01DEF" \
-F "type=DIPLOMA"
# Réponse
{
"id": "doc_01GHI",
"candidateId": "cand_01ABC",
"caseId": "case_01DEF",
"type": "DIPLOMA",
"fileName": "diplome.pdf",
"mimeType": "application/pdf",
"fileSize": 842120,
"isEncrypted": true,
"createdAt": "2026-05-18T18:45:00.000Z"
}Rapports
Le rapport expose le score global, les résultats par module, les incohérences détectées et la décision humaine. L'URL PDF expire après 15 minutes.
/reports/cases/{caseId}/generateGénérer le rapport final./reports/{id}/fullLire le rapport complet avec sections./reports/{id}/jsonExporter le rapport au format JSON./reports/{id}/pdfObtenir une URL présignée vers le PDF (expire 15 min)./reports/{id}/share-linkCréer un lien de partage sécurisé./reports/shared/{token}Accès public par token (sans clé API).# Récupérer le rapport complet
curl -X GET "https://api.certicv.com/api/v1/reports/report_01GHI/full" \
-H "X-API-Key: ccv_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# Réponse
{
"id": "report_01GHI",
"caseId": "case_01DEF",
"globalIndex": 87,
"identityScore": 100,
"educationScore": 80,
"experienceScore": 85,
"referencesScore": null,
"consistencyScore": 95,
"executiveSummary": "3 éléments confirmés sur 4 vérifiés. Indice global : 87/100.",
"publishedAt": "2026-05-18T19:00:00.000Z",
"sections": [
{
"title": "Vérification : EDUCATION — Master Management",
"status": "green",
"content": { "source": "OFFICIAL_SOURCE", "confidence": "high" }
}
]
}
# Obtenir l'URL du PDF (expire dans 15 min)
curl -X GET "https://api.certicv.com/api/v1/reports/report_01GHI/pdf" \
-H "X-API-Key: ccv_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# Réponse
{
"url": "https://s3.certicv.com/reports/report_01GHI.pdf?...",
"expiresIn": 900
}Webhooks & Signature HMAC
CertiCV envoie des événements asynchrones vers vos serveurs. Configurez vos endpoints depuis la page Webhooks du dashboard. Répondez avec un statut 2xxen moins de 5 secondes pour acquitter l'événement.
// Payload webhook
{
"id": "evt_abc123",
"event": "verification.completed",
"created": 1715012345,
"data": {
"caseId": "case_01DEF",
"status": "REPORT_READY",
"reportId": "report_01GHI",
"candidate": "Alice Dubois"
}
}Chaque webhook contient le header X-CertiCV-Signature au format t=timestamp,v1=signature. La signature est un HMAC-SHA256 de timestamp.bodyBrut, calculé avec votre secret webhook.
import crypto from "crypto";
export function verifyCertiCVWebhook(
rawBody: string,
header: string,
secret: string,
toleranceSeconds = 300 // rejeter les events vieux de +5 min
): boolean {
if (!header) return false;
const parts = Object.fromEntries(
header.split(",").map((part) => {
const [k, v] = part.split("=");
return [k, v];
})
);
const timestamp = Number(parts.t);
const signature = parts.v1;
if (!timestamp || !signature) return false;
// Vérifier la fraîcheur du timestamp
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - timestamp) > toleranceSeconds) return false;
const expected = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature, "hex"),
Buffer.from(expected, "hex")
);
}Erreurs & Rate limits
Toutes les erreurs retournent un statut HTTP explicite et un corps JSON. Limite par défaut : 60 requêtes par minute par organisation.
{
"statusCode": 400,
"message": ["email must be an email", "firstName must be a string"],
"error": "Bad Request"
}Enums
Valeurs acceptées pour les champs typés.
VerificationModuleType
IDENTITY — Vérification d'identité EDUCATION — Diplômes et formations EXPERIENCE — Expériences professionnelles REFERENCES — Vérification de références (plan Pro+) DOCUMENT_ANALYSIS — Analyse des documents fournis CRIMINAL_RECORD — Casier judiciaire (plan Business+) PROFESSIONAL_LICENSE — Licences et certifications professionnelles
DocumentType
CV · DIPLOMA · TRANSCRIPT · CERTIFICATE · ATTESTATION ID_DOCUMENT · REFERENCE_LETTER · EMPLOYMENT_CERTIFICATE PAY_SLIP · PORTFOLIO · OTHER
LegalBasis
PRE_CONTRACTUAL_MEASURES — Mesures précontractuelles LEGITIMATE_INTEREST — Intérêt légitime LEGAL_OBLIGATION — Obligation légale EXPLICIT_CONSENT — Consentement explicite
Sécurité & RGPD
CertiCV est conçu pour traiter des données sensibles avec un haut niveau de sécurité. Les intégrateurs doivent s'assurer de disposer d'une base légale appropriée avant de transmettre des données candidat.
Checklist avant mise en production
- Utiliser une clé API live (pas de clé de test).
- Stocker la clé côté serveur uniquement.
- Limiter les scopes au strict nécessaire.
- Tester la création d'un candidat et d'un dossier.
- Tester l'upload de document et la génération de rapport.
- Configurer les webhooks et vérifier la signature HMAC.
- Gérer les erreurs 400, 401, 403, 404, 429 et 500.
- Vérifier la base légale RGPD pour chaque dossier.
- Prévoir une procédure de rotation des clés.