Documentation · API de vérification

Liste de vérification d’intégration

Ce qu’il faut décider, construire et tester avant la mise en production de la vérification Crown Intelligence dans votre système : la collection, la correspondance des champs, le seuil de correspondance, la façon dont les correspondances possibles sont examinées et consignées, la mise à jour des fiches, ainsi que la gestion des limites et des erreurs par l’intégration.

L’API de vérification n’exige aucune clé pour l’instant et répond aux requêtes anonymes. Les contrôles ci-dessous utilisent les points d’accès décrits dans le guide de l’API de vérification et la référence de l’API. La vérification automatisée ou systématique, ainsi que l’utilisation dans un processus d’affaires, nécessitent une licence commerciale en vertu de nos conditions d’utilisation. Confirmez ce point avant de connecter un système en production.

Choisir une collection

Chaque collection constitue un parcours de correspondance distinct. Choisissez celle qui correspond aux listes visées par vos obligations. Un registre n’est pas une collection en soi; pour restreindre une recherche à un registre, utilisez include_dataset.

CollectionParcours de correspondanceContenu
default/api/match/defaultChaque fiche active : sanctions, PEPs, interdiction de contracter, mesures d’application de la loi et autres listes de risques.
sanctions/api/match/sanctionsInscriptions de sanctions uniquement.
peps/api/match/pepsPersonnes politiquement vulnérables (PPV).
crime/api/match/crimeInterdictions de contracter, mandats fiscaux et avis d’insolvabilité.
maritime/api/match/maritimeNavires et fiches comportant un numéro IMO.

Faire correspondre les champs du client à la requête de correspondance

Une requête de correspondance envoie jusqu’à 20 requêtes nommées dans un seul corps, chacune avec schema et properties. Utilisez votre propre ID de client ou de contrepartie comme clé de requête, afin que chaque réponse soit rattachée à votre fiche.

Votre champChamp de correspondanceRègles
Nom, ou chaque graphie que vous détenezproperties.nameTableau d’au plus 5 chaînes. Ajoutez une forme translittérée si vous en détenez une. Obligatoire, sauf si imoNumber ou mmsi est envoyé.
Date de naissanceproperties.birthDateYYYY, YYYY-MM ou YYYY-MM-DD. Envoyez la précision dont vous disposez; une année seule est valide.
Nationalité (personne)properties.nationalityCode ISO 3166 à deux lettres, par exemple ca ou ru.
Pays de constitution (entreprise)properties.countryCode à deux lettres. Le même champ accepte aussi le pavillon d’un navire.
Numéro IMO (navire)properties.imoNumberSept chiffres, par exemple 9418286.
MMSI (navire)properties.mmsiNeuf chiffres.
Type de partieschemaPerson, Company, Organization, LegalEntity ou Vessel. Une fiche d’un type différent fait baisser le score (type_mismatch). Envoyez le type que vous connaissez plutôt que LegalEntity par défaut.

Un point de départ qui fait correspondre une fiche client, envoie un lot avec reprises et affiche le meilleur résultat pour chaque partie.

import os, time, json, requests

BASE = os.environ.get("CROWN_API_BASE", "https://api.crownintelligence.net")
session = requests.Session()
session.headers["User-Agent"] = "my-screening-tool/1.0 ([email protected])"


def to_query(customer):
    """Map one customer record to a match query (see the field table above)."""
    props = {"name": customer["names"][:5]}
    if customer.get("birth_date"):
        props["birthDate"] = [customer["birth_date"]]        # YYYY, YYYY-MM or YYYY-MM-DD
    if customer.get("nationality"):
        props["nationality"] = [customer["nationality"]]     # ISO 3166-1 alpha-2, e.g. "ca"
    if customer.get("imo"):
        props["imoNumber"] = [customer["imo"]]               # seven digits
    return {"schema": customer["schema"], "properties": props}


