> ## 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가 제공합니다.

전용 지갑 endpoint를 사용하면 자체 애플리케이션에서 사용자의 신원을 확인할 수 있습니다.
워크플로를 생성하거나 게시할 필요가 없으며 `workflow_id`를 제공할 필요도 없습니다.
백엔드가 인증을 시작하고 결과를 조회하며, 사용자 인터페이스가 지갑에서 요구하는 인증 절차를 사용자가 완료하도록 안내합니다.

> [!NOTE]
>
> API 연동에서도 사용자가 직접 인증하고 자신의 신원 정보 공유를 승인해야 합니다.
> 이 상호작용 없이 개인 식별자를 제출하는 것만으로는 사용자를 인증할 수 없습니다.

## 인증 작동 방식

1. 백엔드가 [지갑 카탈로그](https://docs.didit.me/ko/standalone-apis/digital-id-wallet-catalog.md)를 확인한 다음, 애플리케이션 API 키를 사용하여 사용 가능한 지갑의 시작 endpoint를 호출합니다.
2. Didit이 인증 참조 값과 사용자가 수행해야 할 작업을 반환합니다.
3. 애플리케이션이 인증 페이지를 열거나 지갑의 승인 안내를 표시합니다.
4. 사용자가 지갑으로 인증합니다.
5. 백엔드가 검증된 결과를 조회하고 완료 알림을 처리합니다.

지갑 인증은 비동기로 진행됩니다.
시작 요청이 성공했다는 것은 인증이 시작되었다는 뜻이며, 신원이 검증되었다는 뜻이 아닙니다.
사용자를 인증된 것으로 처리하기 전에 항상 최종 결과를 확인하십시오.

## 백엔드 연동

[디지털 ID 지갑 목록 조회](https://docs.didit.me/ko/standalone-apis/digital-id-wallet-catalog.md)를 사용하여 애플리케이션에 필요한 현재 endpoint, 필수 필드 및 사용 가능 여부를 확인하십시오.

`x-api-key`는 백엔드에서만 보관하십시오.
브라우저 번들이나 모바일 애플리케이션에 넣으면 안 됩니다.
새로운 인증 시도마다 고유한 `Idempotency-Key`를 사용하고, 같은 시작 요청을 재시도할 때는 그 키를 재사용하십시오.
요청 내용을 바꾼 채 키를 재사용하면 새로운 인증 시도가 아니라 충돌로 처리됩니다.

지갑마다 고유한 시작 URL이 있으며, Finnish Trust Network의 경우 `/v3/id-verification/wallets/ftn/`입니다.
`request_id`는 후속 작업에서 이 독립형 인증을 식별합니다.
자체 참조용으로는 최대 2,000 UTF-8바이트의 `vendor_data`를 사용하고, 선택 사항인 JSON 객체에는 `metadata`를 사용하십시오.
두 값 모두 결과 및 완료 webhook과 함께 반환됩니다.

| 작업 | endpoint |
| - | - |
| 상태 및 결과 조회 | `GET /v3/id-verification/wallets/verifications/{request_id}/` |
| 휴대폰 승인 폴링 | `POST /v3/id-verification/wallets/verifications/{request_id}/poll/` |
| Digital Credentials 지갑 응답 제출 | `POST /v3/id-verification/wallets/verifications/{request_id}/response/` |
| 대기 중인 인증 취소 | `POST /v3/id-verification/wallets/verifications/{request_id}/cancel/` |

이 작업들은 인증을 시작한 애플리케이션의 API 키를 사용합니다.
폴링 및 인증 가능 여부는 선택한 지갑에 따라 달라집니다.

취소는 대기 중인 인증을 요금 청구 없이 거절하며, 이미 완료된 인증은 변경 없이 그대로 반환합니다.
Smart-ID 및 Mobile-ID의 경우, 승인 상태를 확인하는 폴링이 진행 중일 때 도착한 취소 요청은 그 폴링을 몇 초 동안 기다립니다.
그 후 인증을 거절하거나, 사용자가 이미 승인했다면 `verified`로 반환합니다.
사용자가 그 시점에 완료 중인 인증은 취소할 수 없습니다. 이때 응답은 `error: "verification_in_progress"`와 `Retry-After` 헤더가 포함된 `409`입니다.
헤더에 표시된 초만큼 기다린 후 다시 요청하여 완료된 결과를 확인하십시오.

## 반환 대상 등록

리디렉션 방식의 지갑은 인증이 끝난 후 사용자를 애플리케이션으로 되돌려 보냅니다.
인증을 시작하기 전에 정확한 호스트 이름을 등록하십시오:

```bash theme={null}
curl --request PATCH \
  --url https://verification.didit.me/v3/webhook/ \
  --header 'x-api-key: YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{"allowed_return_hosts": ["app.example.com"]}'
```

그런 다음 시작 요청에 HTTPS `return_url`을 보내십시오. 예: `https://app.example.com/identity/complete`.
`allowed_return_hosts`에는 스킴, 경로, 와일드카드 없이 호스트 이름만 입력하십시오.
사용하는 각 서브도메인을 별도로 등록하십시오. 최대 20개의 호스트 이름을 등록할 수 있습니다.
`allowed_return_hosts`를 업데이트하면 등록된 목록이 교체되므로, 유지하려는 모든 호스트 이름을 포함하십시오.
`GET /v3/webhook/`은 현재 목록을 반환합니다. [Webhook 구성](https://docs.didit.me/ko/sessions-api/management-api.md#webhook-구성)을 참조하십시오.
반환 대상을 등록하기 위해 워크플로나 화이트 라벨 도메인은 필요하지 않습니다.
반환 대상은 브라우저에 표시되는 반환 페이지이며, 완료 webhook은 백엔드용으로 별도로 구성하십시오.

## 예시: Finnish Trust Network

반환 호스트 이름을 등록한 후 Finnish Trust Network 인증을 시작하십시오:

```bash theme={null}
curl --request POST \
  --url https://verification.didit.me/v3/id-verification/wallets/ftn/ \
  --header 'x-api-key: YOUR_API_KEY' \
  --header 'Idempotency-Key: your-unique-attempt-key' \
  --header 'Content-Type: application/json' \
  --data '{
    "country": "FIN",
    "return_url": "https://app.example.com/identity/complete",
    "vendor_data": "your-customer-reference"
  }'
```

반환된 `request_id`를 저장하고, `type`이 `redirect`이면 사용자의 브라우저를 `wallet_verification.next_action.url`로 보내십시오.
사용자가 돌아오면 백엔드에서 결과를 조회하십시오:

```bash theme={null}
curl --request GET \
  --url https://verification.didit.me/v3/id-verification/wallets/verifications/REQUEST_ID/ \
  --header 'x-api-key: YOUR_API_KEY'
```

`wallet_verification.outcome`을 확인하십시오:

| 결과 | 의미 |
| - | - |
| `pending` | 인증이 아직 진행 중입니다. |
| `verified` | 인증이 완료되었고 반환된 신원이 검증되었습니다. |
| `cancelled` | 사용자 또는 애플리케이션이 인증 시도를 취소했습니다. |
| `timeout` | 인증 기간이 만료되었습니다. |
| `failed` | 인증 또는 신원 확인에 실패했습니다. |

실제 신원 확인의 경우, 결과가 `verified`이고 `simulated`가 `false`일 때만 신원 정보를 사용하십시오.
대기 중인 응답에는 다음 작업이 포함될 수 있습니다. 최종 상태의 응답에는 다음 작업이 없습니다.

## 인증 방식

**리다이렉트 지갑**은 인증 URL을 반환합니다.
사용자의 브라우저에서 해당 URL을 열고, 사용자가 지갑의 인증 절차를 완료한 뒤 등록된 반환 대상으로 돌아오게 하세요.
반환 URL 파라미터를 신원 증명으로 신뢰하지 말고, 결과는 백엔드에서 읽으세요.

**Smart-ID와 Mobile-ID**는 사용자의 휴대폰에 승인 요청 창을 사용합니다.
인터페이스에서 필요한 개인 식별자를 수집하세요. Mobile-ID에는 연결된 휴대폰 번호도 필요합니다.
비교 코드를 표시하고, 휴대폰에 표시된 코드와 일치할 때만 승인하도록 안내하세요.
PIN은 지갑 또는 휴대폰의 요청 창에만 입력해야 하며, 양식이나 API 요청에는 절대 넣지 마세요.
반환된 `poll_interval_seconds` 간격으로 백엔드에서 폴링하여 요청 창의 피드백을 확인하세요.
Didit도 대기 중인 휴대폰 승인을 백그라운드에서 확인하므로, 사용자가 페이지를 닫은 뒤에도 완료 결과가 webhook에 도착할 수 있습니다.

**Google Wallet**은 리다이렉트 없이 Digital Credentials API를 통해 귀하의 자체 페이지 또는 앱에서 요청합니다. 자세한 내용은 [Digital Credentials 지갑(Google Wallet)](#digital-credentials-지갑-google-wallet)을 참조하세요.

사용 가능한 상호작용은 선택한 지갑에 따라 달라집니다.
모든 지갑이 임베디드 양식, QR 코드 또는 브라우저 없는 인증을 지원한다고 가정하지 마세요.

## Digital Credentials 지갑(Google Wallet)

Google Wallet은 W3C Digital Credentials API를 사용하여 웹 페이지 또는 Android 앱에서 직접 요청합니다.
리다이렉트, Didit 호스팅 페이지, Didit QR 코드는 없습니다.
프로덕션과 샌드박스에서 모두 사용할 수 있습니다.
샌드박스 애플리케이션은 등록이 필요 없습니다. 각 프로덕션 애플리케이션은 Google Wallet을 사용하기 전에 콘솔에서 한 번 등록해야 합니다(신분증 인증 단계, Google Wallet 행, **Google에 등록**).
지금 애플리케이션이 시작할 수 있는 항목은 [디지털 ID 지갑 목록](https://docs.didit.me/ko/standalone-apis/digital-id-wallet-catalog.md)에서 확인하세요.

**1. origin으로 시작하기**

백엔드에서 사용자의 `country`(`USA`, `GBR`, `BRA`, `SGP` 또는 `TWN`)와 지갑에 요청할 `origin`을 담아 `POST /v3/id-verification/wallets/google-wallet/`를 호출합니다.
`origin`은 페이지의 HTTPS origin입니다(예: `https://app.example.com`). 호스트는 [등록된 반환 호스트 이름](#반환-대상-등록) 또는 화이트 라벨 도메인 중 하나여야 합니다.
Android 앱의 경우 `android:apk-key-hash:` 뒤에 앱 서명 인증서의 base64 SHA-256 값을 패딩 없이 붙입니다.
지갑은 다른 origin에서 온 요청을 거부합니다.
`return_url`은 없습니다.

```bash theme={null}
curl --request POST \
  --url https://verification.didit.me/v3/id-verification/wallets/google-wallet/ \
  --header 'x-api-key: YOUR_API_KEY' \
  --header 'Idempotency-Key: your-unique-attempt-key' \
  --header 'Content-Type: application/json' \
  --data '{
    "country": "USA",
    "origin": "https://app.example.com",
    "vendor_data": "your-customer-reference"
  }'
```

**2. 사용자 제스처 안에서 지갑에 요청하기**

응답에는 `wallet_verification.interaction = "digital_credentials"`와 `next_action.type = "request_digital_credential"`이 포함됩니다.
처음 사용한 `origin`에서 탭이나 클릭을 통해 `next_action.digital_credentials.request`를 브라우저 또는 Android Credential Manager에 전달하세요.
데스크톱에서는 지갑이 다른 기기에 있을 경우 브라우저가 자체 QR 코드를 표시합니다.

**3. 지갑이 반환한 값 제출하기**

반환된 `{protocol, data}`를 백엔드로 보낸 다음, 백엔드에서 `{"response": {...}}` 형태로 `POST /v3/id-verification/wallets/verifications/{request_id}/response/`에 제출하세요.
요청은 한 번만 제출할 수 있습니다. 두 번째 제출은 이미 결정된 인증을 반환합니다.

**4. 결과 확인하기**

제출 응답은 결정된 인증입니다.
`GET /v3/id-verification/wallets/verifications/{request_id}/`로 조회하거나 완료 webhook으로 받을 수도 있습니다.

브라우저에서 클릭 핸들러로 지갑에 요청합니다:

```javascript theme={null}
// start = the JSON your backend returned from the start request
const request = start.wallet_verification.next_action.digital_credentials.request;

button.addEventListener("click", async () => {
  try {
    const credential = await navigator.credentials.get({ digital: request });
    // Send {protocol, data} to your backend, which calls POST .../response/ with your API key.
    await fetch("/api/wallet-response", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        request_id: start.request_id,
        response: { protocol: credential.protocol, data: credential.data },
      }),
    });
  } catch (error) {
    // NotAllowedError or AbortError: the person cancelled. NotSupportedError: this browser cannot ask the wallet.
    console.error(error.name);
  }
});
```

브라우저가 지원하는 경우에만 이 방식을 제공하세요. 예를 들어 `"DigitalCredential" in window`가 true인 경우입니다.
`navigator.credentials.get`은 사용자 제스처 안에서 실행되어야 하므로, 비동기 단계 뒤가 아니라 클릭 핸들러에서 호출하세요.

Android에서는 같은 요청과 함께 Jetpack Credential Manager(`androidx.credentials` 1.5.0 이상)를 사용하세요:

```kotlin theme={null}
val option = GetDigitalCredentialOption(
    requestJson = JSONObject(request).toString(), // next_action.digital_credentials.request
)
val result = credentialManager.getCredential(activity, GetCredentialRequest(listOf(option)))
val credentialJson = (result.credential as DigitalCredential).credentialJson // {"protocol": ..., "data": {...}}
// Send credentialJson, parsed as JSON, to your backend as the "response" body.
```

처리해야 할 오류:

| 오류 | 위치 | 의미 |
| - | - | - |
| `origin_invalid` | 시작, `400` | `origin`이 HTTPS origin 또는 Android 앱 origin이 아닙니다. |
| `origin_not_allowed` | 시작, `400` | origin의 호스트가 애플리케이션에 등록되어 있지 않습니다. `allowed_return_hosts`에 등록하세요. |
| `not_a_digital_credentials_wallet` | 제출, `409` | 이 인증은 지갑 응답을 받지 않습니다. |

자격 증명 검증에 실패하면 오류 응답이 아니라 `failed` 결과가 포함된 결정된 인증이 반환됩니다.
인증 요청에 포함된 필드만 지갑에서 전달되며, 결과에는 지갑이 반환한 신원 속성이 포함됩니다.
Google Wallet ID 패스나 미국 주 모바일 운전면허증은 초상 사진을 반환하지 않습니다.

샌드박스 애플리케이션에서는 같은 단계로 흐름이 시뮬레이션되며 `simulated: true`를 반환합니다.
제출된 응답은 `sandbox_scenario`에 따라 인증을 결정하므로, 실제 자격 증명 없이도 전체 브라우저 또는 앱 흐름을 구현할 수 있습니다.

## 완료 webhook

`status.updated`에 대한 애플리케이션 webhook 대상을 [webhook 연동 가이드](https://docs.didit.me/ko/integration/webhooks.md)를 사용해 구성하세요.
여기서 설명하는 결정 구조에는 `webhook_version: "v3"`을 사용하세요.
처리하기 전에 백엔드에서 webhook 서명을 검증하세요.
webhook의 `session_id`는 지갑 API가 반환한 `request_id`와 일치합니다.
완료된 지갑 신원은 `verification_method: "wallet"`과 함께 webhook의 `decision.id_verifications` 배열에 나타납니다.
이 식별자를 사용해 전용 지갑 API 결과를 조회할 수도 있습니다.

승인 및 거부 알림을 처리하세요. 취소되었거나 만료된 인증도 포함됩니다.
실패한 전송은 재시도되므로 webhook 핸들러를 멱등성 있게 만드세요.
브라우저 반환은 완료 webhook이 아니며, 그 쿼리 파라미터는 신원 증명이 아닙니다.

## 반환되는 신원 정보

이름과 생년월일이 반환되는 경우에는 정규화된 신원 정보 필드를 사용합니다.
지갑별 속성은 선택한 지갑이 공유하는 신원 정보를 설명합니다.
사용 가능한 속성은 지갑과 국가에 따라 다릅니다.
신원 인증이 완료되었다고 해서 초상 사진, 주소 또는 요청한 다른 속성을 모두 사용할 수 있다는 뜻은 아닙니다.

## 샌드박스에서 테스트

Didit 샌드박스 모드의 애플리케이션은 지갑 제공업체에 연결하거나 크레딧을 청구하지 않고 지갑 인증을 시뮬레이션합니다.
응답에는 이러한 요청이 `wallet_verification.simulated: true`로 표시됩니다.
시뮬레이션된 승인은 샘플 데이터이며, 실제 신원이 검증되었음을 의미하지 않습니다.

리디렉션 방식 지갑의 경우 반환된 URL을 따라가 콜백을 실행하고 애플리케이션으로 돌아오는지 확인합니다.
Smart-ID 또는 Mobile-ID의 경우 폴링 endpoint를 사용해 시뮬레이션된 승인을 완료합니다. 휴대폰으로는 알림이 전송되지 않습니다.
실패 처리를 테스트하려면 요청을 시작할 때 `sandbox_scenario`를 `wallet_cancelled`, `wallet_timeout` 또는 `wallet_provider_error`로 설정합니다.
프로덕션 환경의 애플리케이션은 `sandbox_scenario`를 거부합니다.

Didit 샌드박스 시뮬레이션은 제공업체 자체의 테스트 환경에서 테스트하는 것과는 별개입니다.
시뮬레이션에 성공했다고 해서 제공업체 접근이 실제로 가능하다거나 프로덕션에서 사용할 수 있다는 것은 아닙니다.

### ConnectID 제공업체 샌드박스

ConnectID의 제공업체 샌드박스는 테스트 은행을 사용하며, Didit 샌드박스 시뮬레이션과는 별개입니다.
연동에 제공업체 샌드박스 접근이 설정되어 있으면 선택한 은행의 `authorisation_server_id`를 [ConnectID 시작 endpoint](https://docs.didit.me/ko/api-reference/digital-id-wallets/connectid.md)에 전달합니다.
ConnectID 은행 선택기가 반환한 ID를 사용하세요. 은행 URL이나 임의의 발급자는 보내지 마세요.
이 필드를 생략하면 기본 테스트 은행이 선택됩니다.
이 필드는 ConnectID 전용이며, 요청하는 신원 속성은 변경하지 않습니다.

초기 번들은 이름, 성, 생년월일을 요청합니다.
반환된 `next_action`을 따라 인증을 완료한 다음 인증 결과를 조회하거나 폴링합니다.
승인 상태가 포함된 완료된 결과만 인증이 성공했음을 확인합니다. 애플리케이션으로 돌아왔다는 사실만으로는 확인되지 않습니다.
ConnectID는 온보딩 및 인증 절차가 완료될 때까지 프로덕션에서 **출시 예정** 상태로 유지됩니다.

## 제공 여부 및 요금

endpoint 지원 범위와 프로덕션 지갑 활성화는 별개입니다.
지갑에 API 참조 페이지가 있더라도 라이브 인증에는 사용할 수 없을 수 있습니다.
라이브 인증 흐름을 구현하기 전에 지갑의 국가별 지원 범위와 프로덕션 상태를 확인하세요.

게시된 요금과 제공 여부는 [디지털 ID 지갑 요금](https://docs.didit.me/ko/getting-started/pricing.md#디지털-id-지갑-요금)을 참고하세요.
지갑 인증은 문서 캡처와 별도로 과금됩니다.

## 연동 방식 선택

주변 인터페이스와 애플리케이션 로직을 직접 관리하려면 이 API를 사용하세요.
Didit의 호스팅된 인증 흐름, 워크플로 규칙, 설정된 대체 단계를 사용하려면 [Sessions API](https://docs.didit.me/ko/sessions-api/create-session.md)를 사용하세요.
두 방식 모두 지갑의 인증 및 동의 절차가 필요합니다.


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