Documentación · API de verificación

Lista de verificación de integración

Qué decidir, construir y probar antes de poner en producción la verificación de Crown Intelligence en su sistema: la colección, el mapeo de campos, el umbral de coincidencia, cómo se revisan y se registran las posibles coincidencias, cómo se mantienen actualizados los registros y cómo maneja la integración los límites y los errores.

Hoy la API de verificación no requiere clave y responde a solicitudes anónimas. Las comprobaciones siguientes usan los puntos de acceso de la guía de la API de verificación y de la referencia de la API. La verificación automatizada o sistemática, y el uso en un proceso de negocio, requieren una licencia comercial conforme a nuestros términos de uso. Confírmelo antes de conectar un sistema en producción.

Elija una colección

Cada colección es una ruta de coincidencia independiente. Elija la que corresponda a las listas que abarcan sus obligaciones. Un registro no es una colección por sí mismo; para limitar una búsqueda a un registro, use include_dataset.

ColecciónRuta de coincidenciaContenido
default/api/match/defaultTodos los registros activos: sanciones, PEPs, inhabilitación para contratar, medidas coercitivas y otras listas de riesgo.
sanciones/api/match/sanctionsSolo inclusiones en listas de sanciones.
peps/api/match/pepsPersonas expuestas políticamente (PEP).
crime/api/match/crimeInhabilitación para contratar, órdenes de cobro de impuestos y avisos de insolvencia.
maritime/api/match/maritimeEmbarcaciones y registros que incluyen un número IMO.

Asigne los campos del cliente a la solicitud de coincidencia

Una solicitud de coincidencia envía hasta 20 consultas con nombre en un solo cuerpo, cada una con schema y properties. Use su propio ID de cliente o contraparte como clave de la consulta, de modo que cada respuesta se asocie con su registro.

Su campoCampo de coincidenciaReglas
Nombre, o cada grafía que tengaproperties.nameArreglo de hasta 5 cadenas. Agregue una forma transliterada cuando disponga de ella. Obligatorio, salvo que se envíe imoNumber o mmsi.
Fecha de nacimientoproperties.birthDateYYYY, YYYY-MM o YYYY-MM-DD. Envíe la precisión de que disponga; un año por sí solo es válido.
Nacionalidad (persona)properties.nationalityCódigo ISO 3166 de dos letras, como ca o ru.
País de constitución (empresa)properties.countryCódigo de dos letras. El mismo campo también admite la bandera de una embarcación.
Número IMO (embarcación)properties.imoNumberSiete dígitos, como 9418286.
MMSI (embarcación)properties.mmsiNueve dígitos.
Tipo de parteschemaPerson, Company, Organization, LegalEntity o Vessel. Un registro de otro tipo reduce la puntuación (type_mismatch). Envíe el tipo que conozca en lugar de LegalEntity por defecto.

Un punto de partida que asigna un registro de cliente, envía un lote con reintentos e imprime el resultado principal de cada parte.

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"])

Defina el umbral e interprete el indicador de coincidencia

Cada resultado tiene un valor score de 0 a 1 y un indicador match, que es true cuando la puntuación es igual o superior a threshold. El umbral predeterminado es 0.75 y el valor predeterminado de limit es de 5 resultados por consulta (hasta 50). Los resultados por debajo del umbral también se devuelven, con match establecido en false, para que los revisores vean los casi coincidentes.

CaracterísticaQué mideEfecto en la puntuación
name_matchAlineación palabra por palabra del nombre de la consulta con los nombres y alias del registro.Establece la puntuación base.
dob_matchFecha de nacimiento, con la precisión del registro.+0.10 si coincide; 0 si solo coincide el año; −0.25 si es distinta.
country_matchNacionalidad o código de país.+0.05 si coincide; −0.10 si es distinta.
identifier_matchNúmero IMO.Al menos 0.98 si coincide; −0.30 si es distinto.
type_mismatchEl registro es de un tipo distinto de schema.−0.20.

Gestione las posibles coincidencias

Un resultado con match establecido en true es una posible coincidencia, no una conclusión. Envíelo a una cola de revisión y conserve una decisión para cada uno.

Registre lo que se verificó

No almacenamos los cuerpos de las consultas, por lo que su sistema debe conservar su propio registro de cada verificación, incluidas las que no arrojan coincidencia. Almacene la respuesta tal como se recibió y agregue los campos siguientes.

Campo que se debe registrarOrigen
Su ID de cliente o contraparteSu sistema.
Consulta tal como se envióEl cuerpo de su solicitud.
Colección y su versiónEl nombre de la colección que utilizó y su version de /api/catalog al momento de la verificación.
Algoritmo, umbral y límiteLos parámetros de consulta que envió. La respuesta devuelve algorithm, threshold y limit.
Hora de la verificaciónchecked_at en la respuesta (UTC).
ID del registro, entidad combinada, puntaje y característicasid, merged_entity, score y features de cada resultado.
Registros, temas y programadatasets, topics y programme de cada resultado.
Decisión, revisor y fecha de la decisiónSu cola de revisión.

Reverificar y monitorear

Las listas cambian. Una parte aprobada el mes pasado puede generar una coincidencia tras una nueva inclusión en la lista. Vuelva a verificar según un calendario y cada vez que se reconstruya una colección.

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"])

Límites de velocidad, reintentos y volumen

El servicio de datos tiene un límite de solicitudes por dirección que el operador puede activar. Hoy está desactivado y no se publica ninguna cifra. Los términos se reservan el derecho de aplicar límites o topes de volumen al uso automatizado, por lo que debe acordar sus volúmenes con nosotros antes de enviar un lote grande.

Por proporcionar: El límite de solicitudes que se aplicará al uso anónimo y con licencia, si lo hubiera. La emisión de claves, el encabezado de la solicitud y el formato de la clave, una vez que se introduzcan las claves. No desarrolle con base en un formato supuesto.

Pruebas con nombres conocidos

Pruebe la integración con nombres que tengan inclusiones conocidas en listas antes de la puesta en producción y mantenga el conjunto de pruebas bajo control de versiones. Incluya:

Una verificación que realizamos para esta página: la consulta Igor Putin, año de nacimiento 1953 y nacionalidad ru, contra la colección de sanciones con un umbral de 0.8, devolvió la inclusión en la lista de sanciones con puntaje 1 y match establecido en true. Los resultados dependen de la compilación en uso, por lo que debe registrar la versión de la colección en cada ejecución de pruebas y repetirlas después de cada reconstrucción.

Verificaciones previas a la puesta en producción

Ejemplos

Los ejemplos siguientes son puntos de partida, por lo que debe ejecutarlos en un entorno de pruebas antes de confiar en ellos. Defina CROWN_API_BASE para cambiar la dirección base; el valor predeterminado es el servicio público.

Node.js: solicitud de coincidencias

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: versiones de colecciones y una coincidencia

# 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"]}}}}'
Por proporcionar: Orientación sobre qué colección usar para cada obligación. Crown Intelligence no define su política de verificación.

Última actualización: 2026-10-10