API partenaire v1 · Version préliminaire, pas encore en service

Correspondance : POST /v1/match

Version préliminaire, pas encore en service. Cette page décrit le contrat v1 proposé pour les partenaires (version 1.0.0-rc.1). Aucun point d’accès décrit ici n’est déployé, et aucune clé d’API ne peut encore être émise.

Envoyez jusqu’à 100 requêtes en un seul appel. Chaque requête revient avec son propre statut, l’heure de son interrogation, les registres consultés et les éventuelles correspondances situées à la bande minimale ou au-dessus.

Envoi d’une requête

La portée requise est match:read. Chaque appel est facturé à raison d’une unité de requête par requête du lot. Envoyez un Idempotency-Key pour chaque vérification afin qu’une nouvelle tentative renvoie la réponse enregistrée plutôt que d’entraîner une deuxième facturation.

curl

curl https://api.crownintelligence.net/v1/match \
  -H "X-Api-Key: $CI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: screen-2026-10-13-0001" \
  -d '{
    "queries": [
      {"query_ref": "case-7731:party-1", "entity_type": "Person",
       "name": "Aleksandr Petrov", "dob": "1971-05-02", "country": ["RU"]},
      {"query_ref": "case-7731:vessel-1", "entity_type": "Vessel",
       "name": "Sea Lark", "identifiers": {"imo": "9176187"}}
    ],
    "options": {"min_band": "POSSIBLE", "limit": 5, "collections": ["default", "sanctions"]}
  }'

Node

const res = await fetch("https://api.crownintelligence.net/v1/match", {
  method: "POST",
  headers: {
    "X-Api-Key": process.env.CI_API_KEY,
    "Content-Type": "application/json",
    "Idempotency-Key": "screen-2026-10-13-0001"   // reuse on retry, never on a new screening
  },
  body: JSON.stringify({
    queries: [
      { query_ref: "case-7731:party-1", entity_type: "Person",
        name: "Aleksandr Petrov", dob: "1971-05-02", country: ["RU"] }
    ],
    options: { min_band: "POSSIBLE", limit: 5 }
  })
});
if (!res.ok) throw new Error("HTTP " + res.status + " " + (await res.text()));
const { match_request_id, queries } = await res.json();

Champs de requête

Champs d’une requête de correspondance
ChampRègle
query_refObligatoire. De 1 à 64 caractères parmi A à Z, a à z, 0 à 9, point, trait de soulignement, deux-points et trait d’union. Unique au sein de la requête. Il s’agit de votre référence opaque. N’y inscrivez ni nom, ni date de naissance, ni numéro d’identité.
entity_typeObligatoire. L’une des valeurs suivantes : Person, Company, Organization, Vessel, Airplane, LegalEntity.
nameDe 2 à 300 caractères. Obligatoire, sauf si la requête ne contient que des identifiants.
aliasesFacultatif. Jusqu’à 10 noms.
dob ou dob_yearFacultatif : YYYY, YYYY-MM ou YYYY-MM-DD dans dob, ou une année seule dans dob_year. Pas les deux.
countryFacultatif. Jusqu’à 5 codes ISO 3166-1 alpha-2.
identifiersFacultatif. imo (7 chiffres), mmsi (9 chiffres), lei (ISO 17442), ou wallet_address avec chain et address.

Le schéma est fermé. Tout autre champ est refusé avec l’erreur 400 invalid_request. Un lot de plus de 100 requêtes renvoie l’erreur 413 batch_too_large.

Options

  • min_band : STRONG, POSSIBLE ou WEAK. La valeur par défaut est POSSIBLE. Voir les bandes dans l’aperçu.
  • collections : de un à cinq éléments parmi default, sanctions, peps, crime et maritime.
  • limit : nombre de correspondances par requête, de 1 à 25. La valeur par défaut est 5.
  • include_features : indique si chaque correspondance énumère les caractéristiques qui ont fait varier son score. La valeur par défaut est true.
  • algorithm : standard ou name-only, selon la liste de la page des algorithmes.

Statuts

Chaque requête a exactement un statut. Lisez d’abord les statuts dans l’aperçu : seul no_hit_searched signifie qu’aucune correspondance n’a été trouvée, et une requête n’est jamais sans résultat tant qu’elle est not_searched ou error.

