Webhooks

Tsara sends webhook events whenever customer verification actions occur — such as when a customer’s BVN, NIN, or CAC verification succeeds or fails.
These webhooks allow your system to stay in sync with real-time identity status updates and automate next steps in onboarding or compliance.


🚀 Overview

Event TypeDescription
customer.createdA new customer record was created successfully.
customer.verifiedCustomer verification (BVN/NIN/CAC) succeeded.
customer.verification_failedCustomer verification failed.

💡 Webhooks are signed with X-Tsara-Signature for security and can be retried multiple times if your server doesn’t acknowledge them.


🧾 Example Payloads

1️⃣ customer.created

{
  "id": "evt_001",
  "type": "customer.created",
  "created_at": "2025-10-17T12:00:00Z",
  "data": {
    "customer_id": "cus_123",
    "type": "individual",
    "first_name": "John",
    "last_name": "Doe",
    "email": "[email protected]",
    "status": "pending_verification"
  }
}

2️⃣ customer.verified

{
  "id": "evt_002",
  "type": "customer.verified",
  "created_at": "2025-10-17T12:05:00Z",
  "data": {
    "customer_id": "cus_123",
    "verification_type": "bvn",
    "status": "verified",
    "verified_at": "2025-10-17T12:05:00Z"
  }
}

3️⃣ customer.verification_failed

{
  "id": "evt_003",
  "type": "customer.verification_failed",
  "created_at": "2025-10-17T12:10:00Z",
  "data": {
    "customer_id": "cus_456",
    "verification_type": "nin",
    "status": "failed",
    "error_message": "Invalid NIN or mismatch in details."
  }
}

🛡️ Signature Verification

Every webhook from Tsara includes a secure signature header:

X-Tsara-Signature: <HMAC-SHA512 hash>

Use this signature to confirm the webhook was sent by Tsara.

Example — PHP

<?php
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_TSARA_SIGNATURE'] ?? '';
$expected = hash_hmac('sha512', $payload, TSARA_WEBHOOK_SECRET);

if (!hash_equals($expected, $signature)) {
    http_response_code(400);
    exit('Invalid signature');
}

$event = json_decode($payload, true);
if ($event['type'] === 'customer.verified') {
    // Handle successful verification
}

http_response_code(200);
?>

🔁 Retry Policy

  • Webhooks that fail to receive a 2xx response are retried automatically.
  • Retries use exponential backoff (1s → 5s → 30s).
  • Webhook events are idempotent — handle duplicate payloads safely using event.id or customer_id.

🧠 Best Practices

  1. Always validate webhook signatures before trusting data.
  2. Use customer.verified to activate accounts or enable transactions.
  3. Store verification timestamps (verified_at) for audit trails.
  4. Log all webhook payloads for debugging or compliance checks.
  5. Return a 200 OK response after successful processing.

🔗 Related Pages