LotiFinanceDocs

Webhooks

Webhooks let your server find out about a successful payment the moment it happens, instead of polling. Configure your endpoint URL from the merchant dashboard.

What fires today

There is currently one event: charge.completed, sent when a charge's status becomes completed. It is a single HTTP POST to the URL you configured.

Payout events are not sent yet

The dashboard lets you configure a webhook for payout events, but nothing currently triggers it — no payout notification is sent today. Only build against charge.completed until this changes.

Payload

POST to your endpoint
{
  "event": "charge.completed",
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "status": "completed",
    "reference": "inv_881",
    "amount": 15000,
    "fee_amount": 225,
    "net_amount": 14775,
    "currency": "XAF",
    "completed_at": "2026-10-02T10:18:42Z"
  }
}
data.amount
integeroptional
The full amount the customer paid.
data.fee_amount
integeroptional
LotiFinance's processing fee, already deducted from amount.
data.net_amount
integeroptional
amount minus fee_amount — what was credited to your balance.

Verifying the signature

Every request includes an X-LotiFinance-Signature header: an HMAC-SHA256 hex digest of the exact request body, signed with your webhook's signing secret (shown once when you create the webhook in the dashboard).

verify.js
import crypto from "crypto";

function isValidSignature(rawBody, signatureHeader, signingSecret) {
  const expected = crypto
    .createHmac("sha256", signingSecret)
    .update(rawBody)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signatureHeader)
  );
}

Compute the HMAC over the raw request body — before any JSON parsing — or the signature won't match.

Delivery behavior

  • Delivery is fire-and-forget with an 8 second timeout.
  • There are no retries. If your endpoint is down or times out, the event is not redelivered. Treat polling via GET /v1/charges/{id}/ as your source of truth, and use the webhook purely as a low-latency notification.
  • Respond quickly with a 2xx status — do heavy processing asynchronously after acknowledging receipt.