Skip to main content
When you make a transfer request, you typically have to wait for a payment to be sent into/out of the platform before that transfer can be updated as done. This can be achieved by either polling the GET Transfer API or by listening to a webhook URL. A webhook URL is simply a POST endpoint that the Busha API server sends updates to. The URL needs to receive and parse a JSON request and return a 200 OK response.
Webhook is the recommended way to listen for updates for a transfer request as the polling alternative will not be reliable due to poor connection on the client side, which you do not have control over.

Prerequisites

Before you start, make sure you have:

Step 1: Create A Webhook URL

Before you can receive webhook events from Busha, you need a dedicated URL where these events will be sent. This URL acts as the listener for all notifications your application needs to process. You have two primary options for setting up this endpoint: For Production Environments (Your Application) For a live, robust integration, you will need to create a specific endpoint within your own application’s backend. This endpoint should be:
  • Publicly Accessible: It must be a live URL that Busha’s servers can reach over the internet (e.g., https://your-domain.com/busha-webhook). Localhost URLs will not work.
  • Configured to Receive POST Requests: Your endpoint should be designed to listen for and process incoming HTTP POST requests, as this is how Busha will deliver webhook payloads.
  • Designed for Processing: This endpoint should contain the logic to verify the webhook signature (for security) and then process the event data according to your application’s needs.
For Testing and Development (e.g., Webhook.site) If you are just getting started, testing your integration, or inspecting webhook payloads, you can use a temporary third-party service to generate a quick webhook URL:
  • Using Webhook.site: Navigate to webhook.site. The site will instantly provide you with a unique, temporary URL.
  • Functionality: Any POST requests sent to this URL will be immediately displayed on the page, allowing you to inspect the payload, headers, and other details.
  • Important Note: URLs generated by services like Webhook.site are for testing and development purposes only and should never be used in a production environment due to their temporary nature and lack of security controls.

Step 2: Create A New Webhook

After you have created your webhook URL, you need to visit the developer tools section on your dashboard to register the URL. Profile > Developer Tools > Webhooks Profile > Developer tools > Webhooks Click on the “Webhooks” button. You should see an input form like this: Create webhook form Enter a name for your webhook and include the full path to the webhook URL you created in the previous step. Click on the “Create webhook” button, then copy your secret key. Webhook secret key
Ensure to copy your Webhook Secret Key and truly keep it secret. This secret is important and will be used to validate that every request made to your webhook URL is genuinely from Busha.

Step 3: Listen for Events

Verifying Webhook Signature To calculate and verify the x-bu-signature, perform a HMAC hash of the request body using the Webhook secret as the key. For example:
func ValidateHMACChecksum(body []byte, checksum string) (bool, error) {
    mac := hmac.New(sha256.New, []byte(hmacSecret))
    mac.Write(body)
    expectedMAC := mac.Sum(nil)
    actualMAC, err := base64.StdEncoding.DecodeString(checksum)
    if err != nil {
       return false, fmt.Errorf("failed to decode checksum: %w", err)
    }
    return hmac.Equal(actualMAC, expectedMAC), nil
}
Webhooks receive the following events from Busha:
Event TypesDescription
transfer.pendingA new Transfer has been initiated and is pending
transfer.processingA transfer is processing.
transfer.cancelledA transfer has been cancelled by the user.
transfer.funds_receivedA deposit transfer has been received successfully.
transfer.funds_convertedAn internal conversion transfer has been completed
transfer.outgoing_payment_sentA payout transfer to a recipient or external wallet address has been sent to the beneficiary and awaiting confirmation of receipt.
transfer.funds_deliveredA payout transfer has been confirmed as received by the beneficiary successfully.
Sample Event Payload:
{
  "business_id": "BUS_tg6yujbZ1nMu5BLQkPGGO",
  "event": "transfer.funds_converted",
  "data": {
    "id": "TRF_BaAUvCTlZCt3hu3OO4u8P",
    "profile_id": "BUS_tg6yujbZ1nMu5BLQkPGGO",
    "quote_id": "QUO_5CnpikeQJEKQoDcnOsdkU",
    "source_currency": "NGN",
    "target_currency": "USDT",
    "source_amount": "10000",
    "target_amount": "5.728032",
    "rate": {
      "product": "USDTNGN",
      "rate": "1745.8",
      "side": "buy",
      "type": "FIXED",
      "source_currency": "NGN",
      "target_currency": "USDT"
    },
    "fees": [],
    "status": "completed",
    "created_at": "2025-02-21T09:55:20.852345Z",
    "updated_at": "2025-02-21T09:55:22.365451Z"
  }
}

Transfer Status Development

The following section aims to show how a transfer can develop from one status to another. This will show you understand how to properly handle and anticipate webhook events. **Transfer.Pending: This is the initial status for all transfers. All transfers start as pending, and a pending transfer can morph into only two next statuses:
  • transfer.cancelled
  • transfer.processing
Pending status flow diagram Transfer.Cancelled: A cancelled transfer means that the transfer was unable to continue and can not begin processing. Hence, this is a final state that can not further change. Transfer.Processing: A processing transfer means that the transfer has started work and is already making the money movement from the destination to the source. A processing transfer can change into any of these statuses depending on the transfer type:
  • transfer.outgoing_payment_sent
  • transfer.funds_received
  • transfer.funds_converted
Processing status flow diagram Transfer.OutgoingPaymentSent: An outgoing_payment_sent status represents any transfer that involves sending money out of the Busha platform to an external bank account or an external wallet address. It is not a final status; the outgoing_payment_sent status can morph into a final funds_delivered status Outgoing payment status flow diagram Funds.Delivered: This is a final status that communicates that a payout transfer has been delivered successfully to the specified destination. Funds.Received: The funds_received status communicates that a Deposit into a Busha Balance has been successful. This could be a final status for all deposit transfers; however, in a scenario where the source currency is not the same as the target currency, then this transfer will further change into a funds_converted status. Funds.Converted: The funds_converted status communicates that a conversion transfer has been done successfully. This is also the same status that communicated the successful Buy/Sell Trade.

Transfer Status Change Map

Transfer Status Change Map Conversions and Trades(Buy/Sell) Status Change:
pending → processing → funds_converted
Payouts Status Change:
pending → processing → outgoing_payment_sent → funds_delivered
Deposit Status Change:
pending → processing → funds_received
On-Ramp (External Fiat → Crypto):
pending → processing → funds_received → funds_converted