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

# 엔티티 webhook: 사용자 및 기업 이벤트

> Didit 사용자 및 기업 엔티티의 상태 전환과 프로필 업데이트를 실시간 webhook으로 받는 방법. payload 필드, 서명, 재시도를 설명합니다.



엔티티 Webhook 프롬프트
        프롬프트를 클립보드에 복사



      
      

\<pre>

\````# Goal — subscribe to entity-level webhooks and apply changes to my database

Entity webhooks fire whenever a User or Business entity changes its status or its profile data. Use them to keep your local mirror of Didit entities in sync.

\## Entity-level event catalog

\| `webhook_type` | Trigger |
\|---|---|
\| `user.status.updated` | User entity status changed (`ACTIVE` / `FLAGGED` / `BLOCKED`). Payload includes `previous_status`. |
\| `user.data.updated` | User entity profile / counters / metadata changed. Includes `changed_fields` and a `changes` map of `{previous, current}`. |
\| `business.status.updated` | Business entity status changed. Payload includes `previous_status`. |
\| `business.data.updated` | Business entity profile or aggregates changed. Includes `changed_fields` and `changes`. |

\`activity.created` is accepted in `subscribed_events` and by the Try Webhook tester, but Didit does not deliver it for live traffic. Do not build on it.

Session-level events (`status.updated`, `data.updated`) and transaction events (`transaction.created`, `transaction.status.updated`) live alongside but are separate — see /integration/webhooks for the full catalog.

\## Register a destination

\```bash
curl -X POST https://verification.didit.me/v3/webhook/destinations/ \
-H "x-api-key: $DIDIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"label": "Entity sync",
"url": "https://yourapp.com/webhooks/didit",
"webhook_version": "v3",
"subscribed_events": [
  "user.status.updated",
  "user.data.updated",
  "business.status.updated",
  "business.data.updated"
]
}'
\```

Persist the returned destination `secret_shared_key` — that's the HMAC signing key.

\## Payload shape

Entity payloads are flat: there is no `data` wrapper and no `event` key. Read `webhook_type`.

\```json
\{
"event_id": "7f3c2c1e-6a1d-4c36-9d8e-0d3b5f4e2a10",
"webhook_type": "user.status.updated",
"timestamp": 1776333600,
"created_at": 1776333594,
"application_id": "0c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
"environment": "live",
"vendor_user_id": "9c7d2a30-...",
"vendor_data": "user-42",
"status": "BLOCKED",
"previous_status": "ACTIVE"
}
\```

\`business.*` events use `vendor_business_id` instead of `vendor_user_id`.
\`user.data.updated` / `business.data.updated` payloads keep `status` and add `changed_fields` (array) and `changes` (`{field: {previous, current}}`). Use these to apply minimal diffs to your DB.

\## Verify the signature

Verify X-Signature-V2 (recommended): HMAC-SHA256 of the canonical JSON body with the destination `secret_shared_key`, then a constant-time compare, and reject an X-Timestamp older than 300 seconds. See /integration/webhooks for the signature headers and code samples. Respond `2xx` within **5 seconds**. On a 5xx, 404, timeout or connection failure Didit retries up to 2 times (about 1 minute, then about 4 minutes later); see /integration/webhooks#retry-policy.

\## Idempotency

Every delivery carries a unique `event_id`. De-dupe on it. Fallback compound key: `(application_id, webhook_type, vendor_data, timestamp)`.

\## Failure modes

\- Wrong `webhook_version` (e.g. v2) → singular fields and older event names; v3 is required for entity events plural-array contract.
\- Slow handler → retried; budget < 5s; do heavy work async.
\- Unknown event type → log and 200; new event types may be added.

\## Apply-decision pseudocode

