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

# Notification examples

One payload per event, grouped by resource. Every delivery has the same envelope — `event` names what happened, `data` carries it — so the objects below are what arrives in `data`.

Every payload carries an `event_id`. Use it to make your handler idempotent: record what you have already processed and ignore a repeat.

## Sub-client

<AccordionGroup>
  <Accordion title="user.created">
    ```json theme={null}
    {
      "event_id": "3f1a9c20-4b5d-4e6f-8a90-1c2d3e4f5a6b",
      "user_id": "e687484f-74ef-43a8-a68a-5bf78aa2e721",
      "type": "business",
      "email": "ops@example.com",
      "phone": "+14155559999",
      "status": "CREATED",
      "verification_status": "unverified",
      "verification_mode": "automatic"
    }
    ```
  </Accordion>

  <Accordion title="user.status_changed">
    ```json theme={null}
    {
      "event_id": "8c2b1d40-5e6f-4a7b-9c8d-2e3f4a5b6c7d",
      "user_id": "e687484f-74ef-43a8-a68a-5bf78aa2e721",
      "previous_status": "VERIFYING",
      "new_status": "REJECTED"
    }
    ```

    Fires on every transition. It is the one to subscribe to.
  </Accordion>

  <Accordion title="user.verification.accepted">
    ```json theme={null}
    {
      "event_id": "1d4e5f60-7a8b-4c9d-8e0f-3a4b5c6d7e8f",
      "user_id": "e687484f-74ef-43a8-a68a-5bf78aa2e721",
      "verification_status": "verified",
      "reasons": []
    }
    ```
  </Accordion>

  <Accordion title="user.verification.failed">
    ```json theme={null}
    {
      "event_id": "9a8b7c60-1d2e-4f30-8a4b-5c6d7e8f9a0b",
      "user_id": "e687484f-74ef-43a8-a68a-5bf78aa2e721",
      "verification_status": "rejected",
      "reasons": ["Verification session expired"]
    }
    ```

    `reasons` exists only here. No read of the sub-client returns it.
  </Accordion>

  <Accordion title="user.liveness_completed">
    ```json theme={null}
    {
      "event_id": "5b6c7d80-9e0f-4a1b-8c2d-3e4f5a6b7c8d",
      "user_id": "e687484f-74ef-43a8-a68a-5bf78aa2e721",
      "person_reference_id": "0123456789abcdef0123456789abcdef",
      "result": "approved"
    }
    ```

    `person_reference_id` is `null` when the check was for the sub-client rather than one of its people.
  </Accordion>
</AccordionGroup>

## Virtual account and deposits

<AccordionGroup>
  <Accordion title="virtual_account.activated">
    ```json theme={null}
    {
      "event_id": "2e3f4a50-6b7c-4d8e-9f0a-1b2c3d4e5f6a",
      "virtual_account_id": "11111111-2222-3333-4444-555555555555",
      "status": "active"
    }
    ```

    The funds-ready signal. Nothing before it can receive money.
  </Accordion>

  <Accordion title="virtual_account.deposit_funds_received">
    ```json theme={null}
    {
      "event_id": "7c8d9e00-1f2a-4b3c-8d4e-5f6a7b8c9d0e",
      "user_id": "e687484f-74ef-43a8-a68a-5bf78aa2e721",
      "virtual_account_id": "11111111-2222-3333-4444-555555555555",
      "deposit_id": "4a5b6c70-8d9e-4f0a-8b1c-2d3e4f5a6b7c",
      "amount": "100.00",
      "currency": "USD",
      "created_at": "2026-09-01T12:00:00.000Z",
      "source": {
        "payment_rail": "wire",
        "description": "Invoice 4471",
        "sender_name": "Northwind Trading LLC",
        "trace_number": "20260901MMQFMP3K000123",
        "sender_bank_routing_number": "000000001"
      }
    }
    ```

    The rail-independent signal that money arrived.
  </Accordion>

  <Accordion title="virtual_account.deposit_funds_refunded">
    ```json theme={null}
    {
      "event_id": "6d7e8f90-0a1b-4c2d-8e3f-4a5b6c7d8e9f",
      "virtual_account_id": "11111111-2222-3333-4444-555555555555",
      "deposit_id": "4a5b6c70-8d9e-4f0a-8b1c-2d3e4f5a6b7c",
      "amount": "100.00",
      "currency": "USD",
      "created_at": "2026-09-01T12:00:00.000Z",
      "return_details": {
        "code": "R01",
        "reason": "Insufficient funds at the sending bank",
        "refunded_at": "2026-09-02T09:00:00.000Z"
      }
    }
    ```
  </Accordion>
</AccordionGroup>

## Payouts

<AccordionGroup>
  <Accordion title="payout.status_changed">
    ```json theme={null}
    {
      "event_id": "0f1a2b30-4c5d-4e6f-8a7b-8c9d0e1f2a3b",
      "payout_id": "99999999-aaaa-bbbb-cccc-dddddddddddd",
      "virtual_account_id": "11111111-2222-3333-4444-555555555555",
      "amount": "1000.00",
      "currency": "USD",
      "recipient_amount": "986.50",
      "recipient_currency": "USD",
      "previous_status": "PROCESSING",
      "status": "IN_REVIEW",
      "updated_at": "2026-09-01T12:00:10.000Z"
    }
    ```

    **Subscribe to this one.** `IN_REVIEW` and `KYT_PENDING` arrive here and nowhere else.
  </Accordion>

  <Accordion title="payout.completed">
    ```json theme={null}
    {
      "event_id": "3b4c5d60-7e8f-4a9b-8c0d-1e2f3a4b5c6d",
      "payout_id": "99999999-aaaa-bbbb-cccc-dddddddddddd",
      "virtual_account_id": "11111111-2222-3333-4444-555555555555",
      "amount": "1000.00",
      "currency": "USD",
      "recipient_amount": "986.50",
      "recipient_currency": "USD",
      "status": "COMPLETED",
      "updated_at": "2026-09-01T12:04:00.000Z"
    }
    ```

    Amounts are strings. `amount` and `recipient_amount` differ by the fees and any conversion.
  </Accordion>
</AccordionGroup>

## Requests for information

These reach a URL with no event filter, or one whose filter names them.

<AccordionGroup>
  <Accordion title="rfi.raised">
    ```json theme={null}
    {
      "event_id": "8e9f0a10-2b3c-4d5e-8f6a-7b8c9d0e1f2a",
      "rfi_id": "7f1c9a20-3b4d-4e5f-8a91-2c3d4e5f6a7b",
      "user_id": "e687484f-74ef-43a8-a68a-5bf78aa2e721",
      "to_status": "pending"
    }
    ```
  </Accordion>

  <Accordion title="rfi.item_returned">
    ```json theme={null}
    {
      "event_id": "1a2b3c40-5d6e-4f70-8a8b-9c0d1e2f3a4b",
      "rfi_id": "7f1c9a20-3b4d-4e5f-8a91-2c3d4e5f6a7b",
      "user_id": "e687484f-74ef-43a8-a68a-5bf78aa2e721",
      "item_id": "1a2b3c4d-5e6f-4708-9a1b-2c3d4e5f6a7b",
      "to_status": "pending",
      "review_note": "The document was issued more than 90 days ago."
    }
    ```

    `to_status` here is the **item's**, not the request's.
  </Accordion>

  <Accordion title="rfi.not_resolved">
    ```json theme={null}
    {
      "event_id": "4c5d6e70-8f9a-4b0c-8d1e-2f3a4b5c6d7e",
      "rfi_id": "7f1c9a20-3b4d-4e5f-8a91-2c3d4e5f6a7b",
      "user_id": "e687484f-74ef-43a8-a68a-5bf78aa2e721",
      "to_status": "not_resolved",
      "resolution_reason": "expired"
    }
    ```

    `resolution_reason` rides along only on this one — it is the difference between a deadline that ran out and an answer that was refused.
  </Accordion>
</AccordionGroup>

<Note>
  Every payload carries `to_status` read off the row that moved, rather than inferred from the event name. A handler that stores the event can reconstruct state without knowing which events existed on the day it was written.
</Note>
