Référence API
L'API Anonari expose un chemin principal : POST /v1/minimize. C'est lui qui résout le profil de données rattaché à votre clé, applique la politique de minimisation, et retourne la charge utile minimisée accompagnée d'un reçu signé.
Les endpoints de signaux agrégés (/snapshot, /metrics, /thirdparty/{id}, /portfolio/summary, /v2/signals/summary…) sont antérieurs à ce moteur et dépréciés : ils authentifient la clé mais ne résolvent pas son profil et n'émettent aucun reçu. Voir Endpoints dépréciés en fin de page. Toute nouvelle intégration doit utiliser /v1/minimize.
En six étapes
- Créez une clé API depuis le dashboard Anonari, section Clés API.
- Choisissez son profil de données au moment de la création. Une clé donne accès à exactement un profil, pour toujours : il n'existe aucun moyen de l'élargir ensuite, ni depuis le dashboard, ni depuis une requête.
- Le profil détermine ce qui peut sortir : quels types d'objets sont acceptés, quelles catégories de données sont restituées, et sous quelle forme (montant exact ou tranche, date exacte ou relative, identifiant brut ou pseudonyme).
- Chaque appel traverse le moteur de minimisation. Rien n'est restitué qui ne soit explicitement autorisé par le profil.
- Un
trace_idest généré pour chaque traitement, et retourné dans la réponse. - Anonari émet un reçu signé (Ed25519) décrivant le traitement : profil utilisé, empreinte de la politique, catégories retirées / transformées / restituées, empreinte de la sortie. Conservez-le : il atteste ce qu'Anonari a fait, et il est vérifiable sans faire confiance à Anonari.
Authentification
Toutes les requêtes nécessitent un header :
Authorization: Bearer ak_xxx
La clé se génère depuis le dashboard, section Clés API. Elle n'est affichée en clair qu'une seule fois : Anonari n'en conserve qu'une empreinte SHA-256 et ne peut pas vous la réafficher.
Deux domaines servent les mêmes fichiers, avec des préfixes différents :
| Domaine | Chemin | |---|---| | api.anonari.fr | POST /v1/minimize | | anonari.fr | POST /api/v1/minimize |
POST /v1/minimize
Requête
{
"object_type": "customer_invoice_history",
"schema_version": "1.0",
"data": {
"invoice_id": 1547,
"customer_id": 42,
"amount_ttc": 3450,
"status": "unpaid",
"due_date": "2026-08-01",
"payment_delay_days": 47
}
}
| Champ | Obligatoire | Rôle | |---|---|---| | objecttype | oui | Type de l'objet soumis (voir le catalogue plus bas) | | data | oui | Objet plat champ: valeur | | schemaversion | non | Version du schéma de votre payload, recopiée dans le reçu (défaut 1.0) | | expected_profile | non | Vérification de configuration — voir plus bas |
expectedprofile ne choisit jamais le profil appliqué : le profil vient toujours de la clé. Ce champ sert uniquement à faire échouer bruyamment un déploiement mal câblé — si la valeur fournie (code.vVERSION, ex. financial.payment-risk.v1) ne correspond pas au profil réel de la clé, l'appel est rejeté en 409 PROFILEMISMATCH plutôt que de traiter silencieusement avec un autre profil.
Réponse
{
"trace_id": "trc_a4dc8615db012147d5beb52dcec7a65e452a",
"profile": {
"code": "financial.payment-risk",
"version": "1",
"checksum": "47bb2a09e98caf60d35fb17116f1d023f8bbabe629a74bfc53a65bdfa60d737a"
},
"data": {
"invoice_id": "ref_99515e70b292a106cb56",
"customer_id": "ref_e33972a192f9a856deb4",
"amount_ttc": "1000-5000",
"status": "unpaid",
"due_date": -44,
"payment_delay_days": 47
},
"receipt": {
"receipt_id": "mrc_19ad5c6de5e555df3fd97d4933acf21a91e2",
"trace_id": "trc_a4dc8615db012147d5beb52dcec7a65e452a",
"processed_at": "2026-09-14T09:13:17+02:00",
"profile_code": "financial.payment-risk",
"profile_version": 1,
"policy_checksum": "47bb2a09e98caf60d35fb17116f1d023f8bbabe629a74bfc53a65bdfa60d737a",
"engine_version": "1.0.0",
"object_type": "customer_invoice_history",
"removed_categories": ["postal_location"],
"transformed_categories": ["entity_reference", "financial_amount", "calendar_date"],
"returned_categories": ["entity_reference", "financial_amount", "financial_status", "calendar_date", "payment_delay"],
"input_field_count": 7,
"output_field_count": 6,
"output_digest": "sha256:83ec8590…",
"signature": "nCyZtD7MT1/7ScBEdIWAhFfan+…"
}
}
Dans cet exemple, produit par le profil financial.payment-risk.v1 : les identifiants sont remplacés par des pseudonymes stables au compte, le montant devient une tranche, l'échéance devient un nombre de jours relatif, et l'adresse de facturation soumise en entrée a été retirée — elle n'appartient à aucune catégorie autorisée par ce profil.
Le reçu ne contient jamais de valeur métier : uniquement des métadonnées, des compteurs, et une empreinte de la sortie (output_digest). Il ne permet pas de reconstituer la donnée.
Deux comportements distincts : retrait et refus
C'est le point le plus important pour intégrer correctement l'API.
Retrait silencieux. Une catégorie que votre profil n'autorise pas est retirée de la réponse. Ce n'est pas une erreur : c'est le fonctionnement normal de la minimisation. Le reçu la liste dans removed_categories.
Refus dur (403). Certaines catégories ne sont jamais restituables, par aucun profil, et leur simple présence dans le payload d'entrée fait échouer toute la requête :
direct_identifier · contact_information · internal_note
free_text · attachment · credential · special_category_data
Ce socle n'est pas configurable. Un profil ne peut pas le réautoriser.
Conséquence pratique à anticiper : tout champ inconnu du catalogue ci-dessous tombe par défaut dans specialcategorydata — donc en refus dur. Un objet ERP brut, même expurgé de ses champs nominatifs, sera rejeté au premier champ non répertorié. Conformez votre payload au catalogue avant d'appeler : n'envoyez que les champs listés pour l'object_type visé.
Catalogue des types d'objets
Seuls ces object_type existent, et chaque profil n'en autorise qu'un sous-ensemble.
customerinvoicehistory
| Champ | Catégorie | Restituable | |---|---|---| | invoiceid, customerid | entityreference | oui | | amountht, amountttc | financialamount | oui | | status | financialstatus | oui | | issuedate, duedate | calendardate | oui | | paymentdelaydays | paymentdelay | oui | | billingaddress | postallocation | seulement généralisée | | customername | directidentifier | refus dur | | customeremail, customerphone | contactinformation | refus dur | | notes | internalnote | refus dur | | internalcomment | free_text | refus dur | | attachments | attachment | refus dur |
quote_history
| Champ | Catégorie | Restituable | |---|---|---| | quoteid, customerid | entityreference | oui | | status | documentstatus | oui | | issuedate, responsedate | calendardate | oui | | amount | financialamount | oui | | sectorcode | businesssector | oui | | customername | directidentifier | refus dur | | notes | internal_note | refus dur |
payment_history
| Champ | Catégorie | Restituable | |---|---|---| | paymentid, invoiceid | entityreference | oui | | amount | financialamount | oui | | paymentdate | calendardate | oui | | method | financialstatus | oui | | delaydays | payment_delay | oui |
thirdparty_activity
| Champ | Catégorie | Restituable | |---|---|---| | thirdpartyid | entityreference | oui | | sectorcode | businesssector | oui | | employeecount | companysize | oui | | lastcontactdate | calendardate | oui | | activityscore | behavioralmetric | oui | | engagementtrend | derivedsignal | oui | | address | postallocation | seulement généralisée | | name | directidentifier | refus dur | | email, phone | contactinformation | refus dur | | freenotes | freetext | refus dur | | portalaccesstoken | credential | refus dur |
sector_aggregate
| Champ | Catégorie | Restituable | |---|---|---| | sectorcode | businesssector | oui | | companysizebracket | companysize | oui | | averagepaymentdelay, benchmarkscore | derived_signal | oui |
Transformations
Ce que le profil applique aux catégories qu'il autorise.
| Opération | Effet | |---|---| | keepexact | valeur restituée telle quelle | | bucket | montant → tranche (0-100, 100-500, 500-1000, 1000-5000, 5000-20000, 20000+) | | round | arrondi à la dizaine | | monthgeneralize | date → YYYY-MM | | relativedays | date → nombre de jours relatif à maintenant (négatif = passé) | | geogeneralize | code postal → 2 premiers chiffres + xxx ; adresse en texte libre → retirée | | pseudonymize_identifier | identifiant → pseudonyme, selon la politique d'identifiants du profil | | suppression | champ retiré |
Politiques d'identifiants : tenantstable (pseudonyme déterministe à l'intérieur de votre compte, ref…, jamais commun à deux comptes), requestscoped (pseudonyme différent à chaque appel, req…), none (identifiant retiré).
Codes d'erreur
| Code | Erreur | Cause | |---|---|---| | 400 | INVALIDSCHEMA | objecttype ou data manquant/mal typé | | 401 | unauthorized | clé absente, invalide, révoquée ou expirée | | 402 | paymentrequired | compte suspendu | | 403 | OBJECTTYPENOTALLOWED | objecttype inconnu, ou non autorisé par le profil de la clé | | 403 | FORBIDDENDATACATEGORY | catégorie du socle d'interdictions présente dans le payload | | 409 | PROFILEMISMATCH | expectedprofile ≠ profil réel de la clé | | 409 | PROFILEUNAVAILABLE | le profil de la clé n'est pas actif | | 429 | quotaexceeded | quota mensuel du compte atteint | | 500 | PROCESSINGFAILED | échec de traitement |
Toutes les réponses d'erreur issues du moteur portent le trace_id du traitement refusé — le même que celui écrit au journal d'audit.
Quota
Le quota est une ressource de compte, pas de clé : toutes vos clés puisent dans le même pool mensuel. Supprimer et recréer une clé ne remet aucun compteur à zéro. Chaque réponse porte :
X-Anonari-Quota-Used / X-Anonari-Quota-Limit / X-Anonari-Quota-Reset
Endpoints dépréciés
Ces endpoints restent fonctionnels pour ne pas casser les intégrations existantes, mais ne doivent plus être utilisés pour une nouvelle intégration :
/v1/snapshot /v1/metrics /v1/invoices /v1/proposals
/v1/thirdparty/{id} /v1/thirdparty/{id}/timeline /v1/thirdparty/{id}/anomalies
/v1/portfolio/summary /v2/signals/summary
Ils vérifient la clé, son expiration et son quota, mais ne résolvent pas le profil de données de la clé et n'émettent aucun reçu : leur réponse n'est couverte par aucune preuve de traitement. Leurs réponses portent désormais les en-têtes Deprecation, Sunset et Link, ainsi qu'un bloc _deprecation dans le corps JSON.
Leur raccordement au moteur de profils est un chantier en cours. D'ici là, si vous avez besoin d'une garantie de minimisation, passez par /v1/minimize.
Portée de la garantie
Anonari garantit que ce qu'il restitue via /v1/minimize est conforme au profil rattaché à votre clé : aucune identité directe, aucun champ libre non contrôlé, aucune pièce jointe brute.
Cette garantie porte sur le flux Anonari, et uniquement sur lui. Deux limites à connaître :
- Les identifiants sont pseudonymisés, pas anonymisés (art. 4.5 RGPD). Seule votre plateforme source permet de réassocier un pseudonyme à une identité réelle.
- Si votre agent dispose d'autres outils ayant un accès direct à l'ERP, à la messagerie, à un CRM ou à une base documentaire, la protection Anonari ne s'étend pas à ce que ces outils renvoient. Un agent qui reçoit un signal minimisé d'Anonari peut, dans la même conversation, aller chercher une note ou un e-mail via un autre connecteur et perdre le bénéfice de la minimisation.
Recommandation : pour tout usage où la confidentialité est une exigence, appliquez la même politique de minimisation aux autres outils de l'agent. Anonari protège ce qu'il transmet ; il ne protège pas l'ensemble des outils auxquels votre agent a accès.