def match(collection, queries, limit=5, threshold=0.75, changed_since=None, retries=3):
    """POST /api/match with retries for 429 (honour Retry-After) and 5xx (back off)."""
    params = {"limit": limit, "threshold": threshold}
    if changed_since:
        params["changed_since"] = changed_since
    for attempt in range(retries + 1):
        r = session.post(f"{BASE}/api/match/{collection}", params=params,
                         json={"queries": queries}, timeout=60)
        if r.status_code == 429 and attempt < retries:
            time.sleep(int(r.headers.get("Retry-After", "5")))
            continue
        if r.status_code >= 500 and attempt < retries:
            time.sleep(2 ** attempt)
            continue
        r.raise_for_status()
        return r.json()


customers = {
    "C-1001": {"schema": "Person", "names": ["Igor Putin", "Игорь Путин"], "birth_date": "1953-03-30", "nationality": "ru"},
    "C-1002": {"schema": "Vessel", "names": ["Selam"], "imo": "9418286"},
    "C-1003": {"schema": "Person", "names": ["Zz Crown Checklist Testperson"], "birth_date": "1980", "nationality": "ca"},
}
queries = {cid: to_query(c) for cid, c in customers.items()}
out = match("default", queries, limit=3, threshold=0.75)

for cid, answer in out["responses"].items():
    print(cid, answer["status"], "candidates:", answer["total"])
    for hit in answer["results"][:1]:
        print("   top:", hit["caption"], hit["score"], "match" if hit["match"] else "no match", hit["datasets"][:1])
print("checked_at:", out["checked_at"], "| collection:", out["collection"], "| threshold:", out["threshold"])

Définir le seuil et lire l’indicateur de correspondance

Chaque résultat comporte un score de 0 à 1 et un indicateur match, qui vaut true lorsque le score est égal ou supérieur à threshold. Le seuil par défaut est de 0.75 et la valeur par défaut de limit est de 5 résultats par requête (jusqu’à 50). Les résultats sous le seuil sont tout de même renvoyés avec match défini à false, ce qui permet aux réviseurs de voir les quasi-correspondances.

CaractéristiqueCe qui est mesuréEffet sur le score
name_matchAlignement mot à mot du nom de la requête avec les noms et alias de la fiche.Établit le score de base.
dob_matchDate de naissance, selon la précision de la fiche.+0.10 en cas de correspondance; 0 si seule l’année correspond; −0.25 si elle diffère.
country_matchNationalité ou code de pays.+0.05 en cas de correspondance; −0.10 si elle diffère.
identifier_matchNuméro IMO.Au moins 0.98 en cas de correspondance; −0.30 s’il diffère.
type_mismatchLa fiche est d’un type différent de schema.−0.20.

Traiter les correspondances possibles

Un résultat dont match est défini à true est une correspondance possible, et non une conclusion. Acheminez-le vers une file d’examen et conservez une décision pour chacun.

Consigner ce qui a été vérifié

Nous ne conservons pas le corps des requêtes; votre système doit donc tenir son propre registre de chaque vérification, y compris celles sans correspondance. Conservez la réponse telle qu’elle a été reçue et ajoutez les champs ci-dessous.

Champ à consignerProvenance
Votre ID de client ou de contrepartieVotre système.
Requête telle qu’envoyéeLe corps de votre requête.
Collection et sa versionLe nom de la collection utilisée et son version provenant de /api/catalog au moment de la vérification.
Algorithme, seuil et limiteLes paramètres de requête que vous avez envoyés. La réponse reprend algorithm, threshold et limit.
Heure de la vérificationchecked_at dans la réponse (UTC).
ID de la fiche, entité fusionnée, score et caractéristiquesLes éléments id, merged_entity, score et features de chaque résultat.
Registres, sujets et programmeLes éléments datasets, topics et programme de chaque résultat.
Décision, réviseur et date de la décisionVotre file de révision.

Revérifier et surveiller

Les listes changent. Une partie blanchie le mois dernier peut produire une correspondance après une nouvelle inscription. Effectuez une nouvelle vérification selon un calendrier établi, et chaque fois qu’une collection est reconstruite.

import os, json, requests

BASE = os.environ.get("CROWN_API_BASE", "https://api.crownintelligence.net")

