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

# Didit API 오류 코드: 상태 코드, 응답 본문 및 해결 방법

> Didit API의 모든 오류를 정리했습니다. HTTP 상태 코드, 응답 본문 구조, 안정적인 오류 코드, 재시도해도 안전한 실패 유형을 401, 403, 409, 429, 5xx별로 안내합니다.

Didit API는 실패를 HTTP 상태 코드로 알리며, 거의 모든 경우 JSON 본문도 함께 반환합니다.
이 페이지에서는 각 상태 코드의 의미, 본문의 형식, 분기 처리에 사용할 수 있는 `code` 값, 그리고 재시도해도 안전한 실패가 무엇인지 설명합니다.
메시지 텍스트는 바뀔 수 있으므로 상태 코드를 먼저 확인하고, `code`가 있으면 그 값을 기준으로 판단하십시오.

## 상태 코드

| 상태 | 의미 | 조치 | 재시도 여부 |
| - | - | - | - |
| `400` | 요청이 잘못되었습니다. 필드 검증에 실패했거나 이미지 또는 문서를 읽을 수 없습니다 | 본문에 명시된 항목 수정 | 수정한 후 |
| `401` | 전송한 키가 잘못되었거나, 형식이 맞지 않거나, 철회되었거나 만료되었습니다 | `DIDIT_API_KEY` 확인 또는 새 키 생성 | 수정한 후 |
| `402` | 검사 비용을 결제할 수 없어 검사가 실행되지 않았습니다 | 잔액 충전 | 충전한 후 |
| `403` | 키가 전송되지 않았거나, 키에 이 리소스 또는 작업에 대한 접근 권한이 없거나, 요청이 키의 IP 목록 외부에서 왔거나, 잔액으로 호출 비용을 감당할 수 없습니다 | 본문을 읽은 다음 [API 키 오류](#api-키-오류) 및 [크레딧 부족](#크레딧-부족) 참조 | 수정한 후 |
| `404` | 리소스가 존재하지 않거나, 세션이 키의 워크플로 또는 상태 범위를 벗어났습니다 | ID와 키의 제한 사항 확인 | 아니요 |
| `409` | 요청이 현재 상태와 충돌합니다. 예를 들어 이미 사용된 `Idempotency-Key`를 재사용했거나 이미 실행된 단계를 다시 요청한 경우입니다 | `code`를 읽고 상태 다시 불러오기 | `code`에 따라 다름 |
| `410` | 리소스가 만료되었습니다. 예를 들어 세션이나 초대와 같은 리소스입니다 | 새로 생성 | 아니요 |
| `415` | 요청 본문이 JSON이 아닙니다 | `Content-Type: application/json` 전송 | 수정한 후 |
| `422` | 지갑 주소가 둘 이상의 블록체인에 해당하므로 스크리닝도 과금도 이루어지지 않았습니다 | `blockchain`을 `candidate_chains` 중 하나로 설정하여 다시 전송 | 수정한 후 |
| `429` | 속도 제한 또는 할당량에 도달했습니다 | `Retry-After`만큼 기다리기. [속도 제한](https://docs.didit.me/ko/integration/rate-limiting.md) 참조 | 예, 기다린 후 |
| `500` | Didit 측의 예기치 않은 오류입니다 | 백오프를 적용하여 재시도하고, 계속 발생하면 지원팀에 문의 | [재시도](#재시도와-멱등성) 참조 |
| `502` | Didit이 의존하는 서비스가 오류를 반환했습니다 | `code` 읽기 | [재시도](#재시도와-멱등성) 참조 |
| `503` | Didit이 의존하는 서비스를 일시적으로 사용할 수 없습니다 | `code`를 읽고 다시 시도 | [재시도](#재시도와-멱등성) 참조 |

## 오류 본문

오류 본문은 하나의 공통 구조를 따르지 않으므로 방어적으로 처리해야 합니다.
구조는 엔드포인트 계열에 따라 다릅니다:

| 형식 | 나타나는 경우 | 예시 |
| - | - | - |
| `detail` | 인증, 리소스 없음, 속도 제한을 포함한 대부분의 오류 | `{"detail": "You do not have permission to perform this action."}` |
| `detail`과 `code` | 안정적인 코드가 있는 오류 | `{"detail": "This application was deleted.", "code": "application_deleted"}` |
| 필드 오류 | 입력 검증 | `{"workflow_id": ["This field is required."]}` |
| `non_field_errors` | 여러 필드에 걸친 검증 | `{"non_field_errors": ["..."]}` |
| JSON 배열 | 일부 검증 오류, 예를 들어 시뮬레이션 호출 | `["Scenario can only be armed before the verification starts."]` |
| `error` | 대부분의 독립형 API | `{"error": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"}` |
| `error`와 `code` | 독립형 API의 이미지 오류 | `{"error": "...", "code": "invalid_image"}` |
| `detail`을 포함한 코드형 `error` | 디지털 ID 지갑 인증 | `{"error": "insufficient_credits", "detail": "..."}` |

`500` 응답에는 JSON 본문이 전혀 없을 수 있으므로, 파싱할 수 없는 본문도 처리해야 합니다.

```javascript theme={null}
const raw = await response.text();
let body = {};
try {
  body = JSON.parse(raw);
} catch {
  // A 5xx response may not be JSON: rely on response.status.
}
const code = body.code ?? null;
const message = body.detail ?? body.error ?? (Array.isArray(body) ? body[0] : raw);
```

## API 키 오류

| 전송한 값 | 상태 | `detail` |
| - | - | - |
| `x-api-key` 헤더 없음 | `403` | `You do not have permission to perform this action.` |
| 잘못되었거나, 형식이 맞지 않거나, 취소된 키 | `401` | `Authentication credentials were not provided or are invalid.` |
| 만료된 키 | `401` | `This API key has expired.` |
| IP 목록에 없는 곳에서 사용한 키 | `403` | `This API key can't be used from this IP address.` |
| 범위가 제한된 키로, 이 리소스 또는 작업에 접근 권한이 없는 경우 | `403` | `This API key has no access to this endpoint.` |
| 일부 워크플로 또는 상태로 제한된 키로, 사용할 수 없는 endpoint를 호출한 경우 | `403` | `This API key only reaches sessions inside its workflow or status limits, so it can't use this endpoint.` |
| 일부 워크플로 또는 상태로 제한된 키로, 제한 범위 밖의 세션을 호출한 경우 | `404` | `Session not found.` |
| 애플리케이션이 방금 삭제된 키 | `403` | `This application was deleted.`, 그리고 `"code": "application_deleted"` |

애플리케이션이 삭제된 후 몇 분 동안은 API가 `application_deleted`로 응답하며, 그 이후에는 잘못된 키와 마찬가지로 키를 거부합니다.
재시도하지 마십시오. 애플리케이션과 키가 모두 삭제되었습니다.

키와 키의 제한 사항이 적용되는 방식은 [API 인증](https://docs.didit.me/ko/getting-started/api-authentication.md) 및 [API 키](https://docs.didit.me/ko/console/api-keys.md)를 참조하십시오.

## 크레딧 부족

API 계열마다 잔액 부족을 다른 방식으로 알립니다:

| 호출 | 상태 | 본문 |
| - | - | - |
| `POST /v3/session/` | `400` | `{"detail": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"}` |
| 대부분의 독립형 API | `403` | `{"error": "You don't have enough credits to perform this request. Please top up at https://business.didit.me"}` |
| `POST /v3/bank/account-check/` | `402` | `{"detail": "...", "code": "insufficient_credits"}` |
| 디지털 ID 지갑 인증 | `403` | `{"error": "insufficient_credits", "detail": "..."}` |
| 거래, Travel Rule 및 주소 검증 | `403` | `{"detail": "...", "code": "insufficient_credits"}` |

계약 고객의 경우, 조직의 유료 서비스가 일시 중지된 동안에는 세션 생성 요청이 `403`과 함께 `"code": "contract_billing_suspended"`를 반환합니다.
[샌드박스 애플리케이션](https://docs.didit.me/ko/integration/sandbox-testing.md)은 과금되지 않으므로 이러한 검사를 건너뜁니다.

## 오류 코드

이 `code` 값은 변하지 않으므로 분기 처리에 사용할 수 있습니다.
대부분은 `detail` 옆에 제공됩니다. 디지털 ID 지갑 인증에서는 `error` 값이 코드입니다.

### 접근 및 결제

| 코드 | 상태 | 의미 |
| - | - | - |
| `insufficient_credits` | `402`, `403` | 잔액으로 호출 비용을 감당할 수 없습니다 |
| `contract_billing_suspended` | `403` | 이 조직의 유료 서비스가 일시 중지되었습니다 |
| `contract_rate_missing` | `402`, `403` | 계약에 이 검사에 대한 요금이 없습니다 |
| `application_deleted` | `403` | 키의 애플리케이션이 삭제되었습니다 |
| `organization_deleted` | `403` | 키의 조직이 삭제되었습니다 |
| `event_monitoring_disabled` | `403` | 이 애플리케이션에서 이벤트 수집이 켜져 있지 않습니다 |
| `networks_not_entitled` | `403` | 이 조직에서는 사기 네트워크를 사용할 수 없습니다 |

### 요청 및 멱등성

| 코드 | 상태 | 의미 |
| - | - | - |
| `invalid_image` | `400` | 이미지를 사용할 수 없습니다 |
| `return_url_invalid` | `400` | 반환 URL이 허용되지 않습니다 |
| `idempotency_key_invalid` | `400` | `Idempotency-Key`가 255자를 초과합니다 |
| `idempotency_key_reused` | `409` | 이 키는 다른 본문과 함께 이미 사용되었습니다 |
| `idempotency_key_in_progress` | `409` | 이 키의 첫 번째 요청이 아직 실행 중입니다. `Retry-After`가 지정하는 시간까지 기다리세요 |
| `verification_in_progress` | `409` | 사용자가 지금 이 인증을 완료하고 있어 취소할 수 없습니다. `Retry-After`가 지정하는 시간까지 기다리세요 |
| `feature_override_not_pending` | `409` | 재정의가 이미 적용되었거나 취소되었습니다 |

### 은행, 전화번호 및 위험 검사

| 코드 | 상태 | 의미 |
| - | - | - |
| `invalid_account_input` | `400` | 계좌 정보가 올바르지 않습니다 |
| `country_not_covered` | `404` | 이 검사는 해당 국가 또는 해당 유형의 계좌를 지원하지 않습니다 |
| `bank_not_covered` | `404` | 이 검사는 해당 은행에 도달하지 않습니다 |
| `bank_verification_not_available` | `404` | 은행 인증을 사용할 수 없습니다 |
| `account_check_unavailable` | `503` | 검사를 일시적으로 사용할 수 없으며 요청에 대한 요금이 청구되지 않았습니다 |
| `phone_provider_unavailable` | `502` | 전화번호 인증을 일시적으로 사용할 수 없습니다. 요금이 청구되지 않으며 시도 횟수도 차감되지 않습니다 |
| `risk_lookup_unavailable` | `502` | 위험 조회를 일시적으로 사용할 수 없으며 요청에 대한 요금이 청구되지 않았습니다 |

### 기업 확인(KYB)

| 코드 | 상태 | 의미 |
| - | - | - |
| `kyb_registry_provider_unavailable` | `502` | 법인 등기부를 일시적으로 사용할 수 없습니다 |
| `kyb_registry_country_unsupported` | `400` | 등기부 검색은 이 국가를 지원하지 않습니다 |
| `kyb_registry_search_limit_reached` | `429` | 애플리케이션이 시간당 유료 검색 600건의 한도에 도달했습니다 |
| `kyb_session_not_writable` | `409` | 세션이 종료되었습니다 |
| `kyb_step_mismatch` | `409` | 세션이 다른 단계에 있습니다. `next_step`에 해당 단계가 표시됩니다 |
| `kyb_no_party_drafts` | `409` | 제출할 당사자 초안이 없습니다 |
| `kyb_parties_already_submitted` | `409` | 당사자가 이미 제출되었습니다 |
| `kyb_party_kyc_session_not_deleted` | `409` | 당사자의 인증이 아직 활성 상태이므로 다시 생성할 수 없습니다 |

### 디지털 ID 지갑

| 코드 | 상태 | 의미 |
| - | - | - |
| `wallet_unavailable` | `403` | 이 지갑은 애플리케이션에서 사용할 수 없습니다 |
| `wallet_provider_unavailable` | `502` | 지갑을 시작하지 못했으며 아무것도 생성되지 않았습니다 |
| `wallet_not_configured` | `503` | 이 환경에서는 지갑에 연결할 수 없습니다 |

### 보고서 및 케이스

| 코드 | 상태 | 의미 |
| - | - | - |
| `report_deletion_pending` | `409` | 보고서를 삭제하는 중입니다. 파일 삭제를 완료하려면 삭제를 다시 요청하세요 |
| `report_storage_unavailable` | `503` | 보고서 파일을 삭제할 수 없었습니다. 삭제를 다시 요청하세요 |
| `wallet_address_deletion_incomplete` | `503` | 저장된 파일 하나를 삭제할 수 없어 삭제가 중단되었습니다. 다시 시도하세요 |
| `case_request_not_waiting` | `409` | 이 요청은 더 이상 고객의 응답을 기다리지 않으므로 알림을 보낼 대상이 없습니다 |
| `case_request_reminder_too_soon` | `429` | 리마인더가 최근에 전송되었습니다. `retry_at`에 다음 리마인더를 보낼 수 있는 시점이 표시됩니다 |

### 전자 서명

| 코드 | 상태 | 의미 |
| - | - | - |
| `signature_not_found` | `404` | 서명이 존재하지 않습니다 |
| `signature_field_not_found` | `404` | 서명 필드가 존재하지 않습니다 |
| `signature_not_signed` | `404`, `409` | 문서에 서명이 완료되지 않았습니다 |

세션 생성 시 아래 문서 문제는 상태 `400`과 함께 문제가 있는 필드의 값으로 반환됩니다. 예: `{"sign": "signature_document_changed"}`

| 값 | 의미 |
| - | - |
| `signature_document_changed` | 문서가 처음 전송된 문서와 다릅니다 |
| `signature_document_not_supported` | 문서 형식이 지원되지 않습니다 |
| `signature_document_conversion_failed` | 문서를 변환할 수 없었습니다 |
| `field_anchor_not_found` | 문서에서 필드의 텍스트 앵커를 찾을 수 없습니다 |
| `field_value_missing` | 필드에 값이 없습니다 |

### webhook

| 코드 | 상태 | 의미 |
| - | - | - |
| `webhook_url_missing` | `400` | 전송에 기록된 URL이 없어 아무것도 전송되지 않습니다 |
| `invalid_webhook_payload` | `400` | webhook 데이터의 형식이 올바르지 않습니다 |
| `webhook_resend_error` | `400` | 저장된 전송에 다시 서명할 수 없었거나 시도를 완료할 수 없었습니다 |

## 재시도와 멱등성

일부 실패는 반복해도 안전하지만, 그렇지 않은 실패도 있습니다.

* **`429`:** `Retry-After` 헤더에서 지정한 시간만큼 기다린 뒤 재시도합니다.
* **`502` 및 `503`:** endpoint 참조 문서에 과금되지 않았다고 명시된 경우(전화번호, 이메일, 은행 및 위험 확인이 이에 해당합니다)에는 백오프를 적용해 재시도합니다.
* **`POST /v3/database-validation/`의 `502`:** 이 상태 코드만으로는 일시적인 실패를 뜻하지 않으므로, 먼저 각 `validation_errors` 항목을 확인합니다.
* **삭제 요청의 `503`:** `200`이 반환될 때까지 같은 요청을 반복합니다.
* **기타 `4xx`:** 같은 요청은 같은 방식으로 계속 실패하므로, 먼저 요청을 수정합니다.

`POST /v3/aml/`과 디지털 ID 지갑 인증은 최대 255자의 `Idempotency-Key` 헤더를 받습니다.
같은 키와 본문으로 요청을 반복하면 저장된 응답이 다시 반환되므로, 작업과 과금은 한 번만 실행됩니다.
같은 키에 다른 본문을 보내면 `409`가 반환됩니다. 첫 번째 요청이 아직 처리 중이면 지갑 endpoint는 `Retry-After`와 함께 `409`를 반환합니다.

`POST /v3/session/`에는 멱등성 키가 없습니다. 따라서 생성 요청이 시간 초과되면 다른 세션을 생성하기 전에 `vendor_data`로 세션 목록을 조회하십시오.

## 관련 문서

* [요청 속도 제한](https://docs.didit.me/ko/integration/rate-limiting.md): 제한, 헤더 및 `429` 본문.
* [API 인증](https://docs.didit.me/ko/getting-started/api-authentication.md): API 키를 전송하는 방법.
* [샌드박스 테스트](https://docs.didit.me/ko/integration/sandbox-testing.md): 실제 데이터나 과금 없이 결과를 재현합니다.
* [webhook](https://docs.didit.me/ko/integration/webhooks.md): 전송, 재시도 및 순서.


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