Webhooks

Overview

Webhooks allow you to receive real-time notifications about events in your Kira integration. Instead of polling the API, events are pushed to your server immediately when they occur.

Why Use Webhooks?

Real-time updates: Get notified instantly when events happen

Reduced API calls: No need to poll endpoints repeatedly

Better user experience: Update your UI immediately

Reliable delivery: Automatic retries if your server is down

Scalable: Handle high volumes efficiently

Available Events

User Events

  • user.created - User account created
  • user.verification.accepted - User verification completed successfully
  • user.verification.failed - User verification failed or rejected

Virtual Account Deposit Events

  • virtual_account.deposit_funds_received - Funds received at virtual account
  • virtual_account.deposit_funds_in_transit - Funds sent to blockchain
  • virtual_account.deposit_funds_in_destination - Funds arrived at destination wallet
  • virtual_account.deposit_scheduled - Deposit scheduled for processing
  • virtual_account.deposit_in_review - Deposit under review
  • virtual_account.deposit_funds_refunded - Funds have been refunded

Quick Setup

1. Create Webhook Endpoint

app.post('/webhooks/kira', async (req, res) => {
  // Verify signature (if configured)
  const signature = req.headers['x-kira-signature'];
  if (signature && !verifySignature(req.body, signature)) {
    return res.status(401).send('Invalid signature');
  }

  // Parse webhook payload
  const webhook = req.body; // { event: "user.created", data: {...} }

  // Process event
  await handleEvent(webhook.event, webhook.data);

  // Acknowledge receipt immediately
  res.status(200).send('OK');
});

2. Register Your Webhook URL

Register your webhook endpoint with Kira:

curl -X POST https://api.balampay.com/webhooks/register \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "webhook_url": "https://your-domain.com/webhooks/kira",
    "secret": "your_webhook_secret",
    "client_uuid": "your-client-uuid"
  }'

Parameters:

  • webhook_url - Your HTTPS endpoint that will receive webhooks (must be HTTPS in production)
  • secret - Secret key for verifying webhook signatures
  • client_uuid - Your unique client identifier

Response:

{
  "message": "Webhook registered successfully"
}

3. Verify Webhook Signatures

Use the secret you provided during registration to verify webhook authenticity:

function verifySignature(payload, signature) {
  // Use the same secret you registered with
  const secret = process.env.KIRA_WEBHOOK_SECRET;

  const computedSignature = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(computedSignature)
  );
}

Note: Store your webhook secret securely (e.g., environment variables) and never commit it to version control.

Event Examples

User Created

{
  "event": "user.created",
  "data": {
    "user_id": "550e8400-e29b-41d4-a716-446655440000",
    "type": "person",
    "email": "[email protected]",
    "first_name": "John",
    "last_name": "Doe",
    "created_at": "2024-01-15T10:30:00Z"
  }
}

Verification Accepted

{
  "event": "user.verification.accepted",
  "data": {
    "event_id": "evt_abc123",
    "user_id": "550e8400-e29b-41d4-a716-446655440000",
    "id": "verif_123",
    "verification_status": "verified",
    "kyc_type": "full"
  }
}

Verification Failed

{
  "event": "user.verification.failed",
  "data": {
    "event_id": "evt_def456",
    "user_id": "550e8400-e29b-41d4-a716-446655440000",
    "id": "verif_123",
    "verification_status": "rejected",
    "reasons": [
      "Invalid document",
      "Photo quality too low"
    ]
  }
}

Deposit Funds Received

{
  "event": "virtual_account.deposit_funds_received",
  "data": {
    "user_id": "550e8400-e29b-41d4-a716-446655440000",
    "virtual_account_id": "va_789012345",
    "amount": "1000.00",
    "currency": "usdc",
    "created_at": "2024-01-15T14:30:00Z",
    "deposit_id": "dep_abc123",
    "source": {
      "payment_rail": "ach_push",
      "sender_name": "Acme Corporation",
      "sender_bank_routing_number": "021000021",
      "trace_number": "123456789",
      "description": "Payment from sender"
    }
  }
}

Deposit Funds in Transit

{
  "event": "virtual_account.deposit_funds_in_transit",
  "data": {
    "user_id": "550e8400-e29b-41d4-a716-446655440000",
    "virtual_account_id": "va_789012345",
    "amount": "1000.00",
    "currency": "usdc",
    "created_at": "2024-01-15T14:32:00Z",
    "source": {
      "payment_rail": "ach_push",
      "sender_name": "Acme Corporation",
      "sender_bank_routing_number": "021000021",
      "trace_number": "123456789",
      "description": "Payment from sender"
    }
  }
}

Deposit Funds in Destination

{
  "event": "virtual_account.deposit_funds_in_destination",
  "data": {
    "user_id": "550e8400-e29b-41d4-a716-446655440000",
    "virtual_account_id": "va_789012345",
    "amount": "1000.00",
    "currency": "usdc",
    "created_at": "2024-01-15T14:35:00Z",
    "destination_tx_hash": "5KYmFMZ3qvXpTrZ...",
    "source": {
      "payment_rail": "ach_push",
      "sender_name": "Acme Corporation",
      "sender_bank_routing_number": "021000021",
      "trace_number": "123456789",
      "description": "Payment from sender"
    }
  }
}

Deposit Funds Refunded

{
  "event": "virtual_account.deposit_funds_refunded",
  "data": {
    "user_id": "550e8400-e29b-41d4-a716-446655440000",
    "virtual_account_id": "va_789012345",
    "amount": "1000.00",
    "currency": "usdc",
    "created_at": "2024-01-15T16:00:00Z",
    "source": {
      "payment_rail": "ach_push",
      "sender_name": "Acme Corporation",
      "sender_bank_routing_number": "021000021",
      "trace_number": "123456789",
      "description": "Payment from sender"
    },
    "refund": {
      "code": "300",
      "reason": "Transaction Review",
      "refunded_at": "2024-01-15T16:00:00Z"
    }
  }
}

Best Practices

  1. Return 200 quickly - Acknowledge receipt immediately, process async
  2. Verify signatures - Always validate webhook authenticity (if configured)
  3. Implement idempotency - Use unique identifiers from the data payload (e.g., user_id, virtual_account_id, deposit_id) to prevent duplicate processing
  4. Use message queues - Handle high volumes efficiently
  5. Log everything - Keep audit trail of all events
  6. Monitor failures - Alert on webhook processing errors

Sandbox Testing

In sandbox mode:

  • User verification is automatically approved
  • Webhooks for user creation and verification are sent immediately
  • Webhooks for deposits are sent when real deposit events occur
  • Use the webhook registration endpoint to point to your test server

Detailed Documentation

For complete webhook implementation details, see:

📖 Webhooks Guide

Topics covered:

  • Complete event reference
  • Signature verification
  • Retry logic
  • Error handling
  • Scaling webhooks
  • Security considerations

Related Documentation

Support