Wavetop API Docs
Get API Key

Callbacks

When a message or payment reaches a notable state, Wavetop notifies your server with a signed HTTP callback. Provide a callback_url on the requests that support it (for example, messaging) to receive these updates.

How callbacks work

Payload

Every callback body includes status, account_uid, and service, plus a service-specific reference/id pair and, for some services, a data object:

FieldDescription
statusThe reported state, e.g. PAYMENT_OK, MSG_FAILED, MSG_DELIVERED.
account_uidThe account the callback relates to.
serviceThe service that produced it, e.g. AIRTIME, DATA, SMS, FLASH, MOMO.
payment_reference / message_referenceReference of the original request: payment_* for payments, message_* for messaging.
payment_id / message_idYour own client-side identifier, echoed back from the original request. Empty if you didn't supply one.
dataAn optional object carrying additional, service-specific detail about the transaction. For Mobile Money it holds a result object with a code and message. May be omitted or empty for services that send no extra detail.
Payment callback
POST https://your-server.example/callback

{
  "status": "PAYMENT_OK",
  "account_uid": "BS-0000-00000",
  "service": "AIRTIME",
  "payment_reference": "ac736bb9-0b41-4be4-a17c-2037eccef645",
  "payment_id": "",
  "data": {}
}
Messaging callback
POST https://your-server.example/callback

{
  "status": "MSG_FAILED",
  "account_uid": "BS-0000-00000",
  "service": "SMS",
  "message_reference": "bc736bb9-6b41-4be4-a17c-2037eccbf611",
  "message_id": "",
  "data": {}
}
Mobile Money callback
POST https://your-server.example/callback

{
  "status": "PAYMENT_FAILED",
  "account_uid": "BS-0000-00000",
  "service": "MOMO",
  "payment_reference": "momo-712-3f43-4609-a1e1-33f3e6464329",
  "payment_id": "",
  "data": {
    "result": {
      "code": "05",
      "message": "Payment request 2fa failed"
    }
  }
}

Verifying the signature

Callbacks are signed with your account's signature key using HMAC-SHA512, the same primitive documented under Signature. Read the signature header, recompute the hash over the request body with your signature key, and compare the two with a constant-time comparison before trusting the payload.

const crypto = require('crypto');

function verifyCallback(rawBody, headerSignature, secret_key) {
  const expected = crypto
    .createHmac('sha512', secret_key)
    .update(rawBody)          // hash the exact bytes received
    .digest('hex')
    .toLowerCase();

  const a = Buffer.from(expected);
  const b = Buffer.from(String(headerSignature || '').toLowerCase());
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Match the serialization exactly. The hash depends on the precise bytes hashed, so hash the raw request body as received rather than re-serialising a parsed object, or the signatures will not match.