> ## 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.

# API d'ingestion d'événements - Surveillance non monétaire

> Envoyez les activités non monétaires (connexions, parties, bonus, paiements, litiges, sécurité des comptes) au moteur qui évalue vos transactions chez Didit.

Les transactions, c'est l'argent. Les événements, c'est tout le reste de ce que votre plateforme sait : la connexion qui a précédé le retrait, la main qui a déplacé des jetons entre deux comptes, le bonus réclamé deux fois, le chargeback reçu une semaine plus tard.

Les événements utilisent une seule enveloppe pour toutes les catégories, sont idempotents par conception et sont évalués par le [même moteur de règles](https://docs.didit.me/fr/transaction-monitoring/event-rules.md) que celui qui note vos [transactions](https://docs.didit.me/fr/transaction-monitoring/transactions.md).

> [!NOTE]
>
> L'ingestion d'événements est **facultative**. Activez-la dans **Transactions → Settings → Event monitoring**.
> Tant qu'elle n'est pas activée, rien ne change : vos règles de transaction existantes continuent de s'appliquer uniquement aux transactions, et une règle d'événement ne peut pas être créée par accident, car une règle s'applique aux transactions sauf si vous y incluez explicitement les événements.
>
> Tant qu'elle n'est pas activée, chaque canal d'écriture (`POST /v3/events/`, `POST /v3/events/batch/`, `POST /v3/events/sdk-token/` et le canal d'appareil `/v1/events/`) renvoie `403` avec `{"code": "event_monitoring_disabled"}`, et rien n'est stocké, enrichi ni évalué. Les lectures ne sont pas affectées.

## Endpoints

| Endpoint | Authentification | Utilisation |
| - | - | - |
| `POST /v3/events/` | clé API | Un événement depuis votre backend |
| `POST /v3/events/batch/` | clé API | Jusqu'à 500 événements dans une seule requête |
| `POST /v3/events/sdk-token/` | clé API | Générer un identifiant d'accès à portée limitée pour l'appareil |
| `POST /v1/events/` | `X-Monitoring-Token` | Un événement depuis le SDK de l'appareil |
| `POST /v1/events/batch/` | `X-Monitoring-Token` | Un tampon du SDK vidé |
| `GET /v3/events/` | clé API | Lister et filtrer les événements |
| `GET /v3/events/{event_uuid}/` | clé API | Un événement avec les éléments de preuve des règles |
| `GET /v3/events/subjects/{vendor_data}/` | clé API | Chronologie d'un sujet (voir `entity_type` ci-dessous) |
| `GET /v3/events/enrichment-metrics/` | clé API | État du cache d'enrichissement IP |