\```ts
switch (event.webhook_type) {
case "user.status.updated":
await db.users.update({ vendor_data: event.vendor_data }, { status: event.status });
break;
case "user.data.updated":
for (const field of event.changed_fields) {
  await db.users.update({ vendor_data: event.vendor_data }, { [field]: event.changes[field].current });
}
break;
case "business.status.updated":
case "business.data.updated": /* same shape, businesses table, keyed by vendor_business_id */ break;
}
\```

\## Sources of truth

\- /integration/webhooks — destinations, signatures, retries, full event catalog
\- /management-api/webhook/create-destination — endpoint schema
\- /entities/users/operations — operations that emit user events
\- /entities/businesses/operations — operations that emit business events
\- /integration/integration-prompt — canonical end-to-end prompt````

\</pre>



      
      

붙여넣을 곳

사용자 또는 기업 엔티티의 상태나 프로필 데이터가 바뀔 때마다 webhook이 전송되어 시스템이 실시간으로 대응할 수 있습니다.
엔티티 webhook은 프로필 데이터를 동기화하거나, 차단 조치를 다른 시스템에 전파하거나, 후속 컴플라이언스 흐름을 시작하는 데 사용합니다.## 이벤트 카탈로그| 이벤트 | 트리거 |
| - | - |
| `user.status.updated` | 사용자 엔티티의 상태가 변경될 때 (`ACTIVE` ↔ `FLAGGED` ↔ `BLOCKED`) |
| `user.data.updated` | 사용자 엔티티의 프로필 필드가 변경될 때 (이름, 생년월일, 프로필 이미지, 누적 카운터, 메타데이터) |
| `business.status.updated` | 기업 엔티티의 상태가 변경될 때 |
| `business.data.updated` | 기업 엔티티의 프로필 필드가 변경될 때 (법적 명칭, 등록번호, 국가, 카운터) |> [!NOTE]
>
> `activity.created`는 `subscribed_events`에서 허용되고 **Try Webhook** 테스터에서도 다루지만, Didit은 현재 실시간 트래픽에 대해 이 이벤트를 전송하지 않습니다.
> 이 이벤트를 기반으로 타임라인 미러링을 구현하지 마십시오.Didit은 엔티티 필드를 참조하는 세션, 거래, 기업 세션 이벤트도 전송합니다. 자세한 내용은 다음을 참고하십시오.- [KYB webhook](https://docs.didit.me/ko/business-verification/webhooks.md): 기업 세션 이벤트
- [거래 모니터링 webhook](https://docs.didit.me/ko/transaction-monitoring/webhooks.md): 거래 이벤트
- [Webhook 참조](https://docs.didit.me/ko/integration/webhooks.md): 서명 검증, 재시도, 대상## 페이로드 형식엔티티 webhook은 평면 구조입니다. `data` 래퍼와 `event` 키가 없습니다.
이벤트를 라우팅하려면 `webhook_type`을 읽으십시오.```json theme={null}
{
  "event_id": "7f3c2c1e-6a1d-4c36-9d8e-0d3b5f4e2a10",
  "webhook_type": "user.status.updated",
  "timestamp": 1776333600,
  "created_at": 1776333594,
  "application_id": "0c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
  "environment": "live",
  "vendor_user_id": "9c7d2a30-2f98-4d4f-9d2d-1a7c4b1e5b6a",
  "vendor_data": "user-42",
  "status": "BLOCKED",
  "previous_status": "ACTIVE"
}
```| 필드 | 설명 |
| - | - |
| `vendor_user_id` / `vendor_business_id` | 엔티티에 대한 Didit 식별자입니다. `business.*` 이벤트는 `vendor_business_id`를 사용합니다. |
| `vendor_data` | 엔티티에 대한 고객사 측 식별자입니다. |
| `status` | `ACTIVE`, `FLAGGED` 또는 `BLOCKED`입니다. |
| `previous_status` | `*.status.updated` 이벤트에만 포함됩니다. |
| `changed_fields` 및 `changes` | `*.data.updated` 이벤트에만 포함됩니다. |
| `created_at` | 엔티티가 마지막으로 업데이트된 시점의 Unix 초입니다. |
| `timestamp` | Didit이 webhook을 전송한 시점의 Unix 초입니다. |### `user.status.updated` / `business.status.updated`상태가 바뀔 때마다 전송됩니다.
페이로드에는 `status`와 `previous_status`가 포함됩니다.
상태가 바뀐 이유는 알려주지 않습니다. 원인이 필요하면 콘솔에서 엔티티를 여십시오.### `user.data.updated` / `business.data.updated`프로필 필드가 바뀔 때 전송됩니다.
`changed_fields`에는 바뀐 필드가 나열되고, `changes`에는 각 필드의 `previous` 값과 `current` 값이 들어 있습니다.```json theme={null}
{
  "event_id": "5d1e8f9a-0c32-4b6a-a7b6-2b9d6f0a3c41",
  "webhook_type": "user.data.updated",
  "timestamp": 1776333700,
  "created_at": 1776333694,
  "application_id": "0c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
  "environment": "live",
  "vendor_user_id": "9c7d2a30-2f98-4d4f-9d2d-1a7c4b1e5b6a",
  "vendor_data": "user-42",
  "status": "ACTIVE",
  "changed_fields": ["full_name", "session_count"],
  "changes": {
    "full_name": { "previous": null, "current": "John Doe" },
    "session_count": { "previous": 2, "current": 3 }
  }
}
````changed_fields`에 나타날 수 있는 필드는 다음과 같습니다.- 사용자: `vendor_data`, `display_name`, `full_name`, `date_of_birth`, `metadata`, `portrait_image`, `issuing_states`, `approved_emails`, `approved_phones`, `features`, `session_count`, `approved_count`, `declined_count`, `in_review_count`, `first_session_at`, `last_session_at`.
- 기업: `vendor_data`, `display_name`, `metadata`, `legal_name`, `registration_number`, `country_code`, `session_count`, `approved_count`, `declined_count`, `in_review_count`, `features`, `first_session_at`, `last_session_at`.`changed_fields`와 `changes`를 사용하면 바뀐 필드만 동기화할 수 있습니다.## 전송, 재시도 및 서명모든 엔티티 webhook은 표준 전송 규칙을 따릅니다.- `X-Signature-V2` 헤더에 대상의 `secret_shared_key`로 HMAC-SHA256 **서명됩니다**(권장). `X-Signature`와 지원 중단된 `X-Signature-Simple`도 `X-Timestamp`와 함께 전송됩니다.
- 엔드포인트가 5xx 또는 404를 응답하거나, 시간 초과되거나, 연결에 실패하면 약 1분 후와 약 4분 후에 최대 2회 **재시도됩니다**. 전체 정책은 [Webhook 참조](https://docs.didit.me/ko/integration/webhooks.md#재시도-정책)에 있습니다.
- **멱등성을 가집니다**. 모든 webhook의 페이로드에는 고유한 `event_id`가 있으므로 수신 측에서 중복을 제거하십시오.대상 설정과 서명 검증 코드 샘플은 [Webhook 참조](https://docs.didit.me/ko/integration/webhooks.md)를 참고하십시오.## 구독Management API 또는 Business Console에서 webhook 대상에 엔티티 이벤트를 구독하십시오.```bash theme={null}
curl -X POST https://verification.didit.me/v3/webhook/destinations/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "Entity sync",
    "url": "https://yourapp.com/webhooks/didit",
    "subscribed_events": [
      "user.status.updated",
      "user.data.updated",
      "business.status.updated",
      "business.data.updated"
    ]
  }'
```## 다음 단계> [card] [Webhook 참조](https://docs.didit.me/ko/integration/webhooks.md)
>
> 대상, 서명, 재시도 및 검증.> [card] [대상 생성](https://docs.didit.me/ko/management-api/webhook/create-destination.md)
>
> 새 webhook 엔드포인트를 등록합니다.> [card] [사용자 작업](https://docs.didit.me/ko/entities/users/operations.md)
>
> 사용자 webhook을 트리거하는 변경 사항.


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