API partenaire v1 · Version préliminaire, pas encore en service
API partenaire v1 : aperçu
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.
La version 1 est la couche destinée aux partenaires, construite au-dessus du service de données de Crown Intelligence. Elle ajoute des clés API avec portées, la mesure de l’utilisation, la mise en correspondance par lots avec un statut clair pour chaque requête, des webhooks, la surveillance des entrées de listes publiques et des dossiers de preuves. Cette page explique les règles que suit chaque opération.
État de cette API
Le contrat v1 est une ébauche, version 1.0.0-rc.1. Il n’est ni déployé, ni publié, ni facturé. Les adresses ci-dessous sont proposées; elles ne pointent pas encore vers un service en fonctionnement.
| Production (proposée) | https://api.crownintelligence.net |
|---|---|
| Bac à sable (proposé) | https://sandbox.api.crownintelligence.net, mêmes registres publics, jamais facturé |
| Contrat lisible par machine | crown-intelligence-v1.yaml (OpenAPI 3.1.0, ébauche) |
Clés API et portées
Envoyez la clé dans l’en-tête X-Api-Key à chaque requête, sauf pour GET /v1/status, qui n’exige aucune clé.
- Les clés de production commencent par
ci_live_. Les clés de bac à sable commencent parci_test_. Une clé de bac à sable n’atteint jamais une route de production et ne crée jamais de commande facturable. - Le secret n’est affiché qu’une seule fois, à la création de la clé. Crown Intelligence ne conserve qu’un hachage et le préfixe visible.
- Chaque clé comporte des portées explicites. Une clé qui n’a pas la portée requise par une route reçoit l’erreur 403
forbidden_scope. - La révocation est immédiate et définitive. Une clé révoquée renvoie 401
key_revoked. Les clés sont retirées, jamais supprimées. - Une clé de production doit indiquer la commande d’abonnement à laquelle elle est facturée (
order_id).
| Portée | Couvre |
|---|---|
match:read | POST /v1/match et rapprochement |
search:read | Recherche, fiches, entités et collections |
sources:read | Sources, programmes et statistiques des collections |
exports:read | Téléchargements de registres, lorsque la licence le permet |
webhooks:manage | Points d’accès des webhooks et leurs journaux de livraison |
monitors:manage | Surveillance des entrées de listes publiques |
cases:read, cases:write | Dossiers, décisions et dossiers de preuves |
usage:read | Utilisation en unités |
keys:manage | Création et révocation des clés |
Essayez : une requête avec clé
curl :
curl https://api.crownintelligence.net/v1/sources \
-H "X-Api-Key: $CI_API_KEY" Node (20 ou version ultérieure) :
const res = await fetch("https://api.crownintelligence.net/v1/sources", {
headers: { "X-Api-Key": process.env.CI_API_KEY }
});
if (!res.ok) throw new Error("HTTP " + res.status);
const body = await res.json(); Vérification de l’état sans clé :
curl https://api.crownintelligence.net/v1/status Référence de facturation : appels internes seulement
Chaque appel entre services comporte une référence de facturation, envoyée dans l’en-tête X-Billing-Ref sous forme de JSON ASCII compact d’au plus 1 024 octets. Elle indique pour qui l’appel est effectué, afin que l’utilisation puisse être facturée et que le coût soit consigné.
{"source_service":"partner-api","source_account":"acct_demo_bank",
"order_id":"ord_2026_1041","type":"ORDER","parent_call":null,"invoice_line_id":null} - Les appels des partenaires peuvent omettre l’en-tête. La passerelle renseigne
source_serviceetsource_accountà partir de la clé authentifiée, et déduit la commande de la valeurorder_idde la clé. Un partenaire ne peut pas les définir lui-même. Si un en-tête envoyé contredit sa clé, l’appel est refusé avec l’erreur 400billing_ref_invalid. - Les appels internes doivent l’envoyer. Un service Crown qui appelle Crown Intelligence sans l’en-tête est refusé avec l’erreur 400
billing_ref_missing. L’objet est transmis tel quel tout au long de la chaîne, et chaque maillon définitparent_callcomme l’appel qui l’a déclenché. typevautORDERlorsqu’un client paie l’appel. Il vautOVERHEADpour le trafic système, sans facture, le coût étant tout de même consigné. UnORDERdoit comporterorder_id; unOVERHEADcomporteorder_id: null.- Aucun autre champ n’est autorisé. L’API n’affiche jamais de montants : l’utilisation est exprimée en unités seulement, et les prix figurent sur la facture.
// Internal Crown service calling match: pass the caller's billing_ref unchanged in X-Billing-Ref.
const billingRef = {
source_service: "your-registered-service-id",
source_account: null,
order_id: null,
type: "OVERHEAD",
parent_call: incomingBillingRefId, // id of the call that triggered this one, or null at the top
invoice_line_id: null
};
const res = await fetch("https://api.crownintelligence.net/v1/match", {
method: "POST",
headers: {
"X-Api-Key": process.env.CI_INTERNAL_KEY,
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
"X-Billing-Ref": JSON.stringify(billingRef)
},
body: JSON.stringify({ queries: [{ query_ref: "svc-1", entity_type: "Company", name: "Northwind Trading LLC" }] })
}); Points en suspens : l’identifiant de source partner-api n’est pas encore enregistré dans le catalogue de services, et le propriétaire n’a pas encore décidé si les lignes d’utilisation comportent une référence de prix. Voir le contrat, sections 4 et 16.
Statuts de correspondance : jamais « clair » par défaut
Chaque requête d’une réponse de correspondance a l’un des quatre statuts. La règle est simple : une requête n’est déclarée claire que si tous les registres qu’elle devait couvrir ont été consultés et que rien ne correspond. Le mot clear n’est une valeur nulle part dans l’API.
| Statut | Signification | Peut-on le traiter comme une absence de correspondance? |
|---|---|---|
hit | Au moins une correspondance à min_band ou au-dessus | Non. Examinez les correspondances. |
no_hit_searched | Tous les registres énumérés ont été consultés. Aucune correspondance. La réponse énumère chaque registre avec loaded_at. | Oui. C’est le seul résultat négatif. |
not_searched | Rien n’a été vérifié, par exemple un identifiant qu’aucun registre chargé ne couvre. La raison est indiquée. | Jamais. Non vérifié ne signifie pas clair. |
error | La vérification a échoué. Réessayez. | Jamais. Une vérification échouée ne signifie pas clair. |
Un statut not_searched ou error ne doit jamais être affiché comme clair, enregistré comme clair ni transmis comme clair. Concevez votre logique de décision de façon que seul no_hit_searched puisse produire un résultat négatif.
Niveaux de correspondance
Chaque correspondance comporte un niveau plutôt qu’un seuil brut. Les niveaux découlent du score (de 0 à 1) et des identifiants concordants.
| Niveau | Règle | Renvoyé lorsque |
|---|---|---|
STRONG | Score de 0,90 ou plus, ou IMO, MMSI ou LEI exact | Toujours, si à min_band ou au-dessus |
POSSIBLE | Score de 0,75 à 0,89 | Valeur par défaut de min_band |
WEAK | Score de 0,60 à 0,74 | Seulement lorsque min_band est WEAK |
Rien en dessous de 0,60 n’est renvoyé. Les seuils des niveaux sont proposés et n’ont pas encore été calibrés sur un ensemble de paires étiquetées; ne fondez donc aucune règle fixe sur eux avant la publication de la calibration. Les versions du moteur de correspondance seront indiquées dans chaque réponse.
Limites de débit et quotas
Ces valeurs par défaut sont proposées. Les limites des forfaits sont provisoires jusqu’à ce que le propriétaire les établisse.
| Limite | Valeur par défaut proposée |
|---|---|
| Requêtes par minute, par clé | 120 |
| Unités de requête par minute, par clé | 600 |
| Requêtes par lot | 100 |
| Requêtes d’exportation par minute, par clé | 10 |
| Unités mensuelles | Défini selon le forfait. Tout dépassement renvoie 429 quota_exceeded. |
Chaque réponse comporte RateLimit-Limit, RateLimit-Remaining et RateLimit-Reset. Les appels mesurés comportent également X-Usage-Units. Une réponse 429 comporte Retry-After.
Idempotence et versions
Chaque requête POST accepte un en-tête Idempotency-Key d’au plus 255 caractères. Répéter la même clé avec le même corps dans un délai de 24 heures renvoie la réponse enregistrée, sans second débit. Réutiliser la clé avec un corps différent renvoie 409 idempotency_mismatch.
La version figure dans le chemin (/v1). Les changements au sein de v1 sont additifs. Un changement incompatible passe à /v2, avec un préavis d’au moins six mois avant toute dépréciation.
Erreurs
Chaque erreur est de type application/problem+json (RFC 9457). Chaque erreur comporte un code stable, un request_id à indiquer au soutien technique, ainsi que son message en anglais (messages.en) et en français (messages.fr).
{"type":"https://api.crownintelligence.net/problems/invalid_request","title":"Invalid request",
"status":400,"code":"invalid_request","detail":"queries[3].name must be at least 2 characters",
"messages":{"en":"queries[3].name must be at least 2 characters",
"fr":"queries[3].name doit comporter au moins 2 caractères"},
"request_id":"req_01J9Z3K4M6","errors":[{"pointer":"/queries/3/name","code":"too_short",
"message":{"en":"Use at least 2 characters.","fr":"Utilisez au moins 2 caractères."}}]} | HTTP | Code | Quand |
|---|---|---|
| 400 | invalid_request | Le corps ou un paramètre ne respecte pas le schéma |
| 400 | billing_ref_missing, billing_ref_invalid | Un appel interne n’a pas de référence de facturation, ou ses champs ne concordent pas avec la clé |
| 400 | personal_data_not_accepted | Le corps d’une surveillance contient un champ de données personnelles |
| 401 | unauthenticated, key_revoked | La clé est absente, inconnue ou révoquée |
| 403 | forbidden_scope, forbidden_environment | La portée est absente, ou une clé de bac à sable appelle une route en production |
| 404 | not_found | Également utilisé lorsqu’une fiche n’est pas visible pour le compte |
| 409 | conflict, idempotency_mismatch | Un doublon, ou une Idempotency-Key réutilisée avec un corps différent |
| 413 | payload_too_large, batch_too_large | Plus de 1 Mo, ou plus de 100 requêtes |
| 429 | rate_limited, quota_exceeded | Voir les limites de débit ci-dessus. Attendez Retry-After. |
| 503 | register_unavailable, unavailable | Un registre ou le service est indisponible. Réessayez avec un délai d’attente progressif. |
| 500 | internal_error | Signalez-la avec le request_id |
Dans un lot, une requête individuelle peut échouer avec un statut error. Le lot lui-même renvoie tout de même 200, et cette requête n’est jamais signalée comme sans correspondance.
const res = await fetch(url, { headers: { "X-Api-Key": process.env.CI_API_KEY } });
if (!res.ok) {
const problem = await res.json(); // application/problem+json
console.error(problem.code, problem.request_id, problem.messages.en);
if (res.status === 429 || res.status === 503) {
const wait = Number(res.headers.get("Retry-After") ?? 5); // back off, then retry the same request
}
}