> ## 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 para crear eventos de monitorización

> Didit recibe desde tu backend eventos de login, juego, bonos, pagos, disputas o seguridad, y los guarda, enriquece y puntúa con tus reglas.



Prompt de la API para crear eventos de monitorización
        Copiar el prompt al portapapeles



      
      

\<pre>

\`Send one non-monetary monitoring event (login, session, gameplay, bonus, affiliate, payment, dispute, security, responsible gambling or custom) from my backend to Didit.

Endpoint:
POST https://verification.didit.me/v3/events/

Authentication:
Use the x-api-key header with my Didit API key, from my backend only. A scoped key needs transactions: write.

Goal:
\- Record what happened on my platform so Didit's event rules can score it alongside my transactions, and read the verdict from the response.

Request body (application/json):
\{
"event_id": "login-2026-10-17-000001",   // required - my id, unique per application, the idempotency key (max 128)
"event_category": "auth",                // required - auth, session, gameplay, bonus, affiliate, payment, dispute, security, responsible_gambling, custom
"action_type": "login",                  // required - what happened inside the category (max 128)
"occurred_at": "2026-10-17T09:15:02.481Z", // required - at most 7 days in the past, 5 minutes in the future
"subject": { "vendor_data": "user-42", "entity_type": "individual" }, // required - entity_type individual (default) or company
"session": { "session_id": "web-session-abc", "sequence": 142 },
"device_context": { "fingerprint": "didit-fp-v2:a8c1", "network_context": { "ip_address": "203.0.113.42" } },
"transaction_context": { "amount": "1000.00", "currency": "EUR", "payment_reference_id": "dep_735" },
"payload": { "method": "password" },     // category fields, max 16 KB
"custom_values": { "vip_tier": "gold" }  // max 100 scalar keys
}

Behavior:
\- Validated, stored, IP-enriched and evaluated by the real-time event rules before the response returns. Cross-subject and long-window rules run asynchronously within minutes (correlation_pending: true).
\- Some actions require payload keys, for example gameplay.p2p_settlement (game_id, counterparty_vendor_data, stake_amount, net_result_amount, role, and one of hand_id, round_id, match_id), payment.deposit_completed (payment_reference_id, amount, currency, payment_method, status) and dispute.chargeback_opened (payment_reference_id and one of dispute_id, chargeback_id). transaction_context keys count towards these requirements.
\- Send hashes and references, never a card number, a full withdrawal address, a password hash or an MFA secret.
\- Idempotency: the same event_id with the same event_category, action_type, occurred_at, subject.vendor_data and payload returns 200 with idempotent_replay true and the stored event's result. Different values in those fields return 409; the other fields are not compared. Retry safely on timeouts.
\- The IP address used for enrichment and rules is device_context.network_context.ip_address as you send it.
\- In a sandbox application no rules run: status is ACCEPTED and rules_evaluated_count is 0.
\- The subject resolves to the user (or company) with that vendor_data; one is created when none exists.
\- Event ingestion is opt-in: until it is switched on in Transactions > Settings > Event monitoring, this call returns 403 with code event_monitoring_disabled and stores nothing.

Example call:
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-10-17-000001","event_category":"auth","action_type":"login","occurred_at":"2026-10-17T09:15:02.481Z","subject":{"vendor_data":"user-42"},"device_context":{"network_context":{"ip_address":"203.0.113.42"}},"payload":{"method":"password"}}'

What to read from the response:
\- event_uuid - Didit id of the stored event.
\- status - ACCEPTED (stored, no rule changed it), APPROVED, IN_REVIEW or DECLINED.
\- score, rules_evaluated_count, rules_matched_count, rule_matches[] (rule_id, library_key, mode, is_async).
\- correlation_pending - when true, read GET /v3/events/{event_uuid}/ later for the final status.
\- retention_class and expires_at (null for payment and dispute events).
\- idempotent_replay - true when the event was already stored.

Failure modes:
\- 400 - validation error keyed by field (missing field, occurred_at outside the window, payload over 16 KB, nested custom_values, missing required payload keys).
\- 401 - the API key has expired.
\- 403 - missing API key (a wrong, revoked or expired key gets 401), a scoped key without transactions: write, or code event_monitoring_disabled.
\- 409 - event_id reused with different content; use a new event_id.
\- 429 - more than 300 writes per minute for this API key; honor Retry-After.

Side effects: stores the event, may create the subject's user or company, and applies the actions of matched active rules (score, status, tags, notes, list entries, cases).

For the full integration shape, see /integration/integration-prompt.`

\</pre>



      
      

Pegar en

> [!NOTE]
>
> La ingesta de eventos es opcional y debes activarla. Actívala en **Transactions > Settings > Event monitoring** antes de enviar eventos; hasta entonces, este endpoint responde `403` con `"code": "event_monitoring_disabled"`.[Ingesta de eventos](https://docs.didit.me/es/transaction-monitoring/events.md) describe el sobre, las diez categorías, las claves obligatorias del payload y las clases de retención. [Reglas de eventos](https://docs.didit.me/es/transaction-monitoring/event-rules.md) explica qué reglas se ejecutan durante la solicitud y cuáles se ejecutan de forma asíncrona. Para enviar eventos desde un navegador o una aplicación en lugar de hacerlo desde tu backend, usa el [envío de eventos desde el SDK](https://docs.didit.me/es/transaction-monitoring/sdk-event-submission.md).


## OpenAPI

````yaml es/openapi-25.json POST /v3/events/
openapi: 3.0.0
info:
  version: 3.0.0
  title: Didit Verification API
  description: API de verificación de identidad. Autentícate con el encabezado x-api-key.
servers:
  - url: https://verification.didit.me
security: []
tags: []
paths:
  /v3/events/:
    post:
      tags:
        - Monitoring Events
      summary: Crear evento de monitorización
      description: >-
        Envía desde tu backend un evento no monetario (inicio de sesión, sesión,
        juego, bono, afiliado, pago, disputa, seguridad, juego responsable o
        personalizado). El evento se valida según el contrato de su categoría,
        se almacena, se enriquece con datos de IP una vez por cada dirección
        pública única y se evalúa con tus reglas de eventos en tiempo real antes
        de que se devuelva la respuesta; las reglas que abarcan varios sujetos o
        ventanas largas se ejecutan de forma asíncrona (`correlation_pending:
        true`), y en una aplicación de sandbox no se ejecuta ninguna regla.
        `event_id` es la clave de idempotencia: el mismo `event_id` con los
        mismos `event_category`, `action_type`, `occurred_at`,
        `subject.vendor_data` y `payload` devuelve `200` con `idempotent_replay:
        true` y el resultado almacenado (los demás campos del sobre no se
        comparan), mientras que valores distintos devuelven `409`. La ingesta de
        eventos se activa por aplicación: hasta que se active, este endpoint
        devuelve `403` con `code: event_monitoring_disabled` y no almacena nada.
        Una clave de API con alcance limitado necesita `transactions: write`.
        Consulta [Ingesta de
        eventos](https://docs.didit.me/es/transaction-monitoring/events) y
        [Reglas sobre
        eventos](https://docs.didit.me/es/transaction-monitoring/event-rules);
        para enviar eventos desde un navegador o una aplicación, usa [Envío de
        eventos con el
        SDK](https://docs.didit.me/es/transaction-monitoring/sdk-event-submission).
      operationId: create_monitoring_event
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MonitoringEventCreateRequest'
            examples:
              Login:
                value:
                  event_id: login-2026-10-17-000001
                  event_category: auth
                  action_type: login
                  occurred_at: '2026-10-17T09:15:02.481Z'
                  time_zone: Europe/Madrid
                  subject:
                    vendor_data: user-42
                    entity_type: individual
                  session:
                    session_id: web-session-abc
                    sequence: 142
                  device_context:
                    fingerprint: fp-a8c1
                    network_context:
                      ip_address: 203.0.113.42
                  payload:
                    method: password
                  custom_values:
                    vip_tier: gold
              Deposit completed:
                value:
                  event_id: deposit-2026-10-17-000002
                  event_category: payment
                  action_type: deposit_completed
                  occurred_at: '2026-10-17T09:16:40Z'
                  subject:
                    vendor_data: user-42
                  transaction_context:
                    amount: '100.00'
                    currency: EUR
                    direction: inbound
                    payment_reference_id: dep_736
                  payload:
                    payment_method: card
                    status: completed
              Chargeback opened:
                value:
                  event_id: chargeback-2026-10-16-000318
                  event_category: dispute
                  action_type: chargeback_opened
                  occurred_at: '2026-10-16T14:02:11Z'
                  subject:
                    vendor_data: user-42
                  payload:
                    payment_reference_id: dep_735
                    chargeback_id: cb_5521
                    amount: '250.00'
                    currency: EUR
                    reason_code: fraud
      responses:
        '200':
          description: >-
            Reproducción idempotente: ya hay almacenado un evento con este
            `event_id` y el mismo contenido. No se ha vuelto a almacenar ni a
            evaluar nada; el cuerpo describe el evento almacenado.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MonitoringEventIngestResult'
              examples:
                Replay:
                  value:
                    event_uuid: 33333333-4444-5555-6666-777777777777
                    event_id: login-2026-10-17-000001
                    status: ACCEPTED
                    score: 0
                    rules_evaluated_count: 6
                    rules_matched_count: 0
                    correlation_pending: false
                    retention_class: standard
                    expires_at: '2026-11-16T09:15:02.481000Z'
                    idempotent_replay: true
                    rule_matches: []
        '201':
          description: El evento se almacenó y se evaluó.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MonitoringEventIngestResult'
              examples:
                Stored, no rule matched:
                  value:
                    event_uuid: 33333333-4444-5555-6666-777777777777
                    event_id: login-2026-10-17-000001
                    status: ACCEPTED
                    score: 0
                    rules_evaluated_count: 6
                    rules_matched_count: 0
                    correlation_pending: false
                    retention_class: standard
                    expires_at: '2026-11-16T09:15:02.481000Z'
                    idempotent_replay: false
                    rule_matches: []
                Rule matched, async rule pending:
                  value:
                    event_uuid: 33333333-4444-5555-6666-777777777777
                    event_id: login-2026-10-17-000001
                    status: IN_REVIEW
                    score: 40
                    rules_evaluated_count: 6
                    rules_matched_count: 1
                    correlation_pending: true
                    retention_class: risk_relevant
                    expires_at: '2027-01-15T09:15:02.481000Z'
                    idempotent_replay: false
                    rule_matches:
                      - rule_id: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
                        library_key: null
                        mode: ACTIVE
                        is_async: false
        '400':
          description: >-
            La validación ha fallado. El cuerpo se agrupa por campo; los campos
            anidados son objetos anidados. No se guarda nada.
          content:
            application/json:
              examples:
                Missing fields:
                  value:
                    event_id:
                      - This field is required.
                    subject:
                      - This field is required.
                Unknown category:
                  value:
                    event_category:
                      - '"login" is not a valid choice.'
                occurred_at too old:
                  value:
                    occurred_at:
                      - >-
                        occurred_at is more than 7 days in the past. Use the
                        batch import lane for backfills.
                occurred_at in the future:
                  value:
                    occurred_at:
                      - occurred_at is more than 5 minutes in the future.
                Missing subject vendor_data:
                  value:
                    subject:
                      vendor_data:
                        - This field is required.
                Missing required payload keys:
                  value:
                    payload:
                      - >-
                        payment.deposit_completed requires: payment_method,
                        status.
                Missing one-of payload key:
                  value:
                    payload:
                      - >-
                        dispute.chargeback_opened requires one of: dispute_id,
                        chargeback_id.
                Security change without changed_field:
                  value:
                    payload:
                      - security.*_changed requires 'changed_field'.
                Payload too large:
                  value:
                    payload:
                      - >-
                        payload exceeds 16384 bytes. Summarise telemetry
                        client-side.
                Too many custom_values:
                  value:
                    custom_values:
                      - custom_values accepts at most 100 keys.
                Nested custom value:
                  value:
                    custom_values:
                      - >-
                        custom_values['limits'] must be a scalar - rule
                        conditions cannot address nested values.
        '401':
          description: >-
            La clave de API con alcance limitado ha expirado. Solo una clave
            expirada recibe `401`; una clave ausente o no válida recibe `403`.
          content:
            application/json:
              examples:
                Expired key:
                  value:
                    detail: This API key has expired.
        '403':
          description: >-
            Falta `x-api-key` (una clave incorrecta, revocada o expirada recibe
            `401`), una clave con permisos limitados sin `transactions: write`,
            una clave limitada a algunos flujos o a sesiones aprobadas (una
            clave así nunca accede a los datos de monitorización de
            transacciones), o una solicitud desde fuera de la lista de IP
            permitidas de la clave. También se devuelve con `code:
            event_monitoring_disabled` mientras la ingesta de eventos está
            desactivada para la aplicación; en ese caso no se almacena nada, y
            la comprobación se ejecuta antes de validar el cuerpo.
          content:
            application/json:
              examples:
                Event monitoring disabled:
                  value:
                    detail: >-
                      Event monitoring is not enabled for this application. Turn
                      on event ingestion in the transaction monitoring settings
                      before submitting events.
                    code: event_monitoring_disabled
                Missing or invalid API key:
                  value:
                    detail: You do not have permission to perform this action.
                Scoped key without access:
                  value:
                    detail: This API key has no write access to transactions.
                Key limited to workflows or approved sessions:
                  value:
                    detail: >-
                      This API key only reaches sessions inside its workflow or
                      status limits, so it can't use this endpoint.
                IP not allowed:
                  value:
                    detail: This API key can't be used from this IP address.
        '409':
          description: >-
            `event_id` ya se usó para un evento con contenido diferente
            (categoría, tipo de acción, `occurred_at`, `vendor_data` del sujeto
            o payload). Envía el evento con un nuevo `event_id`.
          content:
            application/json:
              examples:
                event_id reused:
                  value:
                    event_id: >-
                      event_id 'login-2026-10-17-000001' already exists with a
                      different payload.
        '429':
          description: >-
            Límite de solicitudes superado: las solicitudes de escritura
            (`POST`, `PATCH`, `DELETE`) comparten un cupo de 300 solicitudes por
            minuto por clave de API. Espera `Retry-After` segundos y vuelve a
            intentarlo.
          headers:
            Retry-After:
              description: Segundos que hay que esperar antes de reintentar.
              schema:
                type: integer
                minimum: 1
                example: 30
          content:
            application/json:
              examples:
                Throttled:
                  value:
                    detail: >-
                      Write request rate limit exceeded. You can make up to 300
                      requests per minute.
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: curl
          label: curl
          source: |-
            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-10-17-000001",
                "event_category": "auth",
                "action_type": "login",
                "occurred_at": "2026-10-17T09:15:02.481Z",
                "subject": {"vendor_data": "user-42", "entity_type": "individual"},
                "session": {"session_id": "web-session-abc", "sequence": 142},
                "device_context": {
                  "fingerprint": "fp-a8c1",
                  "network_context": {"ip_address": "203.0.113.42"}
                },
                "payload": {"method": "password"}
              }'
        - lang: python
          label: Python
          source: |-
            from didit import Didit

            # Reads DIDIT_API_KEY.
            client = Didit()

            result = client.monitoring_events.create(
                event_id="login-2026-10-17-000001",
                event_category="auth",
                action_type="login",
                occurred_at="2026-10-17T09:15:02.481Z",
                time_zone="Europe/Madrid",
                subject={
                    "vendor_data": "user-42",
                    "entity_type": "individual",
                },
                session={
                    "session_id": "web-session-abc",
                    "sequence": 142,
                },
                device_context={
                    "fingerprint": "fp-a8c1",
                    "network_context": {
                        "ip_address": "203.0.113.42",
                    },
                },
                payload={"method": "password"},
                custom_values={"vip_tier": "gold"},
            )
            print(result)
        - lang: javascript
          label: Node.js
          source: |-
            import Didit from "@didit-protocol/sdk-node";

            // Reads DIDIT_API_KEY.
            const didit = new Didit();

            const result = await didit.monitoringEvents.create({
              event_id: "login-2026-10-17-000001",
              event_category: "auth",
              action_type: "login",
              occurred_at: "2026-10-17T09:15:02.481Z",
              time_zone: "Europe/Madrid",
              subject: {
                vendor_data: "user-42",
                entity_type: "individual",
              },
              session: {
                session_id: "web-session-abc",
                sequence: 142,
              },
              device_context: {
                fingerprint: "fp-a8c1",
                network_context: {
                  ip_address: "203.0.113.42",
                },
              },
              payload: { method: "password" },
              custom_values: { vip_tier: "gold" },
            });
            console.log(result);
        - lang: go
          label: Go
          source: "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.MonitoringEvents.Create(ctx, didit.MonitoringEventCreateRequest{\n\tEventID:       \"login-2026-10-17-000001\",\n\tEventCategory: \"auth\",\n\tActionType:    \"login\",\n\tOccurredAt:    time.Date(2026, 10, 17, 9, 15, 2, 0, time.UTC),\n\tTimeZone:      didit.String(\"Europe/Madrid\"),\n\tSubject: didit.MonitoringEventCreateRequestSubject{\n\t\tVendorData: \"user-42\",\n\t\tEntityType: didit.String(\"individual\"),\n\t},\n\tSession: didit.Some(didit.MonitoringEventCreateRequestSession{\n\t\tSessionID: didit.String(\"web-session-abc\"),\n\t\tSequence:  didit.Int(142),\n\t}),\n\tDeviceContext: didit.Some(didit.MonitoringEventCreateRequestDeviceContext{\n\t\tFingerprint: didit.String(\"fp-a8c1\"),\n\t\tNetworkContext: didit.Some(didit.MonitoringEventCreateRequestDeviceContextNetworkContext{\n\t\t\tIPAddress: didit.String(\"203.0.113.42\"),\n\t\t}),\n\t}),\n\tPayload:      didit.Some(map[string]any{\"method\": \"password\"}),\n\tCustomValues: didit.Some(map[string]any{\"vip_tier\": \"gold\"}),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
        - lang: java
          label: Java
          source: >-
            import java.time.OffsetDateTime;

            import java.util.Map;

            import me.didit.Didit;

            import me.didit.types.MonitoringEventCreateRequest;


            // Reads DIDIT_API_KEY.

            Didit client = new Didit();


            var result =
            client.monitoringEvents().create(MonitoringEventCreateRequest.builder()
                    .eventId("login-2026-10-17-000001")
                    .eventCategory(MonitoringEventCreateRequest.EventCategory.of("auth"))
                    .actionType("login")
                    .occurredAt(OffsetDateTime.parse("2026-10-17T09:15:02.481Z"))
                    .timeZone("Europe/Madrid")
                    .subject(MonitoringEventCreateRequest.Subject.builder()
                            .vendorData("user-42")
                            .entityType("individual")
                            .build())
                    .session(MonitoringEventCreateRequest.Session.builder()
                            .sessionId("web-session-abc")
                            .sequence(142L)
                            .build())
                    .deviceContext(MonitoringEventCreateRequest.DeviceContext.builder()
                            .fingerprint("fp-a8c1")
                            .networkContext(MonitoringEventCreateRequest.DeviceContext.NetworkContext.builder()
                                    .ipAddress("203.0.113.42")
                                    .build())
                            .build())
                    .payload(Map.of("method", "password"))
                    .customValues(Map.of("vip_tier", MonitoringEventCreateRequest.CustomValuesValue.ofString("gold")))
                    .build());
            System.out.println(result);
        - lang: php
          label: PHP
          source: |-
            <?php

            require 'vendor/autoload.php';

            use Didit\DiditClient;

            // Reads DIDIT_API_KEY.
            $didit = new DiditClient();

            $result = $didit->monitoringEvents->create([
                'event_id' => 'login-2026-10-17-000001',
                'event_category' => 'auth',
                'action_type' => 'login',
                'occurred_at' => '2026-10-17T09:15:02.481Z',
                'time_zone' => 'Europe/Madrid',
                'subject' => [
                    'vendor_data' => 'user-42',
                    'entity_type' => 'individual',
                ],
                'session' => [
                    'session_id' => 'web-session-abc',
                    'sequence' => 142,
                ],
                'device_context' => [
                    'fingerprint' => 'fp-a8c1',
                    'network_context' => [
                        'ip_address' => '203.0.113.42',
                    ],
                ],
                'payload' => ['method' => 'password'],
                'custom_values' => ['vip_tier' => 'gold'],
            ]);
            print_r($result->toArray());
        - lang: ruby
          label: Ruby
          source: |-
            require "didit"

            # Reads DIDIT_API_KEY.
            didit = Didit::Client.new

            result = didit.monitoring_events.create(
              event_id: "login-2026-10-17-000001",
              event_category: "auth",
              action_type: "login",
              occurred_at: "2026-10-17T09:15:02.481Z",
              time_zone: "Europe/Madrid",
              subject: {
                vendor_data: "user-42",
                entity_type: "individual",
              },
              session: {
                session_id: "web-session-abc",
                sequence: 142,
              },
              device_context: {
                fingerprint: "fp-a8c1",
                network_context: {
                  ip_address: "203.0.113.42",
                },
              },
              payload: { method: "password" },
              custom_values: { vip_tier: "gold" }
            )
            puts result.to_h
        - lang: csharp
          label: .NET
          source: >-
            using System;

            using System.Collections.Generic;

            using System.Text.Json;

            using Didit;


            // Reads DIDIT_API_KEY.

            using var client = new DiditClient();


            var result = await client.MonitoringEvents.CreateAsync(new
            MonitoringEventCreateRequest

            {
                EventId = "login-2026-10-17-000001",
                EventCategory = "auth",
                ActionType = "login",
                OccurredAt = DateTimeOffset.Parse("2026-10-17T09:15:02.481Z"),
                TimeZone = "Europe/Madrid",
                Subject = new()
                {
                    VendorData = "user-42",
                    EntityType = "individual",
                },
                Session = new MonitoringEventCreateRequestSession
                {
                    SessionId = "web-session-abc",
                    Sequence = 142,
                },
                DeviceContext = new MonitoringEventCreateRequestDeviceContext
                {
                    Fingerprint = "fp-a8c1",
                    NetworkContext = new MonitoringEventCreateRequestDeviceContextNetworkContext
                    {
                        IpAddress = "203.0.113.42",
                    },
                },
                Payload = new Dictionary<string, object> { ["method"] = "password" },
                CustomValues = new Dictionary<string, object> { ["vip_tier"] = "gold" },
            });

            Console.WriteLine(JsonSerializer.Serialize(result));
components:
  schemas:
    MonitoringEventCreateRequest:
      type: object
      description: >-
        El sobre del evento, igual para todas las categorías. Se aceptan alias
        en camelCase: `eventId`, `eventCategory` (o `category`), `actionType`,
        `occurredAt`, `timeZone` (o `zoneId`), `deviceContext` (o `device`),
        `transactionContext`, `customValues` (o `props`); dentro de `subject`:
        `vendorData`, `entityType`, `fullName`; dentro de `session`:
        `sessionId`, `pageUrl`; dentro de `transaction_context`:
        `paymentReferenceId`.
      required:
        - event_id
        - event_category
        - action_type
        - occurred_at
        - subject
      properties:
        event_id:
          type: string
          maxLength: 128
          description: >-
            Tu identificador para el evento, único por aplicación. Es la clave
            de idempotencia: reenviar los mismos `event_category`,
            `action_type`, `occurred_at`, `subject.vendor_data` y `payload` con
            este identificador es una repetición; cualquier diferencia es un
            conflicto.
          example: login-2026-10-17-000001
        event_category:
          type: string
          enum:
            - auth
            - session
            - gameplay
            - bonus
            - affiliate
            - payment
            - dispute
            - security
            - responsible_gambling
            - custom
          description: Categoría del evento.
          example: auth
        action_type:
          type: string
          minLength: 1
          maxLength: 128
          description: >-
            Qué ocurrió dentro de la categoría. Vocabulario abierto; las
            acciones gestionadas que se indican en [Ingesta de
            eventos](https://docs.didit.me/es/transaction-monitoring/events)
            (por ejemplo, `login`, `deposit_completed`, `chargeback_opened`)
            habilitan la validación tipada y los campos de regla gestionados. Se
            eliminan los espacios en blanco iniciales y finales.
          example: login
        occurred_at:
          type: string
          format: date-time
          description: >-
            Cuándo ocurrió el evento en tu lado, en ISO 8601 (un valor sin
            desfase se interpreta como UTC). No puede ser de hace más de 7 días
            ni de más de 5 minutos en el futuro.
          example: '2026-10-17T09:15:02.481Z'
        time_zone:
          type: string
          nullable: true
          maxLength: 64
          description: >-
            Zona horaria del suceso en tu lado, por ejemplo `Europe/Madrid`. Se
            almacena con el evento; los endpoints de lectura no la devuelven.
        subject:
          type: object
          description: >-
            El usuario o la empresa a la que pertenece el evento. Se resuelve al
            usuario (o empresa) con este `vendor_data` en tu aplicación; se crea
            uno cuando no existe ninguno.
          required:
            - vendor_data
          properties:
            vendor_data:
              type: string
              minLength: 1
              maxLength: 255
              description: Tu ID para el sujeto.
              example: user-42
            entity_type:
              type: string
              maxLength: 32
              default: individual
              description: >-
                `company` resuelve el sujeto como empresa; cualquier otro valor
                (por defecto, `individual`) lo resuelve como persona física. El
                mismo `vendor_data` puede designar uno de cada tipo.
              example: individual
            full_name:
              type: string
              nullable: true
              maxLength: 512
              description: >-
                Nombre visible, que solo se usa cuando este evento crea el
                usuario o la empresa.
            email:
              type: string
              format: email
              nullable: true
              description: >-
                Se valida como dirección de correo electrónico; no se almacena
                en el evento.
            phone:
              type: string
              nullable: true
              maxLength: 32
              description: Se valida; no se almacena en el evento.
            country:
              type: string
              nullable: true
              maxLength: 3
              description: Se valida; no se almacena en el evento.
        business:
          type: object
          description: >-
            La empresa a la que pertenece el evento, cuando es distinta del
            sujeto. Solo se lee `vendor_data`.
          additionalProperties: true
          properties:
            vendor_data:
              type: string
              maxLength: 255
              description: >-
                Tu ID para la empresa. Se puede filtrar como
                `business_vendor_data`.
              example: merchant-7
        session:
          type: object
          description: El contexto de tu sesión para el evento.
          properties:
            session_id:
              type: string
              nullable: true
              maxLength: 255
              description: >-
                Tu identificador de sesión. Se puede filtrar y se devuelve como
                `session_id`.
            sequence:
              type: integer
              nullable: true
              description: >-
                Posición del evento dentro de la sesión. Se devuelve como
                `session_sequence`.
            page_url:
              type: string
              nullable: true
              maxLength: 2048
              description: Se valida; no se almacena en el evento.
            referrer:
              type: string
              nullable: true
              maxLength: 2048
              description: Se valida; no se almacena en el evento.
        device_context:
          type: object
          additionalProperties: true
          description: >-
            Contexto de dispositivo y red. Se almacena tal como se envía y lo
            devuelve `GET /v3/events/{event_uuid}/`. En este canal de servidor,
            Didit no ve la conexión del usuario final. Por eso, la IP que se
            enriquece y que usan las reglas es `network_context.ip_address`, tal
            como la envías.
          properties:
            fingerprint:
              type: string
              maxLength: 255
              description: >-
                Huella digital del dispositivo. Se puede filtrar como
                `device_fingerprint`.
            persistent_device_id:
              type: string
              maxLength: 255
              description: Tu identificador persistente del dispositivo.
            bot_score:
              type: integer
              description: >-
                Puntuación de bot de tu propio sistema de detección, como número
                entero.
            network_context:
              type: object
              additionalProperties: true
              properties:
                ip_address:
                  type: string
                  maxLength: 64
                  description: >-
                    Dirección IP del usuario final. Las direcciones públicas se
                    enriquecen una vez por cada dirección única.
                  example: 203.0.113.42
        transaction_context:
          type: object
          description: >-
            Contexto monetario. Los valores no vacíos de este campo también
            cumplen las claves obligatorias del payload de la acción.
          properties:
            amount:
              type: string
              nullable: true
              description: Importe como cadena decimal (también se acepta un número).
              example: '1000.00'
            currency:
              type: string
              nullable: true
              maxLength: 10
              description: Código de moneda.
            direction:
              type: string
              nullable: true
              maxLength: 16
              description: >-
                Sentido del movimiento de dinero, por ejemplo `inbound` u
                `outbound`.
            payment_reference_id:
              type: string
              nullable: true
              maxLength: 255
              description: >-
                Tu referencia de pago. Se puede filtrar como
                `payment_reference_id`.
        payload:
          type: object
          additionalProperties: true
          description: >-
            Los campos de dominio de la categoría, como máximo 16384 bytes una
            vez codificados en JSON. Algunas acciones requieren claves (en
            `payload` o `transaction_context`): `gameplay.p2p_settlement`
            necesita `game_id`, `counterparty_vendor_data`, `stake_amount`,
            `net_result_amount`, `role` y uno de `hand_id`, `round_id`,
            `match_id`; `gameplay.bet_placed` y `gameplay.bet_settled` necesitan
            `game_id`; `payment.deposit_initiated`, `payment.deposit_completed`,
            `payment.withdrawal_requested` y `payment.withdrawal_completed`
            necesitan `payment_reference_id`, `amount`, `currency`,
            `payment_method`, `status`; `payment.withdrawal_address_changed`
            necesita `withdrawal_address_hash`; `dispute.chargeback_opened`,
            `dispute.chargeback_won` y `dispute.chargeback_lost` necesitan
            `payment_reference_id` y uno de `dispute_id`, `chargeback_id`;
            `session.bot_signal_observed` necesita `telemetry_schema_version` y
            uno de `bot_score`, `actions_per_minute`, `timing_variance_ms`,
            `pointer_entropy`, `keystroke_entropy`, `reaction_time_ms_p50`;
            `responsible_gambling.self_exclusion_match` necesita
            `registry_source`, `exclusion_status`, `identity_match_ref`. Toda
            acción `security` que termina en `_changed` necesita
            `changed_field`, además de `previous_reference_hash` o
            `new_reference_hash` cuando el campo es `password`, `mfa_method`,
            `mfa`, `email`, `phone`, `withdrawal_address`, `payout_method` o
            `api_key`. Envía hashes y referencias, nunca un número de tarjeta,
            una dirección de retiro completa, un hash de contraseña ni un
            secreto MFA.
        custom_values:
          type: object
          description: >-
            Hasta 100 claves propias, accesibles desde las reglas como
            `custom_values.<key>`. Los valores deben ser escalares (cadena,
            número, booleano o null); los objetos y arrays anidados se rechazan.
          additionalProperties:
            nullable: true
            oneOf:
              - type: string
              - type: number
              - type: boolean
      example:
        event_id: login-2026-10-17-000001
        event_category: auth
        action_type: login
        occurred_at: '2026-10-17T09:15:02.481Z'
        time_zone: Europe/Madrid
        subject:
          vendor_data: user-42
          entity_type: individual
        session:
          session_id: web-session-abc
          sequence: 142
        device_context:
          fingerprint: fp-a8c1
          network_context:
            ip_address: 203.0.113.42
        payload:
          method: password
        custom_values:
          vip_tier: gold
    MonitoringEventIngestResult:
      type: object
      description: >-
        Resultado de la ingesta de un evento. Se devuelve la misma estructura
        para un evento nuevo y para una repetición idempotente.
      required:
        - event_uuid
        - event_id
        - status
        - score
        - rules_evaluated_count
        - rules_matched_count
        - correlation_pending
        - retention_class
        - expires_at
        - idempotent_replay
        - rule_matches
      properties:
        event_uuid:
          type: string
          format: uuid
          description: Identificador de Didit del evento almacenado.
        event_id:
          type: string
          description: Tu `event_id`.
        status:
          type: string
          enum:
            - ACCEPTED
            - APPROVED
            - IN_REVIEW
            - DECLINED
          description: >-
            Estado después de ejecutar las reglas en tiempo real. Consulta
            `MonitoringEvent.status`.
        score:
          type: integer
          description: Puntuación después de ejecutar las reglas en tiempo real.
        rules_evaluated_count:
          type: integer
          minimum: 0
          description: >-
            Número de reglas de eventos evaluadas en la solicitud. 0 en una
            aplicación de sandbox, donde no se ejecuta ninguna regla.
        rules_matched_count:
          type: integer
          minimum: 0
          description: >-
            Número de reglas que coincidieron, incluidas las reglas en modo
            `TEST`.
        correlation_pending:
          type: boolean
          description: >-
            `true` cuando todavía falta ejecutar una regla asíncrona. Consulta
            `GET /v3/events/{event_uuid}/` unos minutos después para obtener el
            `status` y el `score` finales.
        retention_class:
          type: string
          enum:
            - low_value
            - standard
            - risk_relevant
            - monetary_or_compliance
          description: >-
            Clase de retención, tras cualquier promoción por una regla
            coincidente.
        expires_at:
          type: string
          format: date-time
          nullable: true
          description: >-
            Cuándo expira el evento según su clase de retención y se elimina.
            Nulo para los eventos `monetary_or_compliance` (pagos y disputas).
        idempotent_replay:
          type: boolean
          description: >-
            `true` cuando ya se había almacenado un evento con este `event_id` y
            el mismo contenido; los valores son los del evento almacenado y no
            se volvió a ejecutar ninguna regla.
        rule_matches:
          type: array
          description: Reglas que coincidieron con el evento.
          items:
            type: object
            required:
              - rule_id
              - library_key
              - mode
              - is_async
            properties:
              rule_id:
                type: string
                format: uuid
                description: UUID de la regla.
              library_key:
                type: string
                nullable: true
                description: >-
                  Clave de la biblioteca cuando la regla se instaló desde la
                  biblioteca de reglas; en caso contrario, null.
              mode:
                type: string
                enum:
                  - ACTIVE
                  - TEST
                description: >-
                  Las reglas `TEST` registran la coincidencia, pero no aplican
                  ninguna acción.
              is_async:
                type: boolean
                description: '`true` cuando la coincidencia procede de la pasada asíncrona.'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        La clave de API de tu aplicación, que encontrarás en Developers -> API
        keys en la Business Console. La clave principal tiene acceso completo.
        Una clave con nombre puede tener un alcance limitado: ninguno, lectura o
        escritura por recurso, limitada a algunos flujos o a sesiones aprobadas,
        a una lista de direcciones IP y a una fecha de caducidad. 401 significa
        que la clave es incorrecta, se revocó o expiró; 403 significa que no se
        envió ninguna clave, que la clave no tiene acceso a este recurso o
        acción, o que la solicitud provino de una dirección fuera de su lista de
        IP; 404 en una ruta de sesión significa que la sesión está fuera de los
        flujos o estados de la clave. Una clave sin acceso a contenido
        multimedia recibe las URL de imágenes, videos y PDF como null, y una
        clave sin permiso de escritura en sesiones recibe los enlaces y tokens
        de sesión como null. Consulta https://docs.didit.me/console/api-keys.

````

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