Schémas et énumérations

Types TypeScript canoniques pour chaque schéma partagé de Certivant — statuts de demande, types de documents, types de contrôles, structure du score de risque, champs du demandeur et de l'entité KYB, enveloppe des webhooks, et pagination.

Cette page regroupe les énumérations et les structures partagées qui apparaissent dans plusieurs points de terminaison. Les schémas complets de chaque point de terminaison se trouvent dans la référence interactive, à l'adresse /api/docs.

Préfixes des identifiants

Tous les identifiants Certivant sont des chaînes préfixées (au format ULID après le préfixe). Le préfixe fait partie de l'identifiant : ne le supprimez pas.

PréfixeRessource
org_Organisation
req_Demande KYC / KYB
doc_Document
app_Demandeur
kyb_Fiche d'entité KYB
check_Contrôle de vérification
kyk_Clé d'API
whsec_Secret de signature du webhook

Ces identifiants sont stables à jamais : ils ne sont jamais recyclés et ne changent jamais après leur création.

Types de demandes

type RequestType = "INDIVIDUAL" | "BUSINESS";
  • INDIVIDUAL — KYC. Vérifie une personne physique.
  • BUSINESS — KYB. Vérifie une entreprise, ses administrateurs et ses bénéficiaires effectifs ultimes.

Statuts des demandes

type RequestStatus =
  | "PENDING_UPLOAD"  // Awaiting documents
  | "PROCESSING"      // Submitted, automated checks running
  | "APPROVED"        // Cleared. Done.
  | "REJECTED"        // Failed. May be resubmitted.
  | "ESCALATED"       // Borderline. Awaiting human decision.
  | "CANCELLED";      // Withdrawn before completion.

Le cycle de vie n'avance que dans un sens : une fois qu'une demande est APPROVED, REJECTED ou CANCELLED, elle ne revient pas en arrière. REJECTED peut être ramené à PENDING_UPLOAD via /resubmit, ce qui crée un nouveau parcours dans la même machine d'état, sur le même enregistrement.

Types de documents

type DocumentType =
  | "GOVERNMENT_ID"
  | "PASSPORT"
  | "SELFIE"
  | "PROOF_OF_ADDRESS"
  | "CERTIFICATE_OF_INCORPORATION"
  | "COMPANY_OWNERSHIP_STRUCTURE"
  | "BANK_STATEMENT"
  | "OTHER";

GOVERNMENT_ID est le seul type qui exige un paramètre side (front / back).

Statuts des documents

type DocumentStatus = "pending" | "verified" | "failed" | "corrupted";
  • pending — envoyé, pas encore traité (n'apparaît qu'avant la soumission de la demande parente).
  • verified — a passé les contrôles d'authenticité après la soumission.
  • failed — a échoué à au moins un contrôle. Les motifs figurent dans les enregistrements de contrôle associés.
  • corrupted — le fichier n'a pas pu être décodé. Envoyez-le à nouveau.

Types de contrôles

type CheckType =
  | "document_authenticity"
  | "ocr"
  | "face_match"
  | "liveness"
  | "sanctions_screening"
  | "pep_screening"
  | "adverse_media"
  | "proof_of_address"
  | "phone_verification"
  | "email_verification"
  | "registry_lookup";

type CheckResult = "pass" | "fail" | "review";

Une demande comporte en général 4 à 8 contrôles, selon l'ensemble de documents et les paramètres KYC de votre organisation.

Décisions

Le moteur de risque produit l'une des trois décisions suivantes, qui correspondent aux statuts de demande :

type RiskDecision = "approve" | "reject" | "escalate";
Décision du moteurStatut résultant
approveAPPROVED
rejectREJECTED
escalateESCALATED (en attente d'une révision humaine)

Score de risque

type RiskScore = {
  score: number;         // 0–100. Higher = lower risk
  decision: RiskDecision;
  factors: RiskFactor[];
  factorVerdicts?: { factor: string; verdict: "pass" | "fail" | "review" }[];
  disqualifiers?: string[];   // Hard blockers, e.g. "document_expired"
  reviewTriggers?: string[];  // Reasons for escalation
  reason?: string;       // Free-text summary for humans
};

type RiskFactor = {
  name: string;          // e.g. "face_match", "liveness"
  weight: number;        // 0–1, contribution to overall score
  score: number;         // 0–1, this factor's standalone score
};

Le score est donné à titre indicatif. C'est le champ decision qui déclenche réellement les transitions d'état ; les seuils de score d'approbation, d'escalade et de rejet sont configurables par organisation dans le tableau de bord, à KYC → Paramètres → Seuils.

Structure du demandeur

type Applicant = {
  externalRef?: string;
  fullName?: string;
  dateOfBirth?: string;     // ISO 8601 date (YYYY-MM-DD)
  nationality?: string;     // ISO 3166-1 alpha-2 (2 chars)
  email?: string;
  phone?: string;           // E.164 format with leading +
  emailVerified?: boolean;
  phoneVerified?: boolean;
  metadata?: Record<string, unknown>;
};

Tous les champs sont facultatifs à la création. Tout champ manquant peut être renseigné par le demandeur via une session hébergée, ou rester vide si les contrôles sous-jacents n'en ont pas besoin (par exemple, vous pouvez effectuer un criblage des seules sanctions avec fullName et dateOfBirth uniquement).

Structure de l'entité KYB

type KybEntity = {
  companyName: string;
  registrationNo?: string;
  countryOfIncorp?: string; // ISO 3166-1 alpha-2
  companyType?: string;     // "private_limited" | "llc" | "partnership" | "sole_trader" | …
  directors?: Director[];
  ubos?: Ubo[];
};

type Director = {
  fullName: string;
  dateOfBirth?: string;
  nationality?: string;
  appointedAt?: string;     // ISO 8601 date
};

type Ubo = {
  fullName: string;
  dateOfBirth?: string;
  nationality?: string;
  ownershipPercentage?: number;  // 0–100
};

Enveloppe du webhook

type WebhookPayload = {
  event: KycWebhookEventType;
  requestId: string;
  organizationId: string;
  externalRef?: string;
  subTenantName?: string;        // Partner mode: end-customer display name
  subTenantExternalId?: string;  // Partner mode: your end-customer id
  status: RequestStatus;
  timestamp: string;        // ISO 8601
  data?: Record<string, unknown>;  // Event-specific
};

type KycWebhookEventType =
  | "kyc.request.created"
  | "kyc.request.processing"
  | "kyc.request.approved"
  | "kyc.request.rejected"
  | "kyc.request.escalated"
  | "kyc.request.cancelled"
  | "kyc.document.uploaded"
  | "kyc.check.completed";

Voir Événements webhook pour la structure data propre à chaque événement.

Pagination

type PaginatedResponse<T> = {
  data: T[];
  pagination: {
    total: number;   // Total matching rows across all pages
    page: number;    // Current page, 1-indexed
    limit: number;   // Page size
    pages: number;   // Total page count
  };
};

Utilisez un limit allant jusqu'à 100 pour réduire le nombre d'allers-retours. La valeur par défaut est 20 si vous ne la précisez pas.

Codes de pays et de devise

  • Pays : ISO 3166-1 alpha-2 (US, GB, FR, JP). Les minuscules sont acceptées, mais sont normalisées en majuscules dans les réponses.
  • Numéros de téléphone : E.164 avec un + initial (+14155551234).
  • Dates : ISO 8601 (YYYY-MM-DD). Horodatages avec fuseau horaire (2026-05-27T10:00:00.000Z).
  • Devises : codes à trois lettres ISO 4217 (USD, EUR, GBP).

Pour aller plus loin

  • La référence interactive à l'adresse /api/v1/docs (également intégrée à la page Référence de l'API) présente chaque point de terminaison avec des constructeurs de requêtes en direct.
  • Le JSON brut OpenAPI 3.1 à l'adresse /api/v1/openapi.json — importez-le dans Postman, générez des clients, ou fournissez-le à l'outil de génération de code de votre choix.

Les deux sont publics : aucune connexion ni clé d'API n'est nécessaire, et ils ne décrivent que les points de terminaison /api/v1/kyc/** sur lesquels vous développez. Les schémas, portées et réponses d'erreur propres à chaque point de terminaison dans le document OpenAPI font foi ; cette page ne réunit que les structures qui se répètent d'un point de terminaison à l'autre.