> ## 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: SMS OTP 검증

> Didit의 POST /v3/phone/check/로 SMS OTP를 검증하고 통신사 유형, 가상 번호, 일회용 번호를 탐지합니다. 사용량 기반 요금, 월 최소 약정 없음.

## 제공업체 장애 처리

전화번호 제공업체를 일시적으로 사용할 수 없으면 이 엔드포인트는 안정적인 기계 판독용 코드와 함께 `502`를 반환합니다:

```json theme={null}
{
  "detail": "The phone verification provider is temporarily unavailable.",
  "code": "phone_provider_unavailable"
}
```

이 응답은 재시도 가능한 것으로 취급하십시오. 짧은 백오프를 적용하고, 유효한 전화번호나 코드를 바꾸라고 요청하는 대신 사용자에게 일시적인 서비스 장애 메시지를 표시하십시오.

## 인텔리전스 부가 기능

`enable_enrichment`를 `true`로 설정하면 해당 번호에 대한 전화번호 인텔리전스도 함께 실행됩니다. 위험 점수, 회선 유형, 최근 번호 이동 여부, 신뢰 지수를 확인할 수 있습니다.
이 부가 기능은 정가 기준으로 요청당 \$0.05가 청구되며, 확인 요청 비용에 추가로 부과됩니다.
잔액이 이 비용을 감당할 수 없으면 요청은 `403`을 반환합니다.

네 가지 필드가 각 신호에 따라 어떤 조치를 취할지 결정합니다.
각 필드는 `NO_ACTION`(기본값) 또는 `DECLINE`으로 설정하며, 각 필드는 `enable_enrichment`가 `true`일 때만 적용됩니다.

| 필드 | 거부되는 경우 |
| - | - |
| `phone_intelligence_score_action` | 위험 점수가 임계값을 초과하는 경우입니다. |
| `phone_type_risk_action` | 번호가 고위험 회선 유형인 경우입니다. |
| `recent_port_action` | 번호가 최근 다른 통신사로 이동된 경우입니다. |
| `low_phone_trust_action` | 신뢰 지수가 임계값 이하인 경우입니다. |

`NO_ACTION`으로 설정하면 해당 신호는 여전히 `phone.phone_intelligence`에 반환되므로, 자체 규칙을 적용할 수 있습니다.


## OpenAPI

````yaml ko/openapi-25.json POST /v3/phone/check/
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/phone/check/:
    post:
      tags:
        - Standalone APIs
      summary: 전화번호 코드 확인
      description: >-
        [`POST /v3/phone/send/`](/ko/standalone-apis/phone-send)로 전송된 OTP를 검증하고
        최종 인증 결과와 전화번호 인텔리전스(통신사명 및 회선 유형, 가상(VoIP) 및 일회용 플래그, 세션 전반에서 해당 번호의 중복
        사용 여부)를 가져옵니다.


        **확인이 인증을 찾는 방식.** 매칭은 애플리케이션 및 E.164 `phone_number`를 기반으로 이루어지며,
        `request_id`는 입력값이 아닙니다. 최근 **5분** 이내에 생성된 가장 최근의 대기 중인 인증이 확인됩니다. 해당하는
        인증이 없는 경우(전송된 적 없음, 이미 완료됨 또는 5분 초과) endpoint는 `200`과 함께 `status:
        "Expired or Not Found"`를 반환합니다.


        **시도 한도.** 각 인증당 **3회의 코드 시도**가 허용됩니다. 처음 두 번 잘못된 코드를 입력하면 남은 시도 횟수 및
        `phone: null`과 함께 `status: "Failed"`가 반환됩니다. 세 번째로 잘못된 코드를 입력하면
        `VERIFICATION_CODE_ATTEMPTS_EXCEEDED` 경고와 함께 인증이 `Declined`로 최종 확정되며 전체
        전화번호 보고서가 반환됩니다.


        **결과.** `Approved` — 올바른 코드이며 거부 위험 없음. `Declined` — 최종 확정: 코드는 올바르지만 거부
        위험이 일치함(아래의 `DECLINE` 작업, 차단 목록에 등록되었거나 고위험 번호), 또는 시도 한도가 소진됨. `Failed`
        — 잘못된 코드이며 잔여 시도 횟수가 있음. `Expired or Not Found` — 확인할 항목 없음.
        `Approved`/`Declined`의 경우 `request_id`는 전송 시의 `request_id`(세션 ID)와 동일하며
        `phone`에 전체 보고서(`carrier`, `is_virtual`, `is_disposable`, `warnings`,
        `lifecycle`, `matches`)가 포함됩니다. `Failed` 및 `Expired or Not Found`의 경우
        `request_id`는 일회성 임의 UUID입니다.


        **위험 작업.** `duplicated_phone_number_action`, `disposable_number_action`,
        `voip_number_action`은 올바른 코드 입력 시 해당 위험이 감지되었을 때 수행할 작업을 결정합니다.
        `DECLINE`은 최종 상태를 `Declined`로 변경합니다. `NO_ACTION`(기본값)은 상태에 영향을 주지 않고
        `phone.warnings`에 위험을 기록합니다.


        **결제.** 확인은 무료이며, 전송 측에서 전송에 대해 요금이 청구됩니다([전화번호 인증
        요금](/ko/getting-started/phone-verification-pricing) 참조).


        **세션 영속성.** 완료된 확인은 전송 시 생성된 세션을 업데이트하고(Business Console에서 확인 가능, `GET
        /v3/session/{sessionId}/decision/`을 통해 조회 가능) `status.updated` webhook을
        트리거합니다.


        **샌드박스.** 샌드박스 API 키는 모든 처리를 건너뜁니다. 올바른 형식의 코드(`123456`을 포함한 4~8자리 숫자)는
        간소화된 평면 `phone` 객체(`status`, `phone_number`, `country_code`,
        `carrier_name`, `line_type`, `flags`)가 포함된 정적 `Approved` payload를 반환합니다.
        형식이 잘못된 입력은 여전히 `400`을 반환합니다. 어떤 항목도 영구 저장되지 않습니다.


        **인증.** `x-api-key` 헤더에 애플리케이션의 API 키를 전송하십시오. 자격 증명이 누락되었거나 유효하지 않으면
        `403`(`{"detail": "You do not have permission to perform this
        action."}`)이 반환됩니다. 이 API는 `401`을 절대 반환하지 않습니다.


        **속도 제한.** API 키당 분당 300개 요청의 쓰기 한도가 공유되며, 번호당 시간당 4회 시도의 업스트림 어뷰징 방지
        한도가 추가로 적용됩니다. 둘 중 하나라도 초과하면 `429`가 반환됩니다.


        **소셜 풋프린트.** `enable_social`을 `true`로 설정하면 `phone_social` 블록이 추가됩니다.
        여기에는 해당 번호가 등록된 온라인 플랫폼 목록, 카테고리별 건수 및 제공되는 프로필 세부 정보가 포함됩니다.
        `profiles_registered: 0`은 플랫폼을 확인했으나 해당 번호가 어떤 플랫폼에서도 발견되지 않았음을 의미하며, 이는
        유효하고 요금이 청구되는 응답입니다. 부가 기능을 요청하지 않았거나 확인을 완료할 수 없는 경우에는 해당 블록이 표시되지 않으며
        요금도 청구되지 않습니다. 결제 시 이 endpoint 자체 가격에 요청당 `phone_social` 1단위가 추가됩니다.
      operationId: post_v3phone_check
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                phone_number:
                  type: string
                  maxLength: 20
                  description: >-
                    일치하는 [`POST
                    /v3/phone/send/`](/ko/standalone-apis/phone-send) 호출에 사용된 것과
                    동일한 E.164 형식의 전화번호입니다. 이를 통해 검증과 전송이 연결됩니다.
                  example: '+14155552671'
                code:
                  type: string
                  minLength: 4
                  maxLength: 8
                  pattern: ^[0-9]{4,8}$
                  description: >-
                    최종 사용자가 수신한 OTP입니다. 4~8자리 숫자여야 하며, 그 외의 경우 시도 횟수를 차감하지 않고
                    `400`을 반환합니다. 형식은 올바르지만 잘못된 코드는 `200`과 함께 `status:
                    "Failed"`를 반환하고 3회의 시도 횟수 중 1회를 소진합니다.
                  example: '123456'
                duplicated_phone_number_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    동일한 번호가 애플리케이션의 다른 사용자(다른 `vendor_data`)에 의해 이미 사용되었을 때 수행할
                    작업입니다. `DECLINE`은 최종 `status`를 `Declined`로 변경하며,
                    `NO_ACTION`은 위험을 `phone.warnings`에 기록하고 `phone.matches`를
                    채웁니다.
                disposable_number_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    통신사 조회를 통해 해당 번호가 일회용/임시 번호로 확인되었을 때(`phone.is_disposable`)
                    수행할 작업입니다. `DECLINE`은 최종 `status`를 `Declined`로 변경하고,
                    `NO_ACTION`은 해당 위험을 `phone.warnings`에 기록합니다.
                voip_number_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    통신사 조회에서 `voip`, `isp` 또는 `vpn`과 같은 가상 회선 유형으로 보고되었을
                    때(`phone.is_virtual`) 수행할 작업입니다. `DECLINE`은 최종 `status`를
                    `Declined`로 변경하고, `NO_ACTION`은 해당 위험을 `phone.warnings`에
                    기록합니다.
                enable_enrichment:
                  type: boolean
                  default: false
                  description: >-
                    `true`인 경우 해당 번호에 대한 전화번호 인텔리전스(위험 점수, 회선 유형, 최근 통신사 변경 여부 및
                    신뢰 지수)도 실행합니다. 이 endpoint의 자체 가격 외에 요청당 하나의
                    `phone_intelligence_api` 단위(정가 기준 $0.05)로 청구됩니다. 잔액이 이를 충당하지
                    못하면 요청은 `403`을 반환합니다.
                  example: false
                phone_intelligence_score_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    전화번호 인텔리전스 위험 점수가 임계값을 초과할 때 수행할 작업입니다. `DECLINE`은 최종
                    `status`를 `Declined`로 변경하며, `NO_ACTION`은 거부하지 않고 신호를 기록합니다.
                    `enable_enrichment`가 `true`일 때만 적용됩니다.
                phone_type_risk_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    전화번호가 고위험 회선 유형일 때 수행할 작업입니다. `DECLINE`은 최종 `status`를
                    `Declined`로 변경하며, `NO_ACTION`은 거부하지 않고 신호를 기록합니다.
                    `enable_enrichment`가 `true`일 때만 적용됩니다.
                recent_port_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    전화번호가 최근 다른 통신사로 번호 이동되었을 때 수행할 작업입니다. `DECLINE`은 최종
                    `status`를 `Declined`로 변경하며, `NO_ACTION`은 거부하지 않고 신호를 기록합니다.
                    `enable_enrichment`가 `true`일 때만 적용됩니다.
                low_phone_trust_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    전화번호 인텔리전스 신뢰 지수가 임계값 이하일 때 수행할 작업입니다. `DECLINE`은 최종
                    `status`를 `Declined`로 변경하며, `NO_ACTION`은 거부하지 않고 신호를 기록합니다.
                    `enable_enrichment`가 `true`일 때만 적용됩니다.
                enable_social:
                  type: boolean
                  default: false
                  description: >-
                    true인 경우, 전화번호의 소셜 발자국(등록된 메시징, 소셜, 전자상거래 및 전문 플랫폼)도 조회합니다.
                    이 endpoint 자체의 가격 외에 요청당 `phone_social` 1단위로 청구됩니다.
                  example: true
                phone_no_social_presence_action:
                  type: string
                  enum:
                    - NO_ACTION
                    - DECLINE
                  default: NO_ACTION
                  description: >-
                    소셜 풋프린트 검사 결과 지원하는 플랫폼 중 어느 곳에도 해당 번호가 등록되어 있지 않을 때 수행할
                    작업입니다. 이 endpoint에서는 NO_ACTION 및 DECLINE만 허용되며, 동일한 이름의 워크플로
                    구성 키에서는 REVIEW를 사용할 수 있습니다.
              required:
                - phone_number
                - code
            examples:
              Default:
                summary: 모든 위험을 기록하지만 자동으로 거부하지는 않음
                value:
                  phone_number: '+14155552671'
                  code: '123456'
              Strict risk policy:
                summary: VoIP 및 일회용 전화번호 자동 거부
                value:
                  phone_number: '+14155552671'
                  code: '123456'
                  voip_number_action: DECLINE
                  disposable_number_action: DECLINE
      responses:
        '200':
          description: >-
            확인 완료 — 잘못된 코드 및 누락된 인증도 `200`을 반환하므로 HTTP 코드가 아닌 `status`를 확인하십시오.
            `phone`은 최종 결과(`Approved`/`Declined`)에서만 채워지며, `Failed`에서는 `null`,
            `Expired or Not Found`에서는 제외됩니다.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PhoneVerificationCheckResponse'
              examples:
                Approved:
                  summary: 올바른 코드 — 통신사, 라이프사이클 및 일치 항목이 포함된 전체 전화번호 보고서
                  value:
                    request_id: e39cb057-92fc-4b59-b84e-02fec29a0f24
                    status: Approved
                    message: The verification code is correct.
                    phone:
                      status: Approved
                      phone_number_prefix: '+1'
                      phone_number: '4155552671'
                      full_number: '+14155552671'
                      country_code: US
                      country_name: United States
                      carrier:
                        name: AT&T
                        type: mobile
                      is_disposable: false
                      is_virtual: false
                      verification_method: whatsapp
                      verification_attempts: 1
                      verified_at: '2026-06-12T01:24:47.311323Z'
                      warnings: []
                      lifecycle:
                        - type: PHONE_VERIFICATION_MESSAGE_SENT
                          timestamp: '2026-06-12T01:23:39.580554+00:00'
                          details:
                            status: Success
                            reason: null
                            channel: whatsapp
                            actual_channel: whatsapp
                          fee: 0.0509
                        - type: PHONE_DELIVERY_DELIVERED
                          timestamp: '2026-06-12T01:23:43.118220+00:00'
                          details:
                            channel: whatsapp
                            status: delivered
                          fee: 0
                        - type: VALID_CODE_ENTERED
                          timestamp: '2026-06-12T01:24:47.311201+00:00'
                          details:
                            code_tried: '123456'
                            status: Approved
                          fee: 0
                        - type: PHONE_VERIFICATION_APPROVED
                          timestamp: '2026-06-12T01:24:47.384292+00:00'
                          details: null
                          fee: 0
                      matches: []
                    vendor_data: user-1234
                    metadata: null
                    created_at: '2026-06-12T01:24:47.401719+00:00'
                Failed (attempts remaining):
                  summary: 잘못된 코드 — 사용자가 재시도할 수 있습니다. 여기서 request_id는 일회용 UUID입니다.
                  value:
                    request_id: 11111111-2222-3333-4444-555555555555
                    status: Failed
                    message: 'The verification code is incorrect. Attempts remaining: 2'
                    phone: null
                    vendor_data: user-1234
                    metadata: null
                    created_at: '2026-06-12T01:24:21.512340+00:00'
                Declined (max attempts):
                  summary: 세 번째 잘못된 코드 — 인증이 거부됨으로 최종 처리됨
                  value:
                    request_id: e39cb057-92fc-4b59-b84e-02fec29a0f24
                    status: Declined
                    message: >-
                      The verification code is incorrect. Maximum attempts
                      reached.
                    phone:
                      status: Declined
                      phone_number_prefix: '+1'
                      phone_number: '4155552671'
                      full_number: '+14155552671'
                      country_code: US
                      country_name: United States
                      carrier:
                        name: AT&T
                        type: mobile
                      is_disposable: false
                      is_virtual: false
                      verification_method: whatsapp
                      verification_attempts: 1
                      verified_at: null
                      warnings:
                        - feature: PHONE
                          risk: VERIFICATION_CODE_ATTEMPTS_EXCEEDED
                          additional_data: null
                          log_type: error
                          short_description: Verification code attempts exceeded
                          long_description: >-
                            The system detected that the phone number has
                            exceeded the maximum number of verification code
                            attempts.
                      lifecycle:
                        - type: PHONE_VERIFICATION_MESSAGE_SENT
                          timestamp: '2026-06-12T01:23:39.580554+00:00'
                          details:
                            status: Success
                            reason: null
                            channel: whatsapp
                            actual_channel: whatsapp
                          fee: 0.0509
                        - type: INVALID_CODE_ENTERED
                          timestamp: '2026-06-12T01:24:01.118220+00:00'
                          details:
                            code_tried: '111111'
                            status: Failed
                          fee: 0
                        - type: INVALID_CODE_ENTERED
                          timestamp: '2026-06-12T01:24:21.512340+00:00'
                          details:
                            code_tried: '222222'
                            status: Failed
                          fee: 0
                        - type: INVALID_CODE_ENTERED
                          timestamp: '2026-06-12T01:24:47.311201+00:00'
                          details:
                            code_tried: '333333'
                            status: Failed
                          fee: 0
                        - type: PHONE_VERIFICATION_DECLINED
                          timestamp: '2026-06-12T01:24:47.384292+00:00'
                          details:
                            reason: VERIFICATION_CODE_ATTEMPTS_EXCEEDED
                          fee: 0
                      matches: []
                    vendor_data: user-1234
                    metadata: null
                    created_at: '2026-06-12T01:24:47.401719+00:00'
                Declined (risk policy):
                  summary: 올바른 코드이지만 VoIP 회선이며 voip_number_action=DECLINE으로 설정됨
                  value:
                    request_id: 7f1c9d2e-44a1-4b6e-9a3e-5b8e6f1c2d3a
                    status: Declined
                    message: The verification code is correct.
                    phone:
                      status: Declined
                      phone_number_prefix: '+1'
                      phone_number: '5005550006'
                      full_number: '+15005550006'
                      country_code: US
                      country_name: United States
                      carrier:
                        name: CLEC LLC
                        type: voip
                      is_disposable: false
                      is_virtual: true
                      verification_method: sms
                      verification_attempts: 1
                      verified_at: '2026-06-12T01:24:47.311323Z'
                      warnings:
                        - feature: PHONE
                          risk: VOIP_NUMBER_DETECTED
                          additional_data: null
                          log_type: error
                          short_description: VoIP number detected
                          long_description: >-
                            The system detected that the phone number is a VoIP
                            number, which is not allowed.
                      lifecycle:
                        - type: PHONE_VERIFICATION_MESSAGE_SENT
                          timestamp: '2026-06-12T01:23:39.580554+00:00'
                          details:
                            status: Success
                            reason: null
                            channel: whatsapp
                            actual_channel: sms
                          fee: 0.0509
                        - type: VALID_CODE_ENTERED
                          timestamp: '2026-06-12T01:24:47.311201+00:00'
                          details:
                            code_tried: '123456'
                            status: Approved
                          fee: 0
                        - type: PHONE_VERIFICATION_DECLINED
                          timestamp: '2026-06-12T01:24:47.384292+00:00'
                          details:
                            reason: VOIP_NUMBER_DETECTED
                          fee: 0
                      matches: []
                    vendor_data: user-1234
                    metadata: null
                    created_at: '2026-06-12T01:24:47.401719+00:00'
                Expired or Not Found:
                  summary: 최근 5분 이내에 이 번호에 대한 대기 중인 인증이 없습니다
                  value:
                    request_id: 69cc35c6-280a-47a6-ab8c-4f32abc02ed0
                    status: Expired or Not Found
                    message: No pending phone verification found in the last 5 minutes.
                    vendor_data: null
                    metadata: null
                    created_at: '2026-06-12T01:24:47.311323+00:00'
        '400':
          description: '검증 오류 — DRF의 필드 오류 엔벨로프: 문제가 있는 필드당 하나의 메시지 배열.'
          content:
            application/json:
              examples:
                Invalid code format:
                  summary: '`code`가 4~8자리 숫자가 아닙니다'
                  value:
                    code:
                      - Invalid code format. Enter 4 to 8 numeric digits.
                Invalid phone number:
                  summary: '`phone_number`가 유효한 E.164 형식이 아님'
                  value:
                    phone_number:
                      - Invalid phone number provided.
                Invalid action:
                  summary: 위험 작업에는 NO_ACTION 또는 DECLINE만 허용됩니다
                  value:
                    voip_number_action:
                      - '"REVIEW" is not a valid choice.'
        '403':
          description: >-
            권한이 거부되었습니다. `x-api-key` 헤더가 누락되었을 때 반환됩니다. 잘못되었거나 취소되었거나 만료된 키는
            `401`을 반환합니다. 확인은 무료이므로 크레딧 확인이 수행되지 않습니다.
          content:
            application/json:
              examples:
                Missing or invalid API key:
                  summary: '`x-api-key` 헤더가 없거나, 키가 유효하지 않거나 해지되었습니다'
                  value:
                    detail: You do not have permission to perform this action.
        '429':
          description: >-
            속도 제한을 초과했습니다. POST/PATCH/DELETE endpoint는 API 키당 분당 300회의 쓰기 요청 한도를
            공유합니다(거래 생성 및 이벤트 수집은 별도로 600회 한도 적용). 또한 상위 시스템에서 전화번호당 시간당 4회의 인증
            시도로 어뷰징 방지 상한이 적용됩니다. 응답에는 `X-RateLimit-Limit`,
            `X-RateLimit-Remaining`, `X-RateLimit-Reset`, `Retry-After` 헤더가
            포함됩니다. 참고: `X-RateLimit-*`/`Retry-After` 헤더는 분당 300회 쓰기 제한으로 인한 429
            응답에만 함께 제공되며, 번호당 상한으로 인한 429 응답에는 속도 제한 헤더가 포함되지 않습니다.
          content:
            application/json:
              examples:
                Per-number cap:
                  summary: 지난 1시간 동안 동일한 번호로 4회를 초과하는 인증 시도 발생
                  value:
                    detail: >-
                      Maximum verification attempts reached for this phone
                      number. Only 4 authentication attempts are allowed per
                      hour. Try again later or use a different number.
                Write rate limit exceeded:
                  summary: 현재 분 동안 300건을 초과하는 쓰기 요청 발생
                  value:
                    detail: >-
                      Write request rate limit exceeded. You can make up to 300
                      requests per minute.
              schema:
                type: object
                properties:
                  detail:
                    type: string
        '500':
          description: >-
            알려진 제공업체 중단이 아닌 업스트림 코드 검증 중 예기치 않은 오류가 발생했습니다. 안전하게 재시도할 수 있으며, 시도
            횟수는 완료된 확인에 대해서만 차감됩니다.
          content:
            application/json:
              examples:
                Provider error:
                  summary: 코드 확인을 완료할 수 없습니다
                  value:
                    detail: Error checking phone verification
              schema:
                type: object
                properties:
                  detail:
                    type: string
        '502':
          description: >-
            전화번호 인증 공급자를 일시적으로 사용할 수 없습니다(5xx 응답, 시간 초과 또는 내장 재시도 후에도 지속된 연결
            실패). 다시 시도해도 안전하며, 시도 가능 횟수가 차감되지 않습니다.
          content:
            application/json:
              examples:
                Provider outage:
                  summary: 공급자가 확인 요청에 응답하지 않았습니다
                  value:
                    detail: >-
                      Phone verification is temporarily unavailable. Please try
                      again shortly.
                    code: phone_provider_unavailable
              schema:
                type: object
                properties:
                  detail:
                    type: string
                  code:
                    type: string
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: curl
          label: curl
          source: |-
            curl -X POST https://verification.didit.me/v3/phone/check/ \
              -H 'x-api-key: YOUR_API_KEY' \
              -H 'Content-Type: application/json' \
              -d '{
                "phone_number": "+14155552671",
                "code": "123456",
                "voip_number_action": "DECLINE"
              }'
        - lang: python
          label: Python
          source: |-
            from didit import Didit

            # Reads DIDIT_API_KEY.
            client = Didit()

            result = client.phone.check_code(
                phone_number="+14155552671",
                code="123456",
            )
            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.phone.checkCode({
              phone_number: "+14155552671",
              code: "123456",
            });
            console.log(result);
        - lang: go
          label: Go
          source: "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Phone.CheckCode(ctx, didit.PhoneCheckCodeParams{\n\tPhoneNumber: \"+14155552671\",\n\tCode:        \"123456\",\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
        - lang: java
          label: Java
          source: |-
            import me.didit.Didit;
            import me.didit.types.PhoneCheckCodeParams;

            // Reads DIDIT_API_KEY.
            Didit client = new Didit();

            var result = client.phone().checkCode(PhoneCheckCodeParams.builder()
                    .phoneNumber("+14155552671")
                    .code("123456")
                    .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->phone->checkCode([
                'phone_number' => '+14155552671',
                'code' => '123456',
            ]);
            print_r($result->toArray());
        - lang: ruby
          label: Ruby
          source: |-
            require "didit"

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

            result = didit.phone.check_code(
              phone_number: "+14155552671",
              code: "123456"
            )
            puts result.to_h
        - lang: csharp
          label: .NET
          source: >-
            using System;

            using System.Text.Json;

            using Didit;


            // Reads DIDIT_API_KEY.

            using var client = new DiditClient();


            var result = await client.Phone.CheckCodeAsync(new
            PhoneCheckCodeParams

            {
                PhoneNumber = "+14155552671",
                Code = "123456",
            });

            Console.WriteLine(JsonSerializer.Serialize(result));
components:
  schemas:
    PhoneVerificationCheckResponse:
      type: object
      properties:
        request_id:
          type: string
          format: uuid
          description: >-
            `Approved`/`Declined`인 경우: 일치하는 인증의 세션 ID — `POST /v3/phone/send/`에서
            반환된 `request_id`와 동일합니다. `Failed` 및 `Expired or Not Found`인 경우: 나중에
            조회할 수 없는 일회성 무작위 UUID입니다.
        status:
          type: string
          enum:
            - Approved
            - Declined
            - Failed
            - Expired or Not Found
          description: >-
            `Approved` — 올바른 코드이며 거부 위험이 없음. `Declined` — 최종 상태: 거부 위험이 일치했거나 시도
            횟수 한도(3회)가 소진됨. `Failed` — 잘못된 코드이며 잔여 시도 횟수가 있음. `Expired or Not
            Found` — 지난 5분 동안 이 번호에 대한 보류 중인 인증이 없음.
        message:
          type: string
          description: 잘못된 코드 입력 후 남은 시도 횟수를 포함한 결과에 대한 사람이 읽기 쉬운 설명입니다.
        phone:
          type: object
          nullable: true
          description: >-
            전체 전화번호 보고서입니다. 확정된 결과(`Approved`/`Declined`)에만 존재(null이 아님)하며,
            `Failed`인 경우 `null`, `Expired or Not Found`인 경우 생략됩니다.
          properties:
            status:
              type: string
              enum:
                - Approved
                - Declined
                - In Review
                - Not Finished
                - Expired
              description: 전화번호 인증의 최종 상태입니다. 완료된 검사의 최상위 `status`와 일치합니다.
            phone_number_prefix:
              type: string
              description: '`+`로 시작하는 국가 전화번호 코드(예: `+1`)입니다.'
              example: '+1'
            phone_number:
              type: string
              description: 국가 전화 코드를 제외한 국내 번호.
              example: '4155552671'
            full_number:
              type: string
              description: E.164 형식의 전체 번호입니다.
              example: '+14155552671'
            country_code:
              type: string
              nullable: true
              description: 해당 번호의 ISO 3166-1 alpha-2 국가 코드입니다.
              example: US
            country_name:
              type: string
              description: '`country_code`에서 파생된 전체 국가명입니다.'
              example: United States
            carrier:
              type: object
              description: 완료 단계에서 실행된 통신사 조회를 통해 확인된 해당 번호의 현재 네트워크입니다.
              properties:
                name:
                  type: string
                  description: 통신사 이름. 조회 시 식별할 수 없는 경우 빈 문자열입니다.
                type:
                  type: string
                  description: >-
                    조회 결과로 보고된 회선 유형: `mobile`, `fixed_line`, `voip`, `isp`,
                    `vpn`, `toll_free`, `premium_rate`, `pager`, `payphone`,
                    `satellite`, `service`, `shared_cost`,
                    `short_codes_commercial`, `calling_cards`, `local_rate`,
                    `universal_access`, `voice_mail`, `other`, 또는 `unknown`.
            is_disposable:
              type: boolean
              description: 번호가 임시/버너 번호 서비스에 속하는 경우 `true`입니다.
            is_virtual:
              type: boolean
              description: 회선 유형이 가상(`voip`, `isp` 또는 `vpn`)인 경우 `true`입니다.
            verification_method:
              type: string
              description: >-
                전송이 확인된 후 실제로 OTP를 전송한 채널(예: `whatsapp`, `sms`)이며, 확인되기 전까지는 요청된
                채널입니다.
            verification_attempts:
              type: integer
              description: 이 인증에 대한 OTP 전송 횟수입니다(1회, 재시도 후에는 2회).
            verified_at:
              type: string
              format: date-time
              nullable: true
              description: 올바른 코드가 입력된 시점입니다. 인증이 승인되지 않은 경우 `null`입니다.
            warnings:
              type: array
              description: 인증 중 기록된 위험 경고(중복, 일회용, VoIP, 시도 횟수 초과, 차단 목록 등). 없을 경우 빈 배열입니다.
              items:
                type: object
                properties:
                  feature:
                    type: string
                    description: 경고를 생성한 기능입니다. 여기서는 항상 `PHONE`입니다.
                  risk:
                    type: string
                    description: 기계 판독 가능한 위험 코드입니다.
                  additional_data:
                    type: object
                    nullable: true
                    description: >-
                      위험별 컨텍스트(예: 중복 위험의 경우 중복된 세션 ID). 위험에 추가 데이터가 없는 경우
                      `null`입니다.
                  log_type:
                    type: string
                    enum:
                      - error
                      - warning
                      - information
                    description: >-
                      심각도입니다. `error` 위험은 인증을 거부하고, `warning`은 검토 대상으로 표시하며,
                      `information`은 상태에 영향을 주지 않고 기록됩니다.
                  short_description:
                    type: string
                    description: 사람이 읽을 수 있는 한 줄의 위험 요약입니다.
                  long_description:
                    type: string
                    description: 위험에 대한 사람이 읽기 쉬운 설명입니다.
            lifecycle:
              type: array
              description: >-
                인증의 시간순 감사 로그입니다. 이벤트 `type`은 `PHONE_VERIFICATION_MESSAGE_SENT`,
                `PHONE_VERIFICATION_RETRY_MESSAGE_SENT`,
                `PHONE_VERIFICATION_BLOCKED`, `PHONE_DELIVERY_DELIVERED`,
                `PHONE_DELIVERY_UNDELIVERABLE`, `VALID_CODE_ENTERED`,
                `INVALID_CODE_ENTERED`, `PHONE_VERIFICATION_APPROVED`,
                `PHONE_VERIFICATION_DECLINED`, `PHONE_VERIFICATION_IN_REVIEW`,
                `PHONE_VERIFICATION_EXPIRED` 중 하나입니다.
              items:
                type: object
                properties:
                  type:
                    type: string
                    description: 이벤트 유형입니다.
                  timestamp:
                    type: string
                    format: date-time
                    description: 이벤트가 발생한 시점입니다.
                  details:
                    type: object
                    nullable: true
                    description: >-
                      이벤트 관련 payload입니다. 발송 이벤트: `{status, reason, channel,
                      actual_channel}` (`actual_channel`은 전송이 확인되면 채워집니다). 전송
                      이벤트: `{channel, status}`. 코드 입력 이벤트: `{code_tried,
                      status}`. 최종 상태 이벤트: `null`, 또는 거부됨/검토 중일 때 `{reason}`.
                  fee:
                    type: number
                    description: >-
                      이 이벤트에 대해 청구된 USD 금액입니다. 발송 이벤트(전송 가격)에서만 0이 아니며, 코드 입력,
                      전송 확인 및 상태 이벤트에서는 0입니다.
            matches:
              type: array
              description: >-
                다른 사용자(다른 `vendor_data`)가 동일한 전화번호를 사용한 애플리케이션의 다른 세션(KYC, KYB
                또는 API)입니다. 최대 5개 항목이며, 합성 목록 항목에 대한 차단 목록 일치 항목이 있는 경우 먼저
                표시됩니다(세션 파생 일치는 쿼리 순서 유지). 일치하는 항목이 없으면 빈 배열입니다.
              items:
                type: object
                properties:
                  session_id:
                    type: string
                    format: uuid
                    description: 이 전화번호를 사용한 다른 인증의 세션 id입니다.
                  session_number:
                    type: integer
                    description: 해당 세션의 사람이 읽기 쉬운 순차 번호입니다.
                  vendor_data:
                    type: string
                    nullable: true
                    description: 해당 세션의 `vendor_data`입니다.
                  verification_date:
                    type: string
                    description: 해당 세션이 생성된 시점(`YYYY-MM-DDTHH:MM:SSZ`)입니다.
                  phone_number:
                    type: string
                    description: 일치하는 전화번호입니다.
                  status:
                    type: string
                    description: '해당 세션의 상태(예: `Approved`, `Declined`, `In Progress`)입니다.'
                  is_blocklisted:
                    type: boolean
                    description: 전화번호가 애플리케이션의 차단 목록에 있는지 여부입니다.
                  api_service:
                    type: string
                    nullable: true
                    description: >-
                      API 유형 세션의 경우 이를 생성한 독립형 API(예: `PHONE_VERIFICATION`), 일반
                      인증 세션의 경우 `null`입니다.
                  source:
                    type: string
                    description: >-
                      일치 항목이 발견된 위치입니다. 일반적으로 `session`이며, 조직 목록 항목을 통한 차단 목록
                      일치는 `source: "list_entry"` 및 null
                      `session_id`/`session_number`가 있는 합성 일치 항목을 앞에 추가합니다.
            phone_social:
              $ref: '#/components/schemas/PhoneSocialFootprint'
            phone_intelligence:
              allOf:
                - $ref: '#/components/schemas/PhoneIntelligence'
              description: 전화번호 인텔리전스 신호입니다. 검사 시 `enable_enrichment`가 `true`인 경우에만 존재합니다.
        vendor_data:
          type: string
          nullable: true
          description: 일치하는 인증 세션의 `vendor_data`입니다. `Expired or Not Found`인 경우 `null`입니다.
        metadata:
          type: object
          nullable: true
          description: 일치하는 인증 세션의 `metadata`입니다. `Expired or Not Found`인 경우 `null`입니다.
        created_at:
          type: string
          format: date-time
          description: 이 검사 응답의 타임스탬프입니다.
    PhoneSocialFootprint:
      type: object
      nullable: true
      description: >-
        전화번호의 소셜 풋프린트(등록된 온라인 플랫폼)입니다. `enable_social`이 설정되고 확인이 완료된 경우에만 표시됩니다.
        반환된 데이터가 없는 경우 각 개수는 null일 수 있습니다. `profiles_registered: 0`은 플랫폼을 확인했으나
        해당 전화번호가 어떤 플랫폼에서도 발견되지 않았음을 의미하며, 이는 유효하고 요금이 청구되는 응답이자 흔히 나타나는 합성 신원
        신호입니다.
      properties:
        profiles_registered:
          type: integer
          nullable: true
          description: 전화번호 등록이 확인된 플랫폼입니다.
          example: 5
        profiles_checked:
          type: integer
          nullable: true
          description: 가입 여부가 평가된 플랫폼입니다.
          example: 14
        names_found:
          type: integer
          nullable: true
          description: 관련 이름을 반환한 플랫폼입니다.
          example: 0
        photos_found:
          type: integer
          nullable: true
          description: 프로필 사진을 반환한 플랫폼입니다.
          example: 0
        communication_breadth:
          type: integer
          nullable: true
          description: 존재가 감지된 커뮤니케이션 플랫폼입니다.
          example: 2
        digital_footprint_diversity:
          type: integer
          nullable: true
          description: 존재가 감지된 고유한 플랫폼 카테고리입니다.
          example: 5
        digital_sophistication_index:
          type: integer
          nullable: true
          description: 복합 디지털 성숙도 지표(0-10)입니다.
          example: 5
        engagement_depth_index:
          type: integer
          nullable: true
          description: 프로필 정보량 지표, 0-10.
          example: 3
        subscription_affordability_index:
          type: integer
          nullable: true
          description: 무료 대 유료 플랫폼 비율(0-10)입니다.
          example: 2
        free_platforms:
          type: integer
          nullable: true
          description: 무료 플랫폼에서의 등록 수입니다.
          example: 4
        full_paid_platforms:
          type: integer
          nullable: true
          description: 완전 유료 플랫폼에서의 등록 수입니다.
          example: 0
        partial_paid_platforms:
          type: integer
          nullable: true
          description: 프리미엄(freemium) 플랫폼에서의 등록 수입니다.
          example: 1
        whatsapp_profile_completeness:
          type: string
          nullable: true
          enum:
            - Basic
            - Partial
            - Complete
            - Not Present
            - null
          description: WhatsApp 프로필의 완성도입니다. 전화번호 전용이며 이메일의 경우 null입니다.
          example: Partial
        registered_platforms:
          type: array
          description: 가입이 확인된 플랫폼입니다.
          items:
            $ref: '#/components/schemas/SocialFootprintPlatform'
        not_registered_platforms:
          type: array
          description: 부정적인 결과가 반환된 플랫폼입니다.
          items:
            $ref: '#/components/schemas/SocialFootprintPlatform'
        categories:
          type: object
          description: 플랫폼 카테고리별 등록 수 및 비율입니다.
          additionalProperties:
            $ref: '#/components/schemas/SocialFootprintCategorySummary'
        profiles:
          type: object
          description: 플랫폼에서 프로필 세부 정보를 제공하는 경우, 플랫폼을 키로 하는 플랫폼별 프로필 세부 정보입니다.
          additionalProperties:
            $ref: '#/components/schemas/SocialFootprintProfile'
    PhoneIntelligence:
      type: object
      description: >-
        정규화된 전화번호 인텔리전스 블록입니다. 이 조회에 대해 인텔리전스 애드온이 실행된 경우에만 존재하며, 존재하는 경우 동일한 값을
        가진 `enrichment` 별칭으로도 노출됩니다.
      properties:
        score:
          type: number
          nullable: true
          description: 정규화된 0-100 위험 점수입니다. 높을수록 위험합니다.
        phone_type_risk:
          type: string
          nullable: true
          description: 점수에서 파생된 `Low`, `Medium` 또는 `High`.
        phone_trust_index:
          type: number
          nullable: true
          description: 점수가 높을수록 좋은 대시보드를 위한 점수를 반전한 값입니다.
        network_stability_index:
          type: number
          nullable: true
          description: 회선 네트워크의 안정성입니다.
        is_disposable:
          type: boolean
          nullable: true
          description: 번호가 일회용 또는 가상 번호로 보이는 경우 `true`입니다.
        is_ported:
          type: boolean
          nullable: true
          description: 번호의 통신사가 변경된 경우 `true`입니다.
        is_recently_ported:
          type: boolean
          nullable: true
          description: 최근에 번호 이동이 발생한 경우 `true`입니다.
        carrier_type:
          type: string
          nullable: true
          description: '조회 결과로 보고된 회선 분류입니다(예: `mobile`).'
        reason_codes:
          type: array
          items:
            type: object
            properties:
              code:
                type: string
                description: >-
                  신호의 안정적인 Didit 식별자입니다(예: `IR-5AC67A32`). 불투명한 값이므로 구문 분석하지 말고
                  그룹화 및 필터링에만 사용하세요.
              value:
                nullable: true
                description: >-
                  위험 플래그(예: `voip`, `leaked`, `disposable`, `spam_trap`)의 경우 해당
                  값: boolean, 수준 또는 날짜입니다. 점수가 산정된 사유 코드의 경우 null입니다.
              direction:
                type: string
                enum:
                  - risk
                  - trust
                description: 신호가 위험을 높였는지 또는 신뢰도를 높였는지 여부입니다.
              message:
                type: string
                description: 신호에 대한 사람이 읽기 쉬운 영어 설명입니다.
              impact_level:
                type: string
                nullable: true
                description: >-
                  시그널이 점수를 얼마나 크게 변동시켰는지 나타내며, 예를 들어 `low`, `medium`, `high` 등이
                  있습니다.
          description: >-
            점수를 설명하는 신호 목록으로, 각각 안정적인 Didit 코드, 방향, 메시지 및 영향 수준을 포함합니다. 새로운 코드가
            점진적으로 추가될 수 있으므로 알 수 없는 코드를 거부하지 마세요.
    SocialFootprintPlatform:
      type: object
      properties:
        platform:
          type: string
          description: 플랫폼 식별자입니다.
          example: whatsapp
        category:
          type: string
          description: >-
            플랫폼 카테고리(예: MESSAGING, SOCIAL_MEDIA, ECOMMERCE, PROFESSIONAL,
            EMAIL_PROVIDER)입니다.
          example: MESSAGING
        scope:
          type: string
          enum:
            - global
            - local
          description: 글로벌 플랫폼의 경우 `global`, 특정 지역 플랫폼의 경우 `local`.
          example: global
    SocialFootprintCategorySummary:
      type: object
      properties:
        registered:
          type: integer
          nullable: true
          description: 이 카테고리에서 가입이 확인된 플랫폼입니다.
          example: 2
        ratio:
          type: number
          format: float
          nullable: true
          description: 해당 카테고리에서 확인된 플랫폼 중 등록이 있는 플랫폼의 비율(0.0-1.0)입니다.
          example: 0.6667
    SocialFootprintProfile:
      type: object
      properties:
        name:
          type: string
          nullable: true
          description: 플랫폼에서 제공하는 경우 프로필 이름입니다.
        photo:
          type: string
          nullable: true
          description: 플랫폼에서 제공하는 경우 프로필 사진 URL입니다.
        about:
          type: string
          nullable: true
          description: 플랫폼에서 제공하는 경우 프로필 소개/약력 텍스트입니다.
        privacy_status:
          type: string
          nullable: true
          enum:
            - PUBLIC
            - PRIVATE
            - null
          description: 플랫폼에서 제공하는 경우 프로필 공개 여부입니다.
        business_account:
          type: boolean
          nullable: true
          description: 플랫폼에서 정보를 제공하는 경우, 프로필이 비즈니스 계정인지 여부입니다.
  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.