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

> 백엔드에서 로그인, 게임플레이, 보너스, 결제, 분쟁 또는 보안 이벤트 하나를 Didit으로 전송하면 저장, 보강 후 이벤트 규칙에 따라 점수가 산정됩니다.



모니터링 이벤트 생성 API 프롬프트
        프롬프트를 클립보드에 복사



      
      

\<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 600 ingestion requests per minute for this API key (event and transaction ingestion share this budget, apart from the 300 of every other write); 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>



      
      

붙여넣을 곳

> [!NOTE]
>
> 이벤트 수집은 옵트인 방식입니다. 이벤트를 전송하기 전에 **Transactions > Settings > Event monitoring**에서 기능을 켜십시오. 그전까지 이 endpoint는 `"code": "event_monitoring_disabled"`와 함께 `403`을 반환합니다.[이벤트 수집](https://docs.didit.me/ko/transaction-monitoring/events.md)에서는 엔벨로프, 10개 카테고리, 필수 payload 키, 보존 등급을 다룹니다. [이벤트 규칙](https://docs.didit.me/ko/transaction-monitoring/event-rules.md)에서는 요청 중에 실행되는 규칙과 비동기로 실행되는 규칙을 설명합니다. 백엔드 대신 브라우저나 앱에서 이벤트를 보내려면 [SDK 이벤트 제출](https://docs.didit.me/ko/transaction-monitoring/sdk-event-submission.md)을 사용하십시오.


## OpenAPI

````yaml ko/openapi-25.json POST /v3/events/
openapi: 3.0.0
info:
  version: 3.0.0
  title: Didit Verification API
  description: 신분증 인증 API입니다. x-api-key 헤더로 인증합니다.
servers:
  - url: https://verification.didit.me
security: []
tags: []
paths:
  /v3/events/:
    post:
      tags:
        - Monitoring Events
      summary: 모니터링 이벤트 생성
      description: >-
        백엔드에서 비금전적 이벤트(로그인, 세션, 게임플레이, 보너스, 제휴사, 결제, 분쟁, 보안, 책임감 있는 도박 또는 커스텀)를
        전송합니다. 이벤트는 해당 카테고리 계약에 대해 유효성이 검사되고, 저장되며, 고유한 공용 주소당 한 번씩 IP 보강이 수행되고,
        응답이 반환되기 전에 실시간 이벤트 규칙에 의해 평가됩니다. 주체 간 규칙 및 긴 윈도우 규칙은 비동기식으로
        실행되며(`correlation_pending: true`), 샌드박스 애플리케이션에서는 규칙이 실행되지 않습니다.
        `event_id`는 멱등성 키입니다. 동일한 `event_category`, `action_type`,
        `occurred_at`, `subject.vendor_data`, `payload`를 가진 동일한 `event_id`는
        `idempotent_replay: true` 및 저장된 결과와 함께 `200`을 반환하고(다른 엔벨로프 필드는 비교되지 않음),
        다른 값은 `409`를 반환합니다. 이벤트 수집은 애플리케이션별로 활성화(opt-in)됩니다. 활성화될 때까지 이
        endpoint는 `code: event_monitoring_disabled`와 함께 `403`을 반환하고 아무것도 저장하지
        않습니다. 범위가 지정된 API 키에는 `transactions: write`가 필요합니다. [이벤트
        수집](https://docs.didit.me/ko/transaction-monitoring/events) 및 [이벤트
        규칙](https://docs.didit.me/ko/transaction-monitoring/event-rules)을
        참조하십시오. 브라우저나 앱에서 이벤트를 전송하려면 [SDK 이벤트
        제출](https://docs.didit.me/ko/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: >-
            멱등 재생: 이 `event_id` 및 동일한 내용을 가진 이벤트가 이미 저장되어 있습니다. 아무것도 다시 저장되거나
            평가되지 않았으며 본문은 저장된 이벤트를 설명합니다.
          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: 이벤트가 저장되고 평가되었습니다.
          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: 검증 실패. 본문은 필드별 키로 구성되며, 중첩된 필드는 중첩 객체입니다. 아무것도 저장되지 않습니다.
          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: >-
            스코프가 지정된 API 키가 만료되었습니다. 만료된 키에 대해서만 `401`이 반환되며, 누락되었거나 유효하지 않은 키에는
            `403`이 반환됩니다.
          content:
            application/json:
              examples:
                Expired key:
                  value:
                    detail: This API key has expired.
        '403':
          description: >-
            `x-api-key`가 누락되었거나(잘못되었거나 취소되었거나 만료된 키에는 `401`이 반환됨),
            `transactions: write` 권한이 없는 범위 제한 키이거나, 특정 워크플로 또는 승인된 세션으로 제한된
            키이거나(이러한 키는 거래 모니터링 데이터에 절대 접근할 수 없음), 키의 IP 허용 목록 외부에서 발생한 요청입니다.
            애플리케이션의 이벤트 수집이 비활성화된 동안 `code: event_monitoring_disabled`와 함께 반환되기도
            합니다. 이 경우 아무것도 저장되지 않으며, 검사는 본문 검증 전에 실행됩니다.
          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`가 다른 콘텐츠(카테고리, 작업 유형, `occurred_at`, 대상 `vendor_data` 또는
            payload)를 가진 이벤트에 이미 사용되었습니다. 새 `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: >-
            속도 제한 초과: 거래 생성 및 이벤트 수집(`POST /v3/transactions/`, `POST
            /v3/events/`, `POST /v3/events/batch/`)은 다른 모든 쓰기 요청이 공유하는 300개와
            별도로, API 키당 분당 600개의 요청 한도를 공유합니다. `Retry-After`초 동안 대기한 후 재시도하세요.
          headers:
            Retry-After:
              description: 재시도가 다음 기간에 이루어지도록 올림 처리한 재시도 대기 시간(초).
              schema:
                type: integer
                minimum: 1
                example: 30
          content:
            application/json:
              examples:
                Throttled:
                  value:
                    detail: >-
                      Ingestion rate limit exceeded. You can make up to 600
                      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: >-
        모든 카테고리에 동일하게 적용되는 이벤트 엔벨로프입니다. camelCase 별칭도 허용됩니다: `eventId`,
        `eventCategory`(또는 `category`), `actionType`, `occurredAt`,
        `timeZone`(또는 `zoneId`), `deviceContext`(또는 `device`),
        `transactionContext`, `customValues`(또는 `props`). `subject` 내부:
        `vendorData`, `entityType`, `fullName`. `session` 내부: `sessionId`,
        `pageUrl`. `transaction_context` 내부: `paymentReferenceId`.
      required:
        - event_id
        - event_category
        - action_type
        - occurred_at
        - subject
      properties:
        event_id:
          type: string
          maxLength: 128
          description: >-
            애플리케이션별로 고유한 이벤트 식별자입니다. 멱등성 키 역할을 합니다. 동일한 키로 동일한 `event_category`,
            `action_type`, `occurred_at`, `subject.vendor_data`, `payload`를 다시
            전송하면 재전송으로 처리되며, 다른 내용이 전송되면 충돌이 발생합니다.
          example: login-2026-10-17-000001
        event_category:
          type: string
          enum:
            - auth
            - session
            - gameplay
            - bonus
            - affiliate
            - payment
            - dispute
            - security
            - responsible_gambling
            - custom
          description: 이벤트 카테고리입니다.
          example: auth
        action_type:
          type: string
          minLength: 1
          maxLength: 128
          description: >-
            카테고리 내에서 발생한 내용입니다. 개방형 어휘이며, [이벤트
            수집](https://docs.didit.me/ko/transaction-monitoring/events)에 나열된 관리형
            작업(예: `login`, `deposit_completed`, `chargeback_opened`)을 사용하면 형식화된
            검증 및 관리형 규칙 필드가 활성화됩니다. 앞뒤 공백은 제거됩니다.
          example: login
        occurred_at:
          type: string
          format: date-time
          description: >-
            귀하 측에서 이벤트가 발생한 시점, ISO 8601(오프셋이 없는 값은 UTC로 해석됨) 형식입니다. 과거 7일 이내,
            미래 5분 이내여야 합니다.
          example: '2026-10-17T09:15:02.481Z'
        time_zone:
          type: string
          nullable: true
          maxLength: 64
          description: >-
            귀사 측에서 발생한 시점의 시간대(예: `Europe/Madrid`)입니다. 이벤트와 함께 저장되며, 조회
            endpoint에서는 반환되지 않습니다.
        subject:
          type: object
          description: >-
            이벤트가 속한 사용자 또는 기업입니다. 애플리케이션에서 해당 `vendor_data`를 가진 사용자(또는 기업)로
            확인되며, 없는 경우 새로 생성됩니다.
          required:
            - vendor_data
          properties:
            vendor_data:
              type: string
              minLength: 1
              maxLength: 255
              description: 대상에 대한 귀하의 id입니다.
              example: user-42
            entity_type:
              type: string
              maxLength: 32
              default: individual
              description: >-
                `company`는 대상을 기업으로 확인합니다. 다른 값(기본값 `individual`)은 개인으로 확인합니다.
                동일한 `vendor_data`로 각각 하나씩 지정할 수 있습니다.
              example: individual
            full_name:
              type: string
              nullable: true
              maxLength: 512
              description: 표시 이름이며, 이 이벤트로 사용자 또는 기업을 생성할 때만 사용됩니다.
            email:
              type: string
              format: email
              nullable: true
              description: 이메일 주소로서 유효성이 검증되었습니다. 이벤트에 저장되지 않습니다.
            phone:
              type: string
              nullable: true
              maxLength: 32
              description: 검증되었습니다. 이벤트에 저장되지 않습니다.
            country:
              type: string
              nullable: true
              maxLength: 3
              description: 검증되었습니다. 이벤트에 저장되지 않습니다.
        business:
          type: object
          description: 이벤트가 속한 기업입니다(대상과 다른 경우). `vendor_data`만 읽습니다.
          additionalProperties: true
          properties:
            vendor_data:
              type: string
              maxLength: 255
              description: 기업에 대한 귀하의 id입니다. `business_vendor_data`로 필터링할 수 있습니다.
              example: merchant-7
        session:
          type: object
          description: 이벤트에 대한 귀하의 세션 컨텍스트입니다.
          properties:
            session_id:
              type: string
              nullable: true
              maxLength: 255
              description: 귀하의 세션 식별자입니다. 필터링 가능하며 `session_id`로 반환됩니다.
            sequence:
              type: integer
              nullable: true
              description: 세션 내 이벤트의 위치입니다. `session_sequence`로 반환됩니다.
            page_url:
              type: string
              nullable: true
              maxLength: 2048
              description: 검증되었습니다. 이벤트에 저장되지 않습니다.
            referrer:
              type: string
              nullable: true
              maxLength: 2048
              description: 검증되었습니다. 이벤트에 저장되지 않습니다.
        device_context:
          type: object
          additionalProperties: true
          description: >-
            전송된 그대로 저장되고 `GET /v3/events/{event_uuid}/`에 의해 반환되는 기기 및 네트워크
            컨텍스트입니다. 이 서버 레인에서는 Didit이 최종 사용자의 연결을 직접 확인하지 않으므로, 규칙에서 보강되고 사용되는
            IP는 직접 전송한 `network_context.ip_address`입니다.
          properties:
            fingerprint:
              type: string
              maxLength: 255
              description: 기기 핑거프린트입니다. `device_fingerprint`로 필터링할 수 있습니다.
            persistent_device_id:
              type: string
              maxLength: 255
              description: 귀하의 영구 기기 식별자입니다.
            bot_score:
              type: integer
              description: 자체 감지 기능에서 산출된 봇 점수(정수)입니다.
            network_context:
              type: object
              additionalProperties: true
              properties:
                ip_address:
                  type: string
                  maxLength: 64
                  description: 최종 사용자의 IP 주소입니다. 공용 주소는 고유 주소당 한 번씩 보강됩니다.
                  example: 203.0.113.42
        transaction_context:
          type: object
          description: 금액 컨텍스트입니다. 여기에 비어 있지 않은 값이 있으면 작업의 필수 payload 키도 충족됩니다.
          properties:
            amount:
              type: string
              nullable: true
              description: 십진수 문자열 형태의 금액입니다(숫자도 허용됨).
              example: '1000.00'
            currency:
              type: string
              nullable: true
              maxLength: 10
              description: 통화 코드입니다.
            direction:
              type: string
              nullable: true
              maxLength: 16
              description: '자금 이동의 방향입니다(예: `inbound` 또는 `outbound`).'
            payment_reference_id:
              type: string
              nullable: true
              maxLength: 255
              description: 귀하의 결제 참조값입니다. `payment_reference_id`로 필터링할 수 있습니다.
        payload:
          type: object
          additionalProperties: true
          description: >-
            JSON 인코딩 시 최대 16384바이트인 카테고리의 도메인 필드입니다. 일부 작업에는 키(`payload` 또는
            `transaction_context`)가 필요합니다: `gameplay.p2p_settlement`에는
            `game_id`, `counterparty_vendor_data`, `stake_amount`,
            `net_result_amount`, `role` 및 `hand_id`, `round_id`, `match_id` 중
            하나가 필요합니다. `gameplay.bet_placed` 및 `gameplay.bet_settled`에는
            `game_id`가 필요합니다. `payment.deposit_initiated`,
            `payment.deposit_completed`, `payment.withdrawal_requested` 및
            `payment.withdrawal_completed`에는 `payment_reference_id`, `amount`,
            `currency`, `payment_method`, `status`가 필요합니다.
            `payment.withdrawal_address_changed`에는 `withdrawal_address_hash`가
            필요합니다. `dispute.chargeback_opened`, `dispute.chargeback_won` 및
            `dispute.chargeback_lost`에는 `payment_reference_id` 및 `dispute_id`,
            `chargeback_id` 중 하나가 필요합니다. `session.bot_signal_observed`에는
            `telemetry_schema_version` 및 `bot_score`, `actions_per_minute`,
            `timing_variance_ms`, `pointer_entropy`, `keystroke_entropy`,
            `reaction_time_ms_p50` 중 하나가 필요합니다.
            `responsible_gambling.self_exclusion_match`에는 `registry_source`,
            `exclusion_status`, `identity_match_ref`가 필요합니다. `_changed`로 끝나는 모든
            `security` 작업에는 `changed_field`가 필요하며, 필드가 `password`, `mfa_method`,
            `mfa`, `email`, `phone`, `withdrawal_address`, `payout_method`,
            `api_key`인 경우 `previous_reference_hash` 또는 `new_reference_hash`가 추가로
            필요합니다. 카드 번호, 전체 출금 주소, 비밀번호 해시 또는 MFA 시크릿은 절대 전송하지 말고 해시 및 참조를
            전송하십시오.
        custom_values:
          type: object
          description: >-
            규칙에서 `custom_values.<key>` 형태로 참조할 수 있는 최대 100개의 커스텀 키입니다. 값은
            스칼라(문자열, 숫자, 불리언 또는 null)여야 하며, 중첩된 객체 및 배열은 거부됩니다.
          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: 단일 이벤트 수집 결과입니다. 새 이벤트와 멱등한 재생 모두에 대해 동일한 형태가 반환됩니다.
      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: 저장된 이벤트의 Didit 식별자입니다.
        event_id:
          type: string
          description: 귀하의 `event_id`입니다.
        status:
          type: string
          enum:
            - ACCEPTED
            - APPROVED
            - IN_REVIEW
            - DECLINED
          description: 실시간 규칙 실행 후 상태입니다. `MonitoringEvent.status`를 참조하세요.
        score:
          type: integer
          description: 실시간 규칙이 실행된 후의 점수입니다.
        rules_evaluated_count:
          type: integer
          minimum: 0
          description: 요청에서 평가된 이벤트 규칙 수입니다. 규칙이 실행되지 않는 샌드박스 애플리케이션에서는 0입니다.
        rules_matched_count:
          type: integer
          minimum: 0
          description: '`TEST` 모드 규칙을 포함하여 일치한 규칙 수입니다.'
        correlation_pending:
          type: boolean
          description: >-
            비동기 규칙이 아직 실행되어야 하는 경우 `true`입니다. 최종 `status` 및 `score`를 확인하려면 몇 분
            후에 `GET /v3/events/{event_uuid}/`를 호출하십시오.
        retention_class:
          type: string
          enum:
            - low_value
            - standard
            - risk_relevant
            - monetary_or_compliance
          description: 일치한 규칙에 의해 승격된 후의 보존 클래스입니다.
        expires_at:
          type: string
          format: date-time
          nullable: true
          description: >-
            이벤트가 보존 등급에 따라 만료되어 삭제되는 시점입니다. `monetary_or_compliance`(결제 및 분쟁)
            이벤트의 경우 null입니다.
        idempotent_replay:
          type: boolean
          description: >-
            이 `event_id` 및 동일한 내용을 가진 이벤트가 이미 저장되어 있는 경우 `true`입니다. 값은 저장된 이벤트의
            값이며 규칙이 다시 실행되지 않았습니다.
        rule_matches:
          type: array
          description: 이벤트와 일치한 규칙입니다.
          items:
            type: object
            required:
              - rule_id
              - library_key
              - mode
              - is_async
            properties:
              rule_id:
                type: string
                format: uuid
                description: 규칙의 UUID입니다.
              library_key:
                type: string
                nullable: true
                description: 규칙 라이브러리에서 설치된 규칙인 경우의 라이브러리 키이며, 그렇지 않은 경우 null입니다.
              mode:
                type: string
                enum:
                  - ACTIVE
                  - TEST
                description: '`TEST` 규칙은 일치 항목을 기록하지만 작업을 적용하지는 않습니다.'
              is_async:
                type: boolean
                description: 일치 항목이 비동기 패스에서 도출된 경우 `true`입니다.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        Business Console의 Developers -> API keys에서 발급받은 귀하 애플리케이션의 API 키입니다. 기본
        키는 전체 접근 권한을 갖습니다. 이름이 지정된 키는 리소스별 none, read, write 범위로 권한을 제한할 수 있으며
        특정 워크플로나 승인된 세션, IP 주소 목록, 만료일 등으로 제한할 수도 있습니다. 401은 키가 잘못되었거나 폐기되었거나
        만료되었음을 의미합니다. 403은 키가 전송되지 않았거나, 키에 해당 리소스나 작업에 대한 접근 권한이 없거나, 요청이 허용된
        IP 목록 외부 주소에서 발생했음을 의미합니다. 세션 경로에서의 404는 해당 세션이 키의 허용 워크플로 또는 상태 범위를
        벗어났음을 의미합니다. 미디어 접근 권한이 없는 키는 이미지, 비디오, PDF URL을 null로 수신하며, 세션 write
        권한이 없는 키는 세션 링크와 token을 null로 수신합니다.
        https://docs.didit.me/console/api-keys 를 참고하십시오.

````

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