Statuts, correspondances et champs propres à chaque statut
StatutCorrespondancesChamps toujours présents
hitUne ou plusieursregisters_searched
no_hit_searchedAucuneregisters_searched, avec au moins un registre
not_searchedAucunenot_searched_reason
errorAucuneerror, avec un code et un message bilingue

Certains identifiants sont acceptés dès maintenant, mais ne sont pas interrogés tant que leur registre n’est pas chargé : lei et wallet_address. Une requête qui ne contient que ces identifiants et aucun nom renvoie not_searched, et la réponse les énumère dans identifiers_not_searched. Un nom interrogé dans des registres qui ne couvrent pas son entity_type renvoie not_searched avec le motif no_register_for_entity_type.

Réponse

La réponse énumère un résultat par requête, dans l’ordre d’envoi, ainsi qu’un match_request_id. Utilisez cet identifiant pour ouvrir un dossier et pour retrouver la requête dans vos journaux.

{
  "match_request_id": "mrq_01J9Z3K4M6",
  "queries": [
    {
      "query_ref": "case-7731:party-1",
      "status": "hit",
      "searched_at": "2026-10-13T14:02:11Z",
      "registers_searched": [
        {"list_id": "crown-list-0412", "register_name": "EU Consolidated Financial Sanctions",
         "publisher": "European Union", "list_date": "2026-10-09", "loaded_at": "2026-10-12T22:40:00Z",
         "licence": "PERMITTED"}
      ],
      "matches": [
        {"record_id": "crown-88213", "list_id": "crown-list-0412", "band": "STRONG", "score": 0.94,
         "schema": "Person", "caption": "Aleksandr Petrov", "matched_name": "Aleksandr Petrov",
         "features": [
           {"field": "dob", "effect": "+0.10", "rule": "birth date match",
            "explanation": {"en": "Birth date matches.", "fr": "La date de naissance correspond."}}
         ],
         "record_url": "https://crownintelligence.net/records/crown-88213"}
      ]
    },
    {
      "query_ref": "case-7731:wallet-1",
      "status": "not_searched",
      "searched_at": "2026-10-13T14:02:11Z",
      "not_searched_reason": "identifier_not_covered",
      "identifiers_not_searched": ["wallet_address"],
      "registers_searched": [],
      "matches": []
    }
  ]
}

Chaque correspondance comporte record_id, list_id, band, score (0 à 1), schema, caption, matched_name, features et record_url. Chaque caractéristique explique une variation du score, avec field, effect, rule et un explanation bilingue. La liste des règles peut s’allonger sans changement de version; ne la codez donc pas en dur.

Chaque entrée de registers_searched indique list_id, register_name, publisher, list_date (la date propre à l’éditeur, ou null), loaded_at (le moment du dernier chargement du registre par Crown Intelligence) et licence. Évaluez la fraîcheur selon loaded_at.

Traitement de chaque statut

Le modèle ci-dessous dirige chaque statut vers un chemin différent. Seul no_hit_searched mène à un résultat « sans correspondance ».

// Only no_hit_searched can ever be a negative. Everything else needs a person or a retry.
function outcome(q) {
  switch (q.status) {
    case "hit":
      return { action: "review", matches: q.matches };
    case "no_hit_searched":
      return { action: "no match", registers: q.registers_searched.map(r => r.register_name), searchedAt: q.searched_at };
    case "not_searched":
      return { action: "not checked", reason: q.not_searched_reason };   // never clear
    case "error":
      return { action: "retry", code: q.error.code };                    // never clear
    default:
      throw new Error("unknown status: " + q.status);
  }
}

Confirmez toujours une correspondance auprès de la publication officielle avant d’agir. Une correspondance appelle un examen; elle ne constitue pas une conclusion.

Ce qui est conservé

Les corps de requête ne sont pas journalisés. Pour chaque requête, Crown Intelligence conserve une empreinte à clé du nom normalisé, de la date de naissance et des codes de pays, sous une clé propre à votre compte. Le nom et la date de naissance ne sont pas conservés. Conservez dans votre propre système le lien entre votre sujet et query_ref. Les durées de conservation demeurent à préciser par le responsable.

Les exemples utilisent des noms, des références et des identifiants de fiche fictifs.