> ## Documentation Index
> Fetch the complete documentation index at: https://docs.baanx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# KYC Status Events

> Complete reference for KYC status change webhooks, payload fields, and failure codes

The `kyc.status.changed` event is sent whenever a user's KYC verification status changes.

## Event Type

```
kyc.status.changed
```

## Successful KYC Payload

When KYC verification completes successfully, `failure_code` and `failure_reason` are `null`.

**Headers:**

```theme={null} theme={null}
Content-Type: application/json
X-Timestamp: 1767711032
X-Signature: 9af85e3e50d7a5c0ee1dcc519a063f272efc8a0d4c75a55eb0c1296e45e13564
```

**Body:**

```json theme={null} theme={null}
{
  "api_version": "v1",
  "event_id": "c386021a-d7a5-4aff-8924-4374f1d1d84f",
  "event_category": "kyc",
  "event_type": "kyc.status.changed",
  "user_id": "ecf74983-b52f-40ff-8a4c-aa052748459b",
  "event_object_id": "ecf74983-b52f-40ff-8a4c-aa052748459b",
  "event_object_status": "completed",
  "event_object_changes": {
    "status": ["pending", "completed"]
  },
  "event_object": {
    "status": "completed",
    "failure_code": null,
    "failure_reason": null
  },
  "occurred_at": "2026-01-06T14:50:31.481Z"
}
```

## Failed KYC Payload

When KYC is denied, `event_object` includes the `failure_code` and `failure_reason` from Veriff (our KYC provider):

```json theme={null} theme={null}
{
  "api_version": "v1",
  "event_id": "d486021a-e8b6-5bff-9035-5485f2e2e95g",
  "event_category": "kyc",
  "event_type": "kyc.status.changed",
  "user_id": "ecf74983-b52f-40ff-8a4c-aa052748459b",
  "event_object_id": "ecf74983-b52f-40ff-8a4c-aa052748459b",
  "event_object_status": "failed",
  "event_object_changes": {
    "status": ["pending", "failed"]
  },
  "event_object": {
    "status": "failed",
    "failure_code": "103",
    "failure_reason": "Person showing the document does not appear to match document photo"
  },
  "occurred_at": "2026-01-06T15:02:47.000Z"
}
```

## KYC Status Values

The `event_object.status` field reflects the current verification state:

| Status          | Description                               |
| --------------- | ----------------------------------------- |
| `pending`       | KYC verification is in progress           |
| `completed`     | KYC verification was successful           |
| `failed`        | KYC verification was denied               |
| `kyc_checked`   | KYC verified, awaiting manual review      |
| `edd_required`  | Enhanced Due Diligence is required        |
| `edd_submitted` | Enhanced Due Diligence has been submitted |

## Failure Codes Reference

When `status` is `failed`, the `failure_code` and `failure_reason` fields provide details from Veriff. Use these to understand why verification was denied and to provide appropriate guidance to the user.

<AccordionGroup>
  <Accordion title="Fraud & Identity (100s)">
    | Code  | Reason                                                              |
    | ----- | ------------------------------------------------------------------- |
    | `101` | Physical document not used                                          |
    | `102` | Suspected document tampering                                        |
    | `103` | Person showing the document does not appear to match document photo |
    | `104` | Name entered does not match name on document                        |
    | `105` | Suspicious behaviour                                                |
    | `106` | Known fraud                                                         |
    | `108` | Velocity/abuse — duplicated end-user                                |
    | `109` | Velocity/abuse — duplicated device                                  |
    | `110` | Velocity/abuse — duplicated ID                                      |
    | `111` | Session fraudulently accessed                                       |
    | `112` | Restricted IP location                                              |
    | `113` | Suspicious behaviour — Identity Farming                             |
    | `120` | Person on the portrait does not appear to match reference photo     |
    | `121` | User ID missing                                                     |
    | `122` | No reference found                                                  |
    | `123` | Unable to pass registry checks                                      |
    | `124` | Face already exists in the face collection                          |
    | `127` | Face match with blocklist                                           |
    | `128` | End User ID mismatch                                                |
    | `129` | Invalid workflow                                                    |
  </Accordion>

  <Accordion title="Document & Media Quality (200s)">
    | Code  | Reason                                                                  |
    | ----- | ----------------------------------------------------------------------- |
    | `201` | Video and/or photos missing                                             |
    | `202` | Face not clearly visible                                                |
    | `203` | Full document not visible                                               |
    | `204` | Poor image quality                                                      |
    | `205` | Document damaged                                                        |
    | `206` | Document type not supported                                             |
    | `207` | Document expired                                                        |
    | `208` | Selfie missing                                                          |
    | `209` | Document photo missing                                                  |
    | `210` | Document front photo submitted twice                                    |
    | `211` | Document not visible in ID document image                               |
    | `212` | Document framing — part of the document is out of the image             |
    | `213` | Document obscured — ID document is partially obscured (e.g. by fingers) |
    | `214` | Selfie poor quality — too dark or too blurry                            |
    | `215` | Document poor quality — document is not readable (too blurry, too dark) |
    | `216` | Document poor quality — glare                                           |
    | `217` | Custom resubmission                                                     |
  </Accordion>
</AccordionGroup>

## Handling KYC Events

A typical implementation pattern:

```typescript theme={null} theme={null}
async function handleKycEvent(event: WebhookEvent): Promise<void> {
  const { user_id, user_external_id, event_object } = event;
  const { status, failure_code, failure_reason } = event_object;

  switch (status) {
    case 'completed':
      // Grant access, activate card, etc.
      await activateUser(user_id);
      break;

    case 'failed':
      // Notify the user and log the failure reason
      await notifyUserKycFailed(user_external_id, failure_code, failure_reason);
      break;

    case 'edd_required':
      // Prompt the user to complete Enhanced Due Diligence
      await requestEdd(user_external_id);
      break;

    case 'pending':
    case 'kyc_checked':
    case 'edd_submitted':
      // Informational — no action required
      break;
  }
}
```

## Related

<CardGroup cols={2}>
  <Card title="Event Payload Structure" icon="list" href="/guides/webhooks/events">
    Full reference for the standard webhook payload fields
  </Card>

  <Card title="Security & Verification" icon="lock" href="/guides/webhooks/security">
    How to verify the X-Signature header before processing events
  </Card>
</CardGroup>
