Webhooks allow you to set up a notification system that can be used to receive updates on certain requests made to the Waza API.

Verify event origin

Since your webhook URL is publicly available, you need to verify that events originate from Waza and not a bad actor. Use signature validation to ensure events to your webhook URL are from Waza:

Signature validation

Events sent from Waza carry the x-waza-signature header. The value of this header is an HMAC SHA256 signature of the event payload signed using the secret attached to your webhook. Verifying the header signature should be done before processing the event:

var crypto = require('crypto');
var secret = process.env.SECRET_KEY;

// Using Express
app.post("/my/webhook/url", function(req, res) {
    //validate event
    const body = req.body;
    const providedSignature = req.headers["x-waza-signature"];
    const hmac = crypto.createHmac("sha256", secret);
    hmac.update(JSON.stringify(body));
    const hash = hmac.digest("hex");
    const computedSignature = Buffer.from(hash).toString("base64");
  
    if (computedSignature === providedSignature) {
      const event = req.body;
      // Do something with event  
    }
    res.send(200);
});

Go live checklist

Now that you’ve successfully created your webhook URL, here are some ways to ensure you get a delightful experience:

  1. Add the webhook URL on your Waza dashboard or through the webhooks API
  2. Ensure your webhook URL is publicly available (localhost URLs cannot receive events)
  3. If using .htaccess kindly remember to add the trailing / to the URL
  4. Test your webhook to ensure you’re getting the JSON body and returning a 200 OK HTTP response
  5. If your webhook function has long-running tasks, you should first acknowledge receiving the webhook by returning a 200 OK before proceeding with the long-running tasks
  6. If we don’t get a 200 OK HTTP response from your webhooks, we flag it as a failed attempt
  7. Failed attempts are retried with exponential backoff for the next 72 hrs

The Event Object

keytypedescription
idstringUnique identifier for the event
typestringDescription of the event
timestamptimestampTime at which the event object was created. Measured in milliseconds since the Unix epoch.
datahashObject containing data associated with the event
{
  "id": "a6415c98-e959-4b32-a1f8-ef15f141f2fe",
  "type": "order.created",
  "timestamp": "1684320647134",
  "data": {
      "id": "16d91a42-8b39-4485-a84b-58bc461232e2",
      "client_reference": null,
      "amount": 100000,
      "currency": "NGN",
      "receive_amount": 174,
      "receive_currency": "USD",
      "beneficiary_id": "clh9bsjzt0046c0vo6hpw5v1n",
      "state": "pending",
      "metadata": {
        "extra": "Sending GHS for NGN"
      },
      "fee_amount": 0,
      "fee_currency": "NGN",
      "rate": 0.00174044732325749,
      "description": "Test API Transfer",
      "destination": {
        "type": "business",
        "address": "Some address",
        "business_name": "My good business",
        "first_name": null,
        "last_name": null,
        "bank_name": "Test Bank",
        "bank_code": "044",
        "account_number": "11111434"
      },
      "timelines": {
        "payout_sent_date": null,
        "arrival_date": null
      }
    }
}

Event types

TypeDescriptionData type
order.createdA new order has been createdOrder
order.completedOccurs when an order is completedOrder
order.payout_sentWhen payout has been made to a beneficiaryOrder