# Versions now, to compare with the versions stored at the last run
catalog = requests.get(f"{BASE}/api/catalog", timeout=30).json()
versions = {c["name"]: c["version"] for c in catalog["collections"]}
last_run = {"sanctions": "20261004022212-jhp"}  # the version stored at the last run
changed = [name for name, v in versions.items() if last_run.get(name) not in (None, v)]
print("collections rebuilt since the last run:", changed)

# Only records added or changed since the last run (ISO 8601 date or time)
body = {"queries": {"C-1001": {"schema": "Person", "properties": {"name": ["Igor Putin"], "birthDate": ["1953"]}}}}
r = requests.post(f"{BASE}/api/match/sanctions", params={"limit": 10, "changed_since": "2026-10-01"},
                  json=body, timeout=60)
r.raise_for_status()
answer = r.json()["responses"]["C-1001"]
print("changed since 2026-10-01:", answer["total"], "candidates;", r.json()["filters"]["changed_since"])

# Entity lookup for the review screen
ent = requests.get(f"{BASE}/api/entity/379781867", timeout=30).json()
print(ent["id"], ent["name"], ent["register"], ent["list_type"], ent["listings"][0]["register"])

Limites de débit, nouvelles tentatives et volume

Le service de données comporte une limite de requêtes par adresse que l’exploitant peut activer. Elle est désactivée actuellement et aucun chiffre n’est publié. Les conditions se réservent le droit d’appliquer des limites ou des plafonds de volume à l’utilisation automatisée; convenez donc de vos volumes avec nous avant d’envoyer un lot important.

À venir : La limite de requêtes qui s’appliquera à l’utilisation anonyme et sous licence, le cas échéant. L’émission des clés, l’en-tête de requête et le format des clés, une fois les clés introduites. Ne développez pas en vous fondant sur un format présumé.

Tester avec des noms connus

Testez l’intégration avec des noms dont l’inscription est connue avant la mise en production, et conservez le jeu de tests dans le contrôle de version. Incluez :

Une vérification que nous avons effectuée pour cette page : la requête Igor Putin, année de naissance 1953 et nationalité ru, sur la collection de sanctions avec un seuil de 0.8, a retourné l’inscription aux sanctions avec un score de 1 et match défini à true. Les résultats dépendent de la construction utilisée; consignez donc la version de la collection à chaque exécution de test et répétez les tests après chaque reconstruction.

Vérifications avant la mise en production

Exemples

Les exemples ci-dessous sont des points de départ; exécutez-les dans un environnement de test avant de vous y fier. Définissez CROWN_API_BASE pour modifier l’adresse de base; la valeur par défaut est le service public.

Node.js : requête de correspondance

const BASE = process.env.CROWN_API_BASE ?? "https://api.crownintelligence.net";
const queries = {
  vessel: { schema: "Vessel", properties: { name: ["Selam"], imoNumber: ["9418286"] } },
  person: { schema: "Person", properties: { name: ["Igor Putin"], birthDate: ["1953-03-30"], nationality: ["ru"] } },
};
const params = new URLSearchParams({ limit: "3", threshold: "0.75" });
const res = await fetch(`${BASE}/api/match/maritime?${params}`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ queries }),
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
for (const [key, answer] of Object.entries(data.responses)) {
  const top = answer.results[0];
  console.log(key, answer.status, answer.total, top ? [top.caption, top.score, top.match] : "no hits");
}

curl : versions des collections et une correspondance

# Versions of each collection, to see when a list was rebuilt
curl -s "$CROWN_API_BASE/api/catalog" | python3 -c 'import json,sys; [print(c["name"], c["version"]) for c in json.load(sys.stdin)["collections"]]'

# One party against the sanctions collection
curl -s -X POST "$CROWN_API_BASE/api/match/sanctions?limit=3&threshold=0.8&topics=sanction" \
  -H "Content-Type: application/json" \
  -d '{"queries":{"q1":{"schema":"Person","properties":{"name":["Igor Putin"],"birthDate":["1953"],"nationality":["ru"]}}}}'
À venir : Des indications sur la collection à utiliser pour chaque obligation. Crown Intelligence ne détermine pas votre politique de vérification.

Dernière mise à jour : 2026-10-10