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

# 이메일 인증 보고서: 유출 및 OTP JSON

> Didit 이메일 인증 응답을 확인하세요. OTP 수명 주기, 데이터 유출 노출, 일회용 및 수신 불가 플래그, 세션 간 일치 항목과 위험 경고를 파싱합니다.

이메일 인증 보고서는 이메일 OTP 챌린지의 전체 결과를 캡처합니다. 즉, 메시지가 누구에게 전송되었는지, 해당 주소가 일회용이거나 전송 불가한 주소인지, 알려진 데이터 침해 사고에 포함되어 있는지, 사용자가 몇 번 시도했는지, 차단 목록 또는 다른 승인된 사용자와의 세션 간 일치 항목이 있는지 등을 기록합니다.

이 페이지에서는 인증된 각 주소에 대한 OTP 결과, 데이터 침해 노출 내역, 위험 플래그를 파싱할 수 있도록 결정 endpoint에서 반환하는 JSON 구조를 설명합니다.

![OTP 결과, 침해 데이터 및 위험 플래그를 보여주는 Didit 이메일 인증 보고서](https://mintcdn.com/didit-0f962782/z6T2GHM4Zh-iSj-K/images/email-verification-report.png?fit=max\&auto=format\&n=z6T2GHM4Zh-iSj-K\&q=85\&s=4d153b7d3d9d4c88bc3932466af7ed29)

## 개요

이메일 보고서는 워크플로 노드가 이메일 인증 기능을 실행할 때마다 생성됩니다. 각 보고서는 단일 주소에 대한 1회의 OTP 챌린지를 나타내며 다음을 포함합니다.

* 인증된 `email` 주소.
* 불리언 위험 플래그(`is_breached`, `is_disposable`, `is_undeliverable`) 및 침해 인텔리전스 데이터베이스에서 가져온 근거 데이터인 `breaches[]` 배열.
* OTP 전송 시도 횟수(`verification_attempts`) 및 승인 타임스탬프.
* 모든 전송, 재시도 및 코드 확인 시도에 대한 시간순 `lifecycle[]` 로그.
* 다른 승인된 이메일 인증 또는 귀하의 차단 목록에서 동일한 주소를 감지하는 `matches[]` 배열.
* `warnings[]` 배열 — 인증 도중 발생한 위험 이벤트([이메일 인증 경고](https://docs.didit.me/ko/core-technology/email-verification/warnings-email-verification.md) 참조).
* 보고서를 생성한 워크플로 그래프 노드를 식별하는 `node_id`(V3 세션 전용).

호스팅 워크플로 세션에서는 OTP 챌린지가 Didit 인증 UI 내에서 실행되므로 결정 payload에서 결과만 읽으면 됩니다. 호스팅 흐름이 없는 서버 간 OTP의 경우 독립형 Email API를 사용합니다. [`POST /v3/email/send/`](https://docs.didit.me/ko/standalone-apis/email-send)는 코드를 전송하고 [`POST /v3/email/check/`](https://docs.didit.me/ko/standalone-apis/email-check)는 사용자가 입력한 값을 검증합니다. 완료된 독립형 인증도 동일한 보고서 구조로 제공됩니다.

호스팅 세션은 기본적으로 사용자의 **잘못된 코드 입력을 2회**(`email_max_check_attempts`)로, **OTP 전송을 2회 — 최초 전송 1회와 재전송 1회**(`email_max_retries`)로 제한하며, 이는 워크플로 노드별로 조정할 수 있습니다. 두 제한 중 하나라도 초과하면 해당 단계는 `EMAIL_CODE_ATTEMPTS_EXCEEDED`와 함께 `Declined`로 완료됩니다.

## API 응답에서 표시되는 위치

결정 endpoint(`GET /v3/session/{sessionId}/decision/`)는 복수형 배열 키인 **`email_verifications`** 아래에 이메일 보고서를 반환합니다. 이 배열에는 워크플로 그래프의 이메일 인증 노드당 하나의 항목이 포함되며, 일반적으로 하나이지만 단계적 추가 인증 흐름에서는 여러 개가 생성될 수 있습니다.

```json theme={null}
{
  "session_id": "11111111-1111-1111-1111-111111111111",
  "status": "Approved",
  "email_verifications": [
    { "node_id": "feature_email_1", "status": "Approved", "...": "..." }
  ]
}
```

`null` 값은 이메일 인증 단계가 아직 실행되지 않았음을 의미합니다. 워크플로에서 둘 이상의 이메일 주소를 수집할 수 있는 경우에는 `email_verifications[0]`을 직접 읽기보다는 배열을 순회하여 처리하십시오.

## 스키마

필드별 표준 스키마는 [데이터 모델](https://docs.didit.me/ko/reference/data-models.md#이메일-인증) 페이지에서 확인할 수 있습니다.

```typescript theme={null}
interface EmailVerification {
  node_id: string | null;
  status: "Not Finished" | "Approved" | "Declined" | "In Review" | "Expired";
  email: string;
  is_breached: boolean;
  breaches: Breach[];                // Up to the 5 most recent known breaches
  is_disposable: boolean;            // Disposable / throwaway provider
  is_undeliverable: boolean;         // Failed syntax / DNS (MX) validation or OTP delivery
  verification_attempts: number;     // OTP send attempts
  verified_at: string | null;        // ISO 8601, null until a valid code is entered
  lifecycle: EmailLifecycleEvent[];  // OTP send/retry/check timeline
  warnings: Warning[];               // Risk events (see Data models → Warning object)
  matches: EmailMatch[];             // Cross-session / blocklist matches
}

interface Breach {
  name: string;                      // Breached service name
  domain: string;                    // Affected domain
  breach_date: string;               // YYYY-MM-DD
  breach_emails_count: number;       // Total affected accounts
  description: string;               // HTML description of the breach
  logo_path: string;                 // Breached-service logo URL
  data_classes: string[];            // Exposed data categories (snake_case)
  is_verified: boolean;              // true when the breach is a verified incident
}
```

전송 불가능한 주소(유효하지 않은 구문, 존재하지 않는 도메인, 누락된 MX 레코드 또는 OTP 전송 실패)의 경우 자동 거부 경고인 `UNDELIVERABLE_EMAIL_DETECTED`와 함께 단계가 **`Declined`**로 완료됩니다. 유일한 예외는 사용자가 직접 주소를 입력한 경우(세션 생성 시 사전 입력되지 않은 경우)로, 전송이 불가능한 경우 인라인 오류가 반환되어 즉시 거부되는 대신 다른 주소로 재시도할 수 있습니다.

### 상태 값

| 상태 | 의미 |
| - | - |
| `Not Finished` | OTP 전송이 시작되었지만 아직 인증이 완료되지 않았습니다. |
| `Approved` | 사용자가 유효한 OTP를 입력했으며 일치하는 거부 위험이 없습니다. |
| `Declined` | 자동 거부 경고가 발생했거나(차단 목록, 전송 불가능한 주소, 시도 횟수 초과) `DECLINE`으로 설정된 위험 작업과 일치했습니다. |
| `In Review` | `REVIEW`로 설정된 위험 작업에 의해 단계가 수동 검토로 라우팅되었습니다. |
| `Expired` | 유효한 코드 없이 5분의 OTP 입력 가능 시간이 경과했습니다. 독립형 이메일 API를 통해 생성된 인증에 적용됩니다. |

### 라이프사이클 이벤트 유형

`lifecycle[]`는 시간순으로 정렬됩니다. 각 이벤트에는 `type`, `timestamp`, `details` 및 청구 가능한 `fee`(해당하는 경우)가 포함됩니다.

| 이벤트 유형 | 발생 시점 |
| - | - |
| `EMAIL_VERIFICATION_MESSAGE_SENT` | 첫 번째 OTP 전송 시도 시 발생합니다(전송 불가능으로 반환된 경우를 포함해). |
| `EMAIL_VERIFICATION_RETRY_MESSAGE_SENT` | 사용자가 재전송을 요청한 후 후속 OTP 전송 시 발생합니다. |
| `VALID_CODE_ENTERED` | 사용자가 올바른 OTP 코드를 제출했을 때 발생합니다. |
| `INVALID_CODE_ENTERED` | 사용자가 잘못되었거나 만료된 OTP 코드를 제출했을 때 발생합니다(최대 시도 횟수에 반영됨). |
| `EMAIL_VERIFICATION_APPROVED` | 기능 수준 상태가 `Approved`로 설정되었을 때 발생합니다. |
| `EMAIL_VERIFICATION_DECLINED` | 기능 수준 상태가 `Declined`로 설정되었을 때 발생합니다. |
| `EMAIL_VERIFICATION_IN_REVIEW` | 기능 수준 상태가 `In Review`로 설정되었을 때 발생합니다. |
| `EMAIL_VERIFICATION_EXPIRED` | 유효한 코드 없이 OTP 입력 가능 시간이 경과했을 때 발생합니다(독립형 이메일 API). |

`details` payload는 이벤트 제품군에 따라 다릅니다.

* **전송 이벤트** (`EMAIL_VERIFICATION_MESSAGE_SENT`, `EMAIL_VERIFICATION_RETRY_MESSAGE_SENT`) — `{ status, reason }`. `status`는 `Success`, `Retry` 또는 `Undeliverable`이며, `reason`은 전송이 실패하지 않는 한 `null`입니다(`email_can_not_be_delivered`, 또는 인식할 수 없는 레거시 값의 경우 `unknown`).
* **확인 이벤트** (`VALID_CODE_ENTERED`, `INVALID_CODE_ENTERED`) — `{ code_tried, status }`, 이때 `status`는 `Approved`, `Failed`, `Expired or Not Found` 또는 `Declined`입니다.
* **최종 상태 이벤트** — `null`이지만, `EMAIL_VERIFICATION_DECLINED` / `EMAIL_VERIFICATION_IN_REVIEW`는 예외로 `{ "reason": "<risk code>" }`(예: `UNDELIVERABLE_EMAIL_DETECTED`)를 포함합니다.

`status`가 `Success` 또는 `Undeliverable`인 전송에는 \$0.02의 이메일 인증 요금이 기록되며, `Retry` 전송, 확인 이벤트 및 상태 이벤트는 항상 `fee: 0`을 가집니다.

### 세션 간 일치 항목

`matches[]`는 동일한 애플리케이션 내에서 **이전에 승인된** 이메일 인증(KYC, KYB 및 독립형 API 세션 전반)의 동일한 주소와 [management API 목록](https://docs.didit.me/ko/management-api/lists/overview.md)에 구성된 차단 목록 일치 항목을 기록합니다. 현재 세션의 `vendor_data`를 공유하는 인증은 제외되며(동일한 최종 사용자는 자신과 일치하지 않음), 배열은 최대 **5**개 항목으로 제한되고 오래된 항목부터 정렬됩니다. 주소가 차단 목록에 있지만 일치하는 세션 중 차단 목록에 등록된 세션이 없는 경우, `source: "list_entry"`(모든 세션 필드는 `null`)를 포함하는 가상 항목이 배열의 맨 앞에 추가됩니다.

```typescript theme={null}
interface EmailMatch {
  session_id: string | null;         // null when source = "list_entry"
  session_number: number | null;
  vendor_data: string | null;
  verification_date: string | null;  // ISO 8601, creation date of the matched session
  email: string;
  status: string | null;             // Status of the matched session
  is_blocklisted: boolean;
  api_service: string | null;        // Set when the matched session came from a standalone API
  source: "session" | "list_entry";  // "list_entry" = manual blocklist hit
}
```

## 예시

### Approved — 정보 제공 수준의 위반 1건이 포함된 정상 OTP

```json theme={null}
{
  "node_id": "feature_email_1",
  "status": "Approved",
  "email": "alex.sample@example.com",
  "is_breached": true,
  "breaches": [
    {
      "name": "ExampleAir",
      "domain": "example-air.com",
      "breach_date": "2022-08-25",
      "breach_emails_count": 6083479,
      "description": "In August 2022, the airline ExampleAir suffered a data breach that exposed customers' personal information.",
      "logo_path": "https://<media-host>/logos/ExampleAir.png",
      "data_classes": [
        "dates_of_birth", "email_addresses", "genders", "names",
        "nationalities", "phone_numbers", "physical_addresses",
        "salutations", "spoken_languages"
      ],
      "is_verified": true
    }
  ],
  "is_disposable": false,
  "is_undeliverable": false,
  "verification_attempts": 1,
  "verified_at": "2025-09-15T17:36:19.963451Z",
  "lifecycle": [
    {
      "type": "EMAIL_VERIFICATION_MESSAGE_SENT",
      "timestamp": "2025-09-15T17:35:50.000000+00:00",
      "details": { "status": "Success", "reason": null },
      "fee": 0.02
    },
    {
      "type": "VALID_CODE_ENTERED",
      "timestamp": "2025-09-15T17:36:19.000000+00:00",
      "details": { "code_tried": "123456", "status": "Approved" },
      "fee": 0
    },
    {
      "type": "EMAIL_VERIFICATION_APPROVED",
      "timestamp": "2025-09-15T17:36:19.963451+00:00",
      "details": null,
      "fee": 0
    }
  ],
  "warnings": [
    {
      "feature": "EMAIL",
      "risk": "BREACHED_EMAIL_DETECTED",
      "additional_data": null,
      "log_type": "information",
      "short_description": "Breached email detected",
      "long_description": "This email address was found in one or more known data breaches.",
      "node_id": "feature_email_1"
    }
  ],
  "matches": []
}
```

### Declined — 전송 불가능한 주소

구문 또는 DNS(MX) 검증에 실패하거나 OTP 이메일을 전송할 수 없는 사전 입력된 주소는 즉시 `Declined`로 완료됩니다. 사용자에게 코드가 전달되지 않았으므로 코드 확인 이벤트가 표시되지 않습니다.

```json theme={null}
{
  "node_id": "feature_email_1",
  "status": "Declined",
  "email": "user@nonexistent-domain.example",
  "is_breached": false,
  "breaches": [],
  "is_disposable": false,
  "is_undeliverable": true,
  "verification_attempts": 1,
  "verified_at": null,
  "lifecycle": [
    {
      "type": "EMAIL_VERIFICATION_MESSAGE_SENT",
      "timestamp": "2025-09-15T18:00:00.000000+00:00",
      "details": { "status": "Undeliverable", "reason": "email_can_not_be_delivered" },
      "fee": 0.02
    },
    {
      "type": "EMAIL_VERIFICATION_DECLINED",
      "timestamp": "2025-09-15T18:00:01.500000+00:00",
      "details": { "reason": "UNDELIVERABLE_EMAIL_DETECTED" },
      "fee": 0
    }
  ],
  "warnings": [
    {
      "feature": "EMAIL",
      "risk": "UNDELIVERABLE_EMAIL_DETECTED",
      "additional_data": null,
      "log_type": "error",
      "short_description": "Undeliverable email detected",
      "long_description": "The system detected that the email is undeliverable, which is not allowed.",
      "node_id": "feature_email_1"
    }
  ],
  "matches": []
}
```

### Declined — 차단 목록에 등록된 일회용 메일함

사용자가 OTP를 완료했지만 주소가 이메일 차단 목록과 일치했습니다(자동 거부). 일회용 플래그도 발생했습니다. 여기서는 `disposable_email_action`이 기본값인 `NO_ACTION`으로 유지되었으므로 `information` 수준으로 표시됩니다.

```json theme={null}
{
  "node_id": "feature_email_1",
  "status": "Declined",
  "email": "user@mailinator.com",
  "is_breached": false,
  "breaches": [],
  "is_disposable": true,
  "is_undeliverable": false,
  "verification_attempts": 1,
  "verified_at": "2025-09-15T18:05:42.201734Z",
  "lifecycle": [
    {
      "type": "EMAIL_VERIFICATION_MESSAGE_SENT",
      "timestamp": "2025-09-15T18:05:01.000000+00:00",
      "details": { "status": "Success", "reason": null },
      "fee": 0.02
    },
    {
      "type": "VALID_CODE_ENTERED",
      "timestamp": "2025-09-15T18:05:42.000000+00:00",
      "details": { "code_tried": "654321", "status": "Approved" },
      "fee": 0
    },
    {
      "type": "EMAIL_VERIFICATION_DECLINED",
      "timestamp": "2025-09-15T18:05:42.201734+00:00",
      "details": { "reason": "EMAIL_IN_BLOCKLIST" },
      "fee": 0
    }
  ],
  "warnings": [
    {
      "feature": "EMAIL",
      "risk": "EMAIL_IN_BLOCKLIST",
      "additional_data": {
        "blocklisted_session_id": null,
        "blocklisted_session_number": null,
        "api_service": null
      },
      "log_type": "error",
      "short_description": "Email in blocklist",
      "long_description": "The system detected that the email is in the blocklist, which is not allowed.",
      "node_id": "feature_email_1"
    },
    {
      "feature": "EMAIL",
      "risk": "DISPOSABLE_EMAIL_DETECTED",
      "additional_data": null,
      "log_type": "information",
      "short_description": "Disposable email detected",
      "long_description": "The system detected that the email is disposable, which is not allowed.",
      "node_id": "feature_email_1"
    }
  ],
  "matches": [
    {
      "session_id": null,
      "session_number": null,
      "vendor_data": null,
      "verification_date": null,
      "email": "user@mailinator.com",
      "status": null,
      "is_blocklisted": true,
      "api_service": null,
      "source": "list_entry"
    }
  ]
}
```

## 관련 항목

* [이메일 인증 개요](https://docs.didit.me/ko/core-technology/email-verification/overview.md) — 기능 동작 및 요금.
* [이메일 인증 경고](https://docs.didit.me/ko/core-technology/email-verification/warnings-email-verification.md) — 모든 위험 코드, 거부 트리거 및 구성 가능한 작업.
* [데이터 모델 — 이메일 인증](https://docs.didit.me/ko/reference/data-models.md#이메일-인증) — 필드별 표준 스키마.
* [이메일 API — OTP 전송](https://docs.didit.me/ko/standalone-apis/email-send.md) 및 [OTP 확인](https://docs.didit.me/ko/standalone-apis/email-check.md) — 독립형 서버 간 endpoint.
* [Management API — 목록](https://docs.didit.me/ko/management-api/lists/overview.md) — `source: list_entry`로 `matches[]`에 제공되는 이메일 차단 목록을 관리합니다.


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