> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Intégration de la surveillance des transactions : API KYT

> Intégrez la surveillance des transactions avec Didit : temps réel ou batch, idempotence, webhooks. 1,000 par mois inclus, puis $0.001 chacun.

Ce guide couvre l'ensemble de l'intégration de la Surveillance des transactions. Le [guide de démarrage rapide](https://docs.didit.me/fr/transaction-monitoring/quickstart.md) vous permet de démarrer ; cette page vous accompagne jusqu'à la mise en production.

## Architecture

```mermaid theme={null}
sequenceDiagram
    participant You as Your platform
    participant Didit as Didit API
    participant Rules as Rule engine
    participant AML as AML providers
    participant Webhook as Your webhook

    You->>Didit: POST /v3/transactions/ (txn_id, parties, amount)
    Didit->>Didit: IP enrichment (inline)
    Didit->>AML: Screen wallet or transaction hash + address
    AML-->>Didit: Hits / clean
    Didit->>Rules: Evaluate all active rules
    Rules-->>Didit: Score + matched rules + actions
    Didit-->>You: Transaction record with status
    Didit->>Webhook: transaction.created
    Didit->>Webhook: transaction.status.updated (if async rules)
```

## Authentification

En-tête `x-api-key` standard. Les mêmes clés servent pour les sessions et les entités. Voir [authentification de l'API](https://docs.didit.me/fr/getting-started/api-authentication.md).

## Envoi d'une transaction

Endpoint unique : `POST /v3/transactions/`. Voir [envoi des transactions](https://docs.didit.me/fr/transaction-monitoring/transactions.md) pour le schéma complet.

**Payload minimal :**

```json theme={null}
{
  "transaction_id": "tx-0001",
  "transaction_category": "finance",
  "transaction_details": {
    "direction": "outbound",
    "amount": "500.00",
    "currency": "EUR"
  },
  "subject": { "entity_type": "person", "vendor_data": "user-42", "full_name": "John Doe" },
  "counterparty": { "entity_type": "company", "full_name": "Acme Corp" }
}
```

**Payload plus riche, avec moyens de paiement, contexte de l'appareil et propriétés personnalisées :**

```json theme={null}
{
  "transaction_id": "tx-0002",
  "transaction_at": "2026-04-16T10:00:00Z",
  "transaction_category": "finance",
  "transaction_details": {
    "direction": "outbound",
    "amount": "12500.00",
    "currency": "USD",
    "action_type": "withdrawal"
  },
  "subject": {
    "entity_type": "person",
    "vendor_data": "user-42",
    "full_name": "John Doe",
    "country_code": "US",
    "device_context": {
      "fingerprint": "fp-9f2c...",
      "user_agent": "Mozilla/5.0 ...",
      "browser_family": "Chrome",
      "platform": "web",
      "network_context": { "ip_address": "203.0.113.5" }
    },
    "payment_method": {
      "method_type": "bank_account",
      "account_id": "US12345678901234567890",
      "issuing_country": "US"
    }
  },
  "counterparty": {
    "entity_type": "company",
    "vendor_data": "biz-acme",
    "full_name": "Acme Corp",
    "country_code": "US",
    "payment_method": {
      "method_type": "bank_account",
      "account_id": "US09876543210987654321",
      "issuing_country": "US"
    }
  },
  "custom_properties": {
    "invoice_id": "INV-2026-00042",
    "category": "b2b_goods"
  }
}
```

Les alias en camelCase sont acceptés pour chaque champ de premier niveau (`txnId`, `txnDate`, `type`, `info`, `applicant`, `props`, `travelRule`, `includeCryptoScreening`) : le format de transmission du SDK et le format snake\_case aboutissent au même endroit.

## Modélisation des parties

Chaque transaction comporte un `subject` obligatoire (votre client, c'est-à-dire la partie que vous surveillez) et un `counterparty` facultatif (l'autre partie). Chacune possède son propre `payment_method` et un contexte `device` facultatif.

Dans la réponse, elles sont renvoyées dans le tableau `parties` avec les rôles `APPLICANT` et `COUNTERPARTY`. Une partie sans `vendor_data` est enregistrée comme instantané externe (`kind: EXTERNAL`), sans entité liée.

Voir [payload des transactions](https://docs.didit.me/fr/transaction-monitoring/transactions.md) pour les champs des parties.

## Idempotence

`txn_id` (le `transaction_id` que vous envoyez) est unique par application.
Renvoyer un `transaction_id` déjà existant retourne `400` avec `A transaction with this transaction_id already exists.` sur le champ `transaction_id`. Lorsque deux requêtes identiques arrivent en même temps, la seconde reçoit `409`.
Aucune de ces deux réponses ne renvoie la transaction existante.
En cas de `400` ou de `409` pour un `transaction_id` en double, consultez la transaction existante au lieu de la soumettre à nouveau : lisez-la avec [`GET /v3/transactions/{uuid}/`](https://docs.didit.me/fr/management-api/transactions/get) en utilisant l'`uuid` de la première réponse, ou utilisez le `transaction_id` (l'uuid Didit) que le webhook `transaction.created` transmet à côté de votre `txn_id`.

**Générez toujours `txn_id` de votre côté** avant l'envoi ; ne vous fiez pas à un identifiant généré par Didit pour l'idempotence. Utilisez l'ID de votre base de données, un UUID ou un hachage des champs de la transaction.

## Temps réel ou traitement par lots

* **Temps réel** : recommandé pour la plupart des cas d'usage. Envoyez la transaction dès qu'elle se produit dans votre système. Les règles sont évaluées de manière synchrone et renvoient la décision.
* **Traitement par lots / rattrapage de données historiques** : pour l'ingestion d'historique, passez un `txn_date` dans le passé. Les règles s'exécutent quand même et peuvent déclencher des webhooks. Pour éviter de déclencher les règles lors du rattrapage de données historiques, utilisez l'import CSV de la console avec l'option « dry ingest ».

## Ingestion de l'historique

Lorsque vous migrez depuis un autre système de surveillance des transactions :

1. Exportez vos transactions historiques au format CSV.
2. Utilisez *Transactions → Importer l'historique* dans la console (ou envoyez-les via l'API dans une boucle) avec un `txn_date` dans le passé.
3. Activez les règles uniquement une fois l'ingestion terminée, ou utilisez « dry ingest » pour ne pas évaluer les règles.

> [!WARNING]
>
> Soyez prudent avec l'évaluation rétroactive des règles. Faire passer 6 mois d'historique par une règle « 20 transferts en 30 jours » générera des milliers d'alertes d'un coup.

## Webhooks

Abonnez-vous à :

* `transaction.created` : chaque transaction envoyée.
* `transaction.status.updated` : changements de statut (par exemple, un analyste passe de `IN_REVIEW` à `APPROVED`, ou une vérification AML asynchrone met à jour le score).

Détails complets : [webhooks TM](https://docs.didit.me/fr/transaction-monitoring/webhooks.md).

```typescript theme={null}
app.post('/webhooks/didit-tm', (req, res) => {
  if (!verifySignature(req)) return res.status(401).end();

  const { webhook_type, status, txn_id } = req.body;
  if (webhook_type === 'transaction.status.updated' && status === 'DECLINED') {
    suspendTransaction(txn_id);
  }
  res.status(200).end();
});
```

## Gestion des statuts

| Statut | Que faire |
| - | - |
| `APPROVED` | Traiter la transaction normalement. |
| `IN_REVIEW` | Mettre la transaction en attente jusqu'à ce que l'examen par un analyste soit terminé ou qu'une revérification automatique ait résolu le problème. |
| `DECLINED` | Rejeter la transaction. Afficher un message d'erreur générique à l'utilisateur. |
| `AWAITING_USER` | L'utilisateur doit agir avant que la transaction puisse être finalisée : lisez le bloc `action_required` et transmettez son `url` à l'utilisateur (les SDK peuvent [gérer cela automatiquement](https://docs.didit.me/fr/transaction-monitoring/sdk-transaction-submission.md#actions-requises-de-l’utilisateur)). |

Voir [statuts TM](https://docs.didit.me/fr/transaction-monitoring/statuses.md).

## Lier les transactions aux entités

Transmettez `vendor_data` sur chaque partie. Avantages :

* Chaque transaction est agrégée dans le profil Utilisateur ou Entreprise.
* Les règles de vélocité et comportementales disposent de l'historique complet pour leur évaluation.
* Le blocage d'une entité se propage automatiquement aux transactions futures.

L'absence de `vendor_data` n'est pas une erreur bloquante : la transaction est enregistrée comme instantané externe, mais vous perdez l'agrégation au niveau de l'entité.

## Sessions de remédiation

Lorsqu'une action de règle fait passer une transaction à `AWAITING_USER`, Didit crée automatiquement une **session de remédiation** - une session de vérification hébergée standard pour le même `vendor_data`.
Les règles personnalisées désignent toujours le workflow directement sur l'action. Pour les règles de la bibliothèque intégrée, le workflow est d'abord celui du [workflow de remédiation de vos paramètres de transaction](https://docs.didit.me/fr/transaction-monitoring/settings.md#workflow-de-remédiation), puis votre workflow d'**Authentification biométrique** (lorsque le sujet dispose d'un visage de référence enregistré), puis le workflow par défaut de votre application.
Les transactions Travel Rule sont exclues de ce repli automatique : leur action en attente est la preuve de propriété du portefeuille.
La transaction (réponse, chaque lecture ultérieure et chaque webhook) la porte dans le bloc canonique `action_required` :

```json theme={null}
{
  "status": "AWAITING_USER",
  "action_required": {
    "type": "verification_session",
    "url": "https://verify.didit.me/session/...",
    "session_id": "11111111-2222-3333-4444-555555555555",
    "session_token": "SESSION_TOKEN",
    "status": "Not Started"
  },
  "remediation": {
    "session_id": "11111111-2222-3333-4444-555555555555",
    "session_token": "SESSION_TOKEN",
    "url": "https://verify.didit.me/session/...",
    "status": "Not Started"
  }
}
```

`remediation` est conservé pour la rétrocompatibilité ; `action_required` est le bloc canonique (il porte aussi les actions `wallet_ownership` pour les transferts [Travel Rule](https://docs.didit.me/fr/transaction-monitoring/travel-rule.md)).
Une action `wallet_ownership` ne modifie pas à elle seule le statut de la transaction : celle-ci conserve le statut que vos règles lui attribuent, souvent `APPROVED`. Vérifiez donc `action_required` sur chaque réponse, et pas seulement lorsque le statut est `AWAITING_USER`.

L'utilisateur effectue la vérification. Pour un workflow d'**Authentification biométrique**, il s'agit d'un selfie contrôlé par détection du vivant, comparé au visage capturé lors de son onboarding KYC initial : c'est l'étape de vérification renforcée la plus robuste pour les [transactions à forte valeur](https://docs.didit.me/fr/transaction-monitoring/sdk-transaction-submission.md#exemple-de-renforcement-biométrique-pour-un-retrait-d’un-montant-élevé).
Une fois la session parvenue à une décision, la transaction la suit automatiquement : `APPROVED` (`decision_reason_code: user_action_approved`), `DECLINED` (`user_action_declined`) ou `IN_REVIEW` (`user_action_in_review`). Un webhook `transaction.status.updated` est alors déclenché.

> [!NOTE]
>
> Tout type de workflow, à l'exception de KYB, peut être sélectionné.
> Les workflows d'Authentification biométrique (ainsi que les workflows dans lesquels la correspondance faciale est effectuée avant la vérification d'identité) exigent que le sujet dispose déjà d'un visage de référence enregistré issu d'une vérification approuvée. Les utilisateurs qui n'en ont pas sont orientés vers le workflow par défaut de votre application, avec une note sur la transaction indiquant cette substitution.

## Bonnes pratiques

| Pratique | Pourquoi |
| - | - |
| Transmettez toujours `vendor_data` | Permet l'agrégation. |
| Utilisez votre propre `txn_id` | Idempotence. |
| Abonnez-vous à `transaction.created` et à `transaction.status.updated` | Détecter les changements d'état asynchrones (par ex. résultats de l'examen par un analyste). |
| Définissez les seuils des règles avec soin | Seuils bas = plus d'alertes ; seuils élevés = davantage de risques non détectés. Voir [notation des risques](https://docs.didit.me/fr/transaction-monitoring/risk-scoring.md). |
| Suivez le nombre d'exécutions des règles dans la console | Repérer les règles qui ne se déclenchent jamais (mal configurées) ou qui se déclenchent sur tout (trop permissives). |
| Testez les règles en mode TEST avant la mise en production | Voir [règles](https://docs.didit.me/fr/transaction-monitoring/rules.md). |

## Limites de débit

Voir [limitation du débit](https://docs.didit.me/fr/integration/rate-limiting.md). La création de transactions est l'un des endpoints les plus sollicités ; les limites habituelles se situent à plusieurs centaines de requêtes par seconde. Effectuez les rafales avec prudence.

## Étapes suivantes

> [card] [Transactions](https://docs.didit.me/fr/transaction-monitoring/transactions.md)
>
> Référence complète du payload.

> [card] [Règles](https://docs.didit.me/fr/transaction-monitoring/rules.md)
>
> Fonctionnement de l'évaluation des règles.

> [card] [Webhooks](https://docs.didit.me/fr/transaction-monitoring/webhooks.md)
>
> Catalogue des événements.

> [card] [Dépannage](https://docs.didit.me/fr/transaction-monitoring/troubleshooting.md)
>
> Problèmes d'intégration courants.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.