Payout Webhooks

LedgerBlock uses webhooks to notify your application when the status of a payout changes. Instead of repeatedly checking the payout status, you can provide a notification URL and LedgerBlock will send an HTTP request to your endpoint whenever a relevant payout event occurs.

This allows your system to automatically update the payout status and take the appropriate action.

How Payout Webhooks Work

The payout webhook flow is:

  1. Your application creates a payout through the LedgerBlock API.
  2. LedgerBlock processes the payout.
  3. Your application provides a notification URL for LedgerBlock to send webhook events to.
  4. When the payout status changes, LedgerBlock sends a webhook request to the configured notification URL.
  5. Your server receives and verifies the webhook.
  6. Your application updates the corresponding payout record based on the event.

For example:

Create Payout
     ↓
Payout Processing
     ↓
Status Changes
     ↓
LedgerBlock sends Webhook
     ↓
Merchant Notification URL
     ↓
Verify Webhook
     ↓
Update Payout Status

Notification URL

The notification URL is the endpoint on your server that receives payout webhook notifications from LedgerBlock.

You configure or update this URL through the appropriate LedgerBlock notification endpoint.

Your endpoint should be publicly accessible and capable of accepting HTTP POST requests.

Example:

https://your-domain.com/webhooks/ledgerblock/payout

The notification URL is configured on the LedgerBlock side. Once configured, LedgerBlock uses this URL whenever it needs to notify your application about a payout event.

Webhook Secret

LedgerBlock uses a webhook secret to help your application verify that an incoming webhook was sent by LedgerBlock.

The webhook secret is a private value associated with your webhook configuration. It should be stored securely on your server and should never be exposed in client-side applications or committed to source control.

The webhook secret is not part of the payout request body.

Instead, it is used when your application verifies the authenticity and integrity of the webhook notification received from LedgerBlock.

Never expose your webhook secret publicly.

Payout Webhook Request

When a payout event occurs, LedgerBlock sends a POST request to your configured notification URL.

Example:

POST /webhooks/ledgerblock/payout
Content-Type: application/json

The request contains information about the payout and its current status.

Example payload:

{
  "event": "payout.updated",
  "status": "successful",
  "data": {
    "reference": "PAY-8F72A19C",
    "amount": 50000,
    "currency": "NGN",
    "account_number": "0123456789",
    "account_name": "John Doe",
    "bank_code": "058",
    "bank_name": "GTBank",
    "reason": null
  },
  "timestamp": "2026-09-02T07:30:00Z"
}

The exact fields and values depend on the payout event and the information available for the transaction.

Payout Statuses

A payout may move through different statuses during processing.

Common payout states include:

StatusDescription
pendingThe payout has been created and is waiting to be processed.
processingLedgerBlock is currently processing the payout.
successfulThe payout has been completed successfully.
failedThe payout could not be completed.

Your application should update its internal payout record whenever it receives a valid status update.

Verifying the Webhook

When your server receives a webhook, it should verify the request before processing the payload.

The verification process uses the webhook secret associated with your LedgerBlock webhook configuration.

At a high level:

Webhook received
      ↓
Read verification/signature information
      ↓
Use your webhook secret to validate the request
      ↓
Verification successful?
   ↙            ↘
 Yes             No
 ↓                ↓
Process event    Reject request

Do not process payout events until the webhook has been successfully verified.

Your application should also ensure that the same webhook event is not processed multiple times.

Handling Duplicate Webhooks

Webhook requests can potentially be delivered more than once.

Your webhook handler should therefore be idempotent.

Use a unique transaction or event reference to determine whether an event has already been processed.

For example:

Webhook received
       ↓
Check payout reference
       ↓
Already processed?
   ↙            ↘
 Yes             No
 ↓                ↓
Ignore           Process

This prevents duplicate balance updates, notifications, or other side effects.

Webhook Response

After successfully receiving and processing a webhook, your endpoint should return a successful HTTP response.

Example:

HTTP/1.1 200 OK
Content-Type: application/json
{
  "status": "success"
}

A successful response tells LedgerBlock that your application received the notification.

If your endpoint returns an error or is unavailable, LedgerBlock may attempt to deliver the webhook again.

Recommended Webhook Handler

Your webhook endpoint should generally follow this sequence:

1. Receive webhook
2. Read request headers and body
3. Verify the webhook using your webhook secret
4. Validate the payload
5. Check whether the event has already been processed
6. Update the payout record
7. Trigger any required business logic
8. Return HTTP 200

Example Implementation

A simplified Node.js example:

app.post("/webhooks/ledgerblock/payout", async (req, res) => {
  try {
    // Verify the webhook using your LedgerBlock webhook secret
    const isValid = verifyWebhook(req);

    if (!isValid) {
      return res.status(401).json({
        status: "error",
        message: "Invalid webhook"
      });
    }

    const { event, data } = req.body;

    // Prevent duplicate processing
    const alreadyProcessed = await isEventProcessed(data.reference);

    if (alreadyProcessed) {
      return res.status(200).json({
        status: "success"
      });
    }

    // Update payout status
    await updatePayoutStatus(
      data.reference,
      req.body.status
    );

    // Mark event as processed
    await markEventAsProcessed(data.reference);

    return res.status(200).json({
      status: "success"
    });

  } catch (error) {
    return res.status(500).json({
      status: "error"
    });
  }
});

The verification function in this example is illustrative. Implement the verification logic using the signature/header format provided by LedgerBlock.

Important Security Practices

Keep your webhook secret private and store it securely in environment variables or a secrets manager.

Do not trust the webhook payload solely because it was received by your endpoint. Always perform the required verification before processing it.

Your webhook endpoint should use HTTPS in production.

Your application should also be designed to handle duplicate webhook deliveries safely.

Testing Webhooks

During integration, you should test your webhook endpoint with payout events representing the different stages of a payout.

At minimum, verify that your application correctly handles:

  • Pending payouts
  • Processing payouts
  • Successful payouts
  • Failed payouts
  • Duplicate webhook events
  • Invalid webhook signatures
  • Malformed webhook payloads

A successful integration should result in your internal payout record matching the latest verified status received from LedgerBlock.


Did this page help you?