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

# Webhook Events

> Complete list of webhook event types

Zentra sends webhook notifications for various events in your account. This page shows common event families and representative payload shapes, not a reviewed schema bundle for every tenant and rail combination.

<Note>
  Treat event names and fields here as implementation guidance. Exact event availability and payload shape can vary by tenant capability, provider path, and rollout phase.
</Note>

## Event Structure

All webhook payloads follow this structure:

```json theme={null}
{
  "event": "event.type",
  "data": {
    // Event-specific data
  },
  "created_at": "2024-01-15T10:30:00Z",
  "webhook_id": "wh_abc123"
}
```

## Virtual Account Events

### `virtual_account.created`

Triggered when a virtual account is successfully created.

```json theme={null}
{
  "event": "virtual_account.created",
  "data": {
    "id": "va_123",
    "customer_id": "cus_456",
    "account_number": "0123456789",
    "bank_name": "GTBank",
    "status": "active"
  }
}
```

### `virtual_account.credited`

Triggered when a payment is received in a virtual account.

```json theme={null}
{
  "event": "virtual_account.credited",
  "data": {
    "id": "va_123",
    "account_number": "0123456789",
    "amount_minor": 50000,
    "sender_name": "Jane Smith",
    "sender_account": "9876543210",
    "sender_bank": "Zenith Bank",
    "reference": "TRF12345",
    "narration": "Payment",
    "credited_at": "2024-01-15T10:30:00Z"
  }
}
```

### `virtual_account.closed`

Triggered when a virtual account is closed.

```json theme={null}
{
  "event": "virtual_account.closed",
  "data": {
    "id": "va_123",
    "account_number": "0123456789",
    "reason": "Customer request",
    "closed_at": "2024-01-15T10:30:00Z"
  }
}
```

## Transfer Events

### `transfer.pending`

Transfer initiated and pending processing.

```json theme={null}
{
  "event": "transfer.pending",
  "data": {
    "id": "trn_123",
    "amount_minor": 50000,
    "recipient_account": "0123456789",
    "recipient_bank": "GTBank",
    "reference": "TRF_123",
    "status": "pending"
  }
}
```

### `transfer.processing`

Transfer is being processed by the bank.

```json theme={null}
{
  "event": "transfer.processing",
  "data": {
    "id": "trn_123",
    "status": "processing",
    "session_id": "SES_xyz"
  }
}
```

### `transfer.completed`

Transfer successfully completed.

```json theme={null}
{
  "event": "transfer.completed",
  "data": {
    "id": "trn_123",
    "amount_minor": 50000,
    "recipient_name": "John Doe",
    "reference": "TRF_123",
    "status": "completed",
    "completed_at": "2024-01-15T10:35:00Z"
  }
}
```

### `transfer.failed`

Transfer failed to process.

```json theme={null}
{
  "event": "transfer.failed",
  "data": {
    "id": "trn_123",
    "amount_minor": 50000,
    "reference": "TRF_123",
    "status": "failed",
    "reason": "Insufficient balance",
    "failed_at": "2024-01-15T10:35:00Z"
  }
}
```

## Payment Events

### `payment.pending`

Payment created and awaiting customer action or downstream completion.

```json theme={null}
{
  "event": "payment.pending",
  "data": {
    "id": "pay_123",
    "amount_minor": 100000,
    "customer_email": "customer@example.com",
    "reference": "PAY_123",
    "authorization_url": "https://checkout.zentra.io/pay_123"
  }
}
```

### `payment.successful`

Payment completed successfully.

```json theme={null}
{
  "event": "payment.successful",
  "data": {
    "id": "pay_123",
    "amount_minor": 100000,
    "customer_email": "customer@example.com",
    "reference": "PAY_123",
    "payment_method": "card",
    "status": "successful",
    "paid_at": "2024-01-15T10:40:00Z"
  }
}
```

### `payment.failed`

Payment failed.

```json theme={null}
{
  "event": "payment.failed",
  "data": {
    "id": "pay_123",
    "amount_minor": 100000,
    "reference": "PAY_123",
    "reason": "Declined by bank",
    "status": "failed"
  }
}
```

## Card Events

### `card.created`

Card successfully issued.

```json theme={null}
{
  "event": "card.created",
  "data": {
    "id": "crd_123",
    "customer_id": "cus_456",
    "last4": "4567",
    "brand": "visa",
    "type": "virtual",
    "status": "active"
  }
}
```

### `card.transaction`

Transaction made with the card.

```json theme={null}
{
  "event": "card.transaction",
  "data": {
    "id": "crd_123",
    "transaction_id": "txn_789",
    "amount_minor": 15000,
    "merchant": "Netflix",
    "status": "approved",
    "timestamp": "2024-01-15T10:45:00Z"
  }
}
```

### `card.locked`

Card has been locked.

```json theme={null}
{
  "event": "card.locked",
  "data": {
    "id": "crd_123",
    "reason": "Customer request",
    "locked_at": "2024-01-15T10:50:00Z"
  }
}
```

### `card.unlocked`

Card has been unlocked.

```json theme={null}
{
  "event": "card.unlocked",
  "data": {
    "id": "crd_123",
    "reason": "Risk review cleared",
    "unlocked_at": "2024-01-15T10:55:00Z"
  }
}
```

## KYC Events

### `kyc.completed`

KYC verification completed.

```json theme={null}
{
  "event": "kyc.completed",
  "data": {
    "customer_id": "cus_123",
    "verification_type": "bvn",
    "status": "verified",
    "verified_at": "2024-01-15T11:00:00Z"
  }
}
```

### `kyc.failed`

KYC verification failed.

```json theme={null}
{
  "event": "kyc.failed",
  "data": {
    "customer_id": "cus_123",
    "verification_type": "bvn",
    "status": "failed",
    "reason": "BVN mismatch",
    "failed_at": "2024-01-15T11:00:00Z"
  }
}
```

## Customer Events

### `customer.created`

New customer created.

```json theme={null}
{
  "event": "customer.created",
  "data": {
    "id": "cus_123",
    "email": "customer@example.com",
    "name": "John Doe",
    "created_at": "2024-01-15T11:05:00Z"
  }
}
```

### `customer.updated`

Customer information updated.

```json theme={null}
{
  "event": "customer.updated",
  "data": {
    "id": "cus_123",
    "updated_fields": ["phone", "address"],
    "updated_at": "2024-01-15T11:10:00Z"
  }
}
```

## Wallet Events

### `wallet.credited`

Wallet credited with funds.

```json theme={null}
{
  "event": "wallet.credited",
  "data": {
    "wallet_id": "wal_123",
    "amount_minor": 100000,
    "source": "virtual_account",
    "reference": "DEP_123",
    "balance_minor": 250000,
    "credited_at": "2024-01-15T11:15:00Z"
  }
}
```

### `wallet.debited`

Wallet debited.

```json theme={null}
{
  "event": "wallet.debited",
  "data": {
    "wallet_id": "wal_123",
    "amount_minor": 50000,
    "purpose": "transfer",
    "reference": "TRF_123",
    "balance_minor": 200000,
    "debited_at": "2024-01-15T11:20:00Z"
  }
}
```

## Handling Events

<CodeGroup>
  ```javascript JavaScript theme={null}
  app.post('/webhooks/zentra', (req, res) => {
    const { event, data } = req.body;
    
    switch (event) {
      case 'virtual_account.credited':
        handleAccountCredit(data);
        break;
      case 'transfer.completed':
        handleTransferComplete(data);
        break;
      case 'payment.successful':
        handlePaymentSuccess(data);
        break;
      default:
        console.log(`Unhandled event: ${event}`);
    }
    
    res.status(200).send('OK');
  });
  ```

  ```python Python theme={null}
  @app.route('/webhooks/zentra', methods=['POST'])
  def handle_webhook():
      payload = request.json
      event = payload['event']
      data = payload['data']
      
      if event == 'virtual_account.credited':
          handle_account_credit(data)
      elif event == 'transfer.completed':
          handle_transfer_complete(data)
      elif event == 'payment.successful':
          handle_payment_success(data)
      
      return 'OK', 200
  ```

  ```php PHP theme={null}
  $payload = json_decode(file_get_contents('php://input'), true);
  $event = $payload['event'];
  $data = $payload['data'];

  switch ($event) {
      case 'virtual_account.credited':
          handleAccountCredit($data);
          break;
      case 'transfer.completed':
          handleTransferComplete($data);
          break;
      case 'payment.successful':
          handlePaymentSuccess($data);
          break;
  }

  http_response_code(200);
  ```
</CodeGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Configure Webhooks" icon="gear" href="/api-reference/webhooks/configure">
    Set up webhook endpoints
  </Card>

  <Card title="Verify Signatures" icon="shield" href="/api-reference/webhooks/verify-signature">
    Secure your webhooks
  </Card>

  <Card title="Handling Guide" icon="book" href="/guides/handling-webhooks">
    Best practices
  </Card>

  <Card title="Test Events" icon="flask" href="/resources/sandbox">
    Test in sandbox
  </Card>
</CardGroup>