Le canal `/v3/` est le canal serveur et utilise la même authentification `x-api-key` que le reste de l'API de transactions. Le canal `/v1/events/` est le canal de l'appareil : voir [Envoi d'événements depuis le SDK](https://docs.didit.me/fr/transaction-monitoring/sdk-event-submission.md).

## L'enveloppe

```bash theme={null}
curl -X POST https://verification.didit.me/v3/events/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "event_id": "login-2026-08-31-000001",
    "event_category": "auth",
    "action_type": "login",
    "occurred_at": "2026-08-31T20:40:31.123Z",
    "time_zone": "UTC",
    "subject": {
      "entity_type": "individual",
      "vendor_data": "user_391"
    },
    "session": { "session_id": "web-session-abc", "sequence": 142 },
    "device_context": {
      "fingerprint": "didit-fp-v2:a8c1",
      "network_context": { "ip_address": "203.0.113.42" }
    },
    "payload": { "method": "password" }
  }'
```

```json theme={null}
{
  "event_uuid": "0f2b...",
  "event_id": "login-2026-08-31-000001",
  "status": "ACCEPTED",
  "score": 0,
  "rules_evaluated_count": 6,
  "rules_matched_count": 0,
  "correlation_pending": false,
  "retention_class": "standard",
  "expires_at": "2026-09-30T20:40:31.123Z",
  "idempotent_replay": false,
  "rule_matches": []
}
```

| Champ | Obligatoire | Remarques |
| - | - | - |
| `event_id` | oui | Votre propre identifiant, unique par application. C'est la clé d'idempotence. |
| `event_category` | oui | L'une des dix catégories ci-dessous. |
| `action_type` | oui | Chaîne libre, jusqu'à 128 caractères. |
| `occurred_at` | oui | Moment où l'événement s'est produit de votre côté. Jusqu'à 7 jours dans le passé et 5 minutes dans le futur. |
| `subject.vendor_data` | oui | Votre identifiant utilisateur. Associé au même utilisateur auquel une transaction aurait été associée. |
| `subject.entity_type` | non | `individual` (par défaut) ou `company`. |
| `business.vendor_data` | non | L'entreprise à laquelle appartient l'événement. |
| `session` | non | `session_id`, `sequence`, `page_url`, `referrer`. |
| `device_context` | non | `fingerprint`, `persistent_device_id`, `bot_score` et `network_context.ip_address`. |
| `transaction_context` | non | `amount`, `currency`, `direction`, `payment_reference_id`. |
| `payload` | non | Les champs métier de la catégorie. Jusqu'à 16 Ko. |
| `custom_values` | non | Jusqu'à 100 clés scalaires, accessibles depuis les règles sous la forme `custom_values.<key>`. |

## Catégories

Dix catégories de première classe, chacune avec une validation typée et des [champs de règle](https://docs.didit.me/fr/transaction-monitoring/event-rules.md#champs-d’événement) gérés.

| Catégorie | Actions courantes |
| - | - |
| `auth` | `signup`, `login`, `login_failed`, `logout`, `password_forgot`, `password_reset`, `mfa_reset`, `mfa_challenge` |
| `session` | `session_started`, `session_ended`, `page_view`, `sdk_loaded`, `device_seen`, `bot_signal_observed`, `sdk_heartbeat` |
| `gameplay` | `round_started`, `round_completed`, `bet_placed`, `bet_settled`, `cashout`, `limit_change`, `p2p_settlement` |
| `bonus` | `bonus_claimed`, `bonus_wagered`, `bonus_released`, `promotion_viewed` |
| `affiliate` | `affiliate_attributed`, `referral_clicked`, `campaign_joined`, `commission_event` |
| `payment` | `deposit_initiated`, `deposit_completed`, `withdrawal_requested`, `withdrawal_completed`, `withdrawal_address_changed`, `payment_instrument_seen` |
| `dispute` | `chargeback_opened`, `chargeback_won`, `chargeback_lost`, `refund_issued`, `payment_dispute_updated` |
| `security` | `login_attempt`, `login_succeeded`, `login_failed`, `password_changed`, `mfa_changed`, `credential_reset`, `country_changed`, `device_changed`, `account_locked` |
| `responsible_gambling` | `self_exclusion_checked`, `self_exclusion_match`, `re_registration_attempt`, `limit_breach_attempt`, `registry_status_changed` |
| `custom` | Ce que vous définissez |

`auth` est la catégorie produit générale ; `security` est le sous-ensemble axé sur le risque, avec le cycle de vie ordonné qu'utilisent les règles de prise de contrôle de compte.

### Clés de payload requises

Certaines actions ne peuvent pas être corrélées sans clés spécifiques ; la validation les rejette plutôt que de stocker des preuves que personne ne pourra relier.

| Action | Requis |
| - | - |
| `gameplay.p2p_settlement` | `game_id`, `counterparty_vendor_data`, `stake_amount`, `net_result_amount`, `role`, et l'un des `hand_id` / `round_id` / `match_id` |
| `gameplay.bet_placed`, `gameplay.bet_settled` | `game_id` |
| `payment.deposit_*`, `payment.withdrawal_completed`, `payment.withdrawal_requested`, `payment.deposit_initiated` | `payment_reference_id`, `amount`, `currency`, `payment_method`, `status` |
| `payment.withdrawal_address_changed` | `withdrawal_address_hash` |
| `dispute.chargeback_*` | `payment_reference_id`, et l'un des `dispute_id` / `chargeback_id` |
| `security.*_changed` | `changed_field` ; les changements de contrôle de compte ou de versement exigent aussi `previous_reference_hash` ou `new_reference_hash` |
| `session.bot_signal_observed` | `telemetry_schema_version`, plus un `bot_score` ou au moins une métrique de télémétrie |
| `responsible_gambling.self_exclusion_match` | `registry_source`, `exclusion_status`, `identity_match_ref` |

> [!WARNING]
>
> Envoyez des **références et des hachages**, jamais de secrets en clair. Les instruments de paiement, les destinations de retrait et les changements de contrôle de compte sont stockés sous la forme de la référence hachée que vous envoyez. N'envoyez jamais de numéro de carte, d'adresse de retrait complète, de hachage de mot de passe ni de secret MFA.

### Exemple de règlement P2P

```json theme={null}
{
  "event_id": "p2p-hand-8842-user-391",
  "event_category": "gameplay",
  "action_type": "p2p_settlement",
  "occurred_at": "2026-08-31T12:34:17.392Z",
  "subject": { "vendor_data": "user_391" },
  "payload": {
    "game_id": "poker_holdem",
    "table_id": "table_17",
    "hand_id": "hand_8842",
    "role": "winner",
    "counterparty_vendor_data": "user_812",
    "stake_amount": "250.00",
    "net_result_amount": "240.50",
    "effective_margin": "0.038",
    "operator_ledger_ref": "ledger_998123"
  }
}
```

### Exemple de rétrofacturation

```json theme={null}
{
  "event_id": "chargeback-cb_921-opened",
  "event_category": "dispute",
  "action_type": "chargeback_opened",
  "occurred_at": "2026-08-31T09:22:05.000Z",
  "subject": { "vendor_data": "user_391" },
  "transaction_context": {
    "amount": "1000.00",
    "currency": "EUR",
    "payment_reference_id": "dep_735"
  },
  "payload": {
    "dispute_id": "disp_498",
    "chargeback_id": "cb_921",
    "reason_code": "fraudulent",
    "liability_shift": false
  }
}
```

Les cycles de vie des litiges ne peuvent être modifiés que par ajout : une correction est un nouvel événement `dispute`, jamais une modification du premier.

## Idempotence

`event_id` est unique par application et constitue l'ensemble du contrat d'idempotence.

* **Même `event_id`, même contenu** renvoie `200` avec `"idempotent_replay": true` et l'événement stocké à l'origine. Réessayez autant de fois que vous le souhaitez.
* **Même `event_id`, contenu différent** renvoie `409`. Vous avez réutilisé un identifiant par erreur.

## Lots

`POST /v3/events/batch/` accepte jusqu'à **500 événements**. Un lot est partiellement réussi par conception : une consultation de page mal formée ne doit jamais faire échouer la rétrofacturation juste à côté.

```json theme={null}
{
  "accepted_count": 2,
  "replayed_count": 0,
  "rejected_count": 1,
  "results": [
    { "index": 0, "outcome": "rejected", "errors": { "occurred_at": ["This field is required."] } },
    { "index": 1, "outcome": "accepted", "event_uuid": "…", "status": "ACCEPTED" },
    { "index": 2, "outcome": "accepted", "event_uuid": "…", "status": "IN_REVIEW" }
  ]
}
```

La réponse est `207 Multi-Status` si un élément a été rejeté et `201 Created` si tout a été enregistré.

## Statuts

| Statut | Signification |
| - | - |
| `ACCEPTED` | Enregistré. Aucune règle n'a modifié son statut (c'est la réponse normale pour la plupart des événements). |
| `APPROVED` | Une règle a été exécutée et le score est resté sous votre seuil d'examen. |
| `IN_REVIEW` | Une règle l'a fait dépasser le seuil d'examen, ou a défini directement le statut. |
| `DECLINED` | Une règle l'a refusé. |

`correlation_pending: true` signifie qu'une règle inter-sujets doit encore être exécutée ; la corrélation est résolue en quelques minutes et le statut et le score de l'événement sont mis à jour sur place. Voir [règles asynchrones](https://docs.didit.me/fr/transaction-monitoring/event-rules.md#temps-réel-et-règles-asynchrones).

## Conservation

Le volume des événements est beaucoup plus élevé que celui des transactions, donc chacun est classé dans une classe de conservation à son arrivée.

| Classe | Conservation à chaud par défaut | Ce qui y figure |
| - | - | - |
| `low_value` | 14 jours | Consultations de pages, signaux de pulsation, signaux indiquant qu'un appareil a été vu, télémétrie bot, consultations de promotions |
| `standard` | 30 jours | Auth, session, gameplay, bonus, affiliate, custom |
| `risk_relevant` | 90 jours | Événements de sécurité et de jeu responsable, ainsi que **tout événement mis en correspondance par une règle** |
| `monetary_or_compliance` | Conservation des transactions | Événements de paiement et de litige |

Deux règles découlent du tableau :

* Un événement qui correspond à une règle constitue une preuve : il passe automatiquement dans `risk_relevant`.
* Les événements de paiement et de litige conservent la durée de conservation des transactions. Ils n'expirent jamais selon le calendrier des événements, et les remplacements par classe ne peuvent pas la raccourcir.

Configurez, par application, des durées personnalisées pour les trois classes expirables dans **Transactions → Paramètres → Surveillance des événements** (1 à 730 jours chacune).

## Enrichissement IP

Les événements portent le même [enrichissement IP](https://docs.didit.me/fr/transaction-monitoring/ip-enrichment.md) que les transactions (pays, ASN, indicateurs VPN/proxy et de centre de données), et l'enrichissement est résolu **par adresse IP unique, jamais par événement**. Une session qui génère 200 consultations de pages depuis une même adresse ne résout cette adresse qu'une seule fois.

La télémétrie à faible valeur va plus loin : elle ne lit l'enrichissement que si un autre événement a déjà résolu cette adresse. Elle ne déclenche jamais de recherche par elle-même.

`GET /v3/events/enrichment-metrics/` renvoie le résultat, et la console affiche les mêmes chiffres au-dessus de la liste des événements :

```json theme={null}
{
  "events_ingested": 128450,
  "enrichment_lookups": 41230,
  "enrichment_cache_hits": 40118,
  "enrichment_provider_calls": 1112,
  "enrichment_skipped_low_value": 74320,
  "unique_ips_seen": 1112,
  "cache_hit_rate": 0.973,
  "unique_ip_ratio": 0.0087,
  "provider_calls_per_1k_events": 8.65,
  "period_days": 30
}
```

## Relire les événements

```bash theme={null}
curl "https://verification.didit.me/v3/events/?event_category=payment&event_category=dispute&matched_only=true" \
  -H "x-api-key: YOUR_API_KEY"
```

Filtres : `event_category`, `action_type`, `status`, `retention_class`, `subject_vendor_data`, `business_vendor_data`, `session_id`, `device_fingerprint`, `ip_address`, `game_id`, `round_id`, `affiliate_code`, `payment_reference_id`, `counterparty_vendor_data`, `matched_only`, `occurred_from`, `occurred_to`, `search`. Les filtres à valeurs multiples répètent le paramètre (`?status=A&status=B`).

### Chronologie d'un sujet

```bash theme={null}
curl "https://verification.didit.me/v3/events/subjects/acct_9931/?entity_type=company" \
  -H "x-api-key: YOUR_API_KEY"
```

Un `vendor_data` n'est unique **qu'au sein** d'un type d'entité : le même identifiant peut désigner un utilisateur et une entreprise, et Didit les traite comme deux sujets distincts. `entity_type` indique celui que vous demandez : `individual` (valeur par défaut) ou `company`. Si vous omettez ce paramètre pour un identifiant d'entreprise, vous obtenez la chronologie de la personne physique, et non les deux. Les mêmes filtres de liste s'appliquent.

`GET /v3/events/{event_uuid}/` ajoute le payload, le contexte de l'appareil, l'enrichissement IP, les signaux de risque du sujet mis en cache et chaque correspondance de règle avec ses preuves, y compris si chaque champ concerné était dérivé côté serveur, dérivé du SDK ou fourni par le client.

`DELETE /v3/events/{event_uuid}/delete/` supprime un événement. Il n'est plus renvoyé par aucune lecture, et la suppression est irréversible.

## Suite

> [card] [Règles sur les événements](https://docs.didit.me/fr/transaction-monitoring/event-rules.md)
>
> Règles de vélocité, de ratio, de séquence et de corrélation sur les données d'événements.

> [card] [Envoi d'événements via le SDK](https://docs.didit.me/fr/transaction-monitoring/sdk-event-submission.md)
>
> Capturez les événements directement depuis l'appareil avec des informations d'identification à portée limitée.


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