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

# KYB State Updated

> Webhook event fired when the KYB verification level changes

<Info>
  **Event Name:** `kyb_state_updated`
</Info>

<Note>
  This event is emitted when the overall KYB verification level changes for a business user, typically after a verification process is completed, downgraded, or expires.
</Note>

## Event Payload

The webhook payload contains the following structure:

```json Example Payload theme={null}
{
  "eventId": "a3f1b2c4-5d6e-7f8a-9b0c-1d2e3f4a5b6c",
  "eventType": "kyb_state_updated",
  "timestamp": "2026-03-21T23:55:00.000Z",
  "data": {
    "kybId": 42,
    "userId": "c8e2f1a0-4b3d-4e5f-8a9b-0c1d2e3f4a5b",
    "state": "REGULAR"
  }
}
```

## Field Description

<ParamField path="eventId" type="string" required>
  Unique event identifier (UUID)
</ParamField>

<ParamField path="eventType" type="string" required>
  Event type - always `kyb_state_updated` for this webhook
</ParamField>

<ParamField path="timestamp" type="string" required>
  Event timestamp in ISO 8601 format
</ParamField>

<ParamField path="data" type="object" required>
  Contains the event data
</ParamField>

<ParamField path="data.kybId" type="integer" required>
  Unique KYB record ID
</ParamField>

<ParamField path="data.userId" type="string" required>
  Unique business user ID (UUID)
</ParamField>

<ParamField path="data.state" type="string" required>
  Current KYB level. Common values include `REGULAR` and `LIGHT`
</ParamField>

## When This Event Is Sent

This webhook is sent when the KYB record changes its overall verification level for a business user.

Typical scenarios include:

* A verification flow upgrades the business user to `REGULAR`
* A review or business rule downgrades the business user to `LIGHT`

## Expected Responses

<CardGroup cols={3}>
  <Card title="Success Response" icon="circle-check" color="#16a34a">
    **HTTP 200 OK**

    The webhook was processed successfully.
  </Card>

  <Card title="Client Error" icon="triangle-exclamation" color="#ea580c">
    **HTTP 4xx Status**

    Client-side error. Will not be retried.
  </Card>

  <Card title="Server Error" icon="circle-xmark" color="#dc2626">
    **HTTP 5xx Status**

    Server-side error. Will be retried with exponential backoff.
  </Card>
</CardGroup>

## Implementation Example

<CodeGroup>
  ```javascript Node.js theme={null}
  app.post('/webhooks/ralio', async (req, res) => {
    const { eventType, data } = req.body;

    if (eventType === 'kyb_state_updated') {
      const { kybId, userId, state } = data;

      console.log(
        `KYB ${kybId} for business user ${userId} changed to ${state}`
      );

      await updateBusinessUserKybLevel(userId, state);

      res.status(200).json({ received: true });
    }
  });
  ```

  ```python Python theme={null}
  @app.route('/webhooks/ralio', methods=['POST'])
  def handle_webhook():
      payload = request.get_json()

      if payload['eventType'] == 'kyb_state_updated':
          data = payload['data']
          kyb_id = data['kybId']
          user_id = data['userId']
          state = data['state']

          print(f"KYB {kyb_id} for business user {user_id} changed to {state}")

          update_business_user_kyb_level(user_id, state)

          return jsonify({'received': True}), 200
  ```

  ```go Go theme={null}
  func handleWebhook(w http.ResponseWriter, r *http.Request) {
      var payload struct {
          EventType string `json:"eventType"`
          Data      struct {
              KybID  int    `json:"kybId"`
              UserID string `json:"userId"`
              State  string `json:"state"`
          } `json:"data"`
      }

      if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
          http.Error(w, "Invalid JSON", http.StatusBadRequest)
          return
      }

      if payload.EventType == "kyb_state_updated" {
          log.Printf(
              "KYB %d for business user %s changed to %s",
              payload.Data.KybID,
              payload.Data.UserID,
              payload.Data.State,
          )

          if err := updateBusinessUserKybLevel(payload.Data.UserID, payload.Data.State); err != nil {
              http.Error(w, "Internal error", http.StatusInternalServerError)
              return
          }

          w.Header().Set("Content-Type", "application/json")
          w.WriteHeader(http.StatusOK)
          json.NewEncoder(w).Encode(map[string]bool{"received": true})
      }
  }
  ```
</CodeGroup>
