Webhooks Guide
Overview
Webhooks allow you to receive real-time notifications about events happening in your Kira integration. Instead of polling the API, events are pushed to your server immediately when they occur.
Register Your Webhook URL
Register your webhook endpoint with the Kira API:
Endpoint
POST /webhooks/register
Request
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
| Parameter | Type | Required | Description |
|---|---|---|---|
webhook_url | string | Yes | Your HTTPS endpoint that will receive webhooks (must be HTTPS in production) |
secret | string | Yes | Secret key used to sign webhook payloads for verification |
client_uuid | string | Yes | Your unique client identifier |
Response
{
"message": "Webhook registered successfully"
}Webhook Structure
All webhooks follow the same base structure:
{
"event": "event.name",
"data": {
...
}
}| Field | Type | Description |
|---|---|---|
event | string | The event type (e.g., user.created, virtual_account.deposit_funds_received) |
data | object | Event-specific payload |
Your endpoint must return a 200 status code to acknowledge receipt. Non-2xx responses will be treated as a delivery failure.
Signature Verification
All webhooks include an x-signature-sha256 header containing an HMAC SHA256 signature computed with the secret you provided during registration. Always verify this signature before processing webhooks.
Verification Steps
- Extract the
x-signature-sha256header from the request - Compute the HMAC SHA256 of the JSON-stringified request body using your secret
- Compare the computed signature with the received signature using a timing-safe comparison
Example (Node.js)
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature) {
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)
);
}Important: If you use middleware that parses the JSON body (e.g.,
express.json()), you mustJSON.stringify()the parsed body to verify the signature — do not use the raw buffer.
Best Practices
- Return 200 quickly - Acknowledge receipt immediately, process the event asynchronously
- Verify signatures - Always validate webhook authenticity before processing
- Implement idempotency - Use unique identifiers from the
datapayload (e.g.,event_id) to prevent duplicate processing - Use HTTPS - Webhook URLs must use HTTPS in production
- Store secrets securely - Use environment variables, never commit secrets to code
Testing
Local Development with ngrok
# 1. Start your local server
npm run dev
# 2. In another terminal, start ngrok
ngrok http 3000
# 3. Register the ngrok URL as your webhook endpoint
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://abc123.ngrok.io/webhooks/kira",
"secret": "dev_secret_123",
"client_uuid": "YOUR_CLIENT_UUID"
}'Sandbox
In sandbox mode, user verification is automatically approved and webhooks are sent immediately for user creation and verification events.
Support
- Email: [email protected]
Updated about 2 months ago
