Tembo
  • Welcome!
  • Introduction
  • Reference
    • Merchant Virtual Accounts
      • Create Merchant Virtual Account
      • Get Account Balance
      • Get Account Statement
      • Webhook Callback
    • Banking & Wallets
      • Create Wallet
      • Deposit Funds
      • Withdraw Funds
      • Wallet to Wallet Transfer
      • Wallet Balance
      • Wallet Statement
      • Main Balance
      • Main Statement
      • List Wallets
    • Make Payment
      • Pay to Mobile
      • Pay to Other Banks
      • Utility Payments
      • Payment Status
    • Collect Money
      • Collect from Mobile Money
      • Collection Balance
      • Collection Statement
      • Payment Status
    • eKYC
      • Start Onboarding
      • Retrieve First Question
      • Reply to Question
    • Remittance
      • API Overview
      • Create Remittance
      • Transaction Status
      • Callback Notification
Powered by GitBook
On this page
  • Overview
  • Important Notes
  • Callback Method
  • Example Implementation
  • Best Practices
  1. Reference
  2. Remittance

Callback Notification

Overview

The TemboPlus Remittance API includes a callback notification service that automatically notifies you when a transaction's status changes. This enables real-time monitoring and immediate response to successful payments, failures, or other status updates.

When a transaction is processed, the system will send a POST request to the callbackUrl you provided in the original remittance request. Your callback endpoint should respond with an HTTP status code 200 to acknowledge receipt of the callback.

Important Notes

  • Callback requests are not authenticated, so you should validate transaction status using the Transaction Status endpoint.

  • Your callback endpoint should respond with HTTP status code 200 to acknowledge receipt of the callback.

  • If your callback endpoint is unavailable or returns an error, the system will retry sending the notification several times before giving up.

Callback Method

POST {callbackUrl}

The system will send a POST request to the callbackUrl you provided in the original remittance request.

Headers

Name
Type
Description

Content-Type

string

application/json

x-request-id

string

The same UUID from the original request for traceability

Callback Payload

The callback payload contains complete information about the transaction, including its current status. This is identical to the response format from the Transaction Status endpoint.

Name
Type
Description

transactionId

string

Unique system-generated identifier for the transaction

paymentDate

string

Transaction initiation timestamp in ISO 8601 format

senderCurrency

string

ISO currency code of funds from the remitting partner

senderAmount

number

Amount debited from the remitting partner in sender's currency

receiverCurrency

string

ISO currency code for local disbursement

receiverAmount

number

Amount disbursed to the recipient in local currency

exchangeRate

number

Conversion rate applied between sender and receiver currencies

transactionFee

number

Fee charged for processing the transaction in receiver's currency

transactionAmount

number

Total amount including the principal and fee in receiver's currency

transactionDate

string

The timestamp when the transaction was processed by the receiving institution

receiverAccount

string

Account identifier for fund disbursement (mobile number or bank account)

receiverChannel

string

Disbursement channel type: MOBILE or BANK

institutionCode

string

Financial institution or mobile network operator code

partnerReference

string

Unique transaction identifier from the remitting partner

institutionReference

string

Reference number provided by the receiving financial institution

status

string

Current transaction status (e.g., COMPLETED, FAILED)

statusCode

string

Detailed status code (e.g., PAYMENT_SUCCESS)

statusMessage

string

Human-readable description of the current transaction status

receiptNumber

string

Receipt number for successful transactions

createdAt

string

Timestamp when the transaction was created in the system

updatedAt

string

Timestamp when the transaction was last updated

completedAt

string

Timestamp when the transaction reached a terminal state

Example Callback Payload

{
  "transactionId": "550e8400e29b41d4a716446655440000",
  "paymentDate": "2025-02-27T10:56:00Z",
  "senderCurrency": "USD",
  "senderAmount": 100.00,
  "receiverCurrency": "TZS",
  "receiverAmount": 250000.00,
  "exchangeRate": 2500.00,
  "transactionFee": 2500,
  "transactionAmount": 252500.00,
  "transactionDate": "2025-02-18T10:00:00Z",
  "receiverAccount": "255745908755",
  "receiverChannel": "MOBILE",
  "institutionCode": "VODACOM",
  "partnerReference": "HSC8474837-VS83",
  "institutionReference": "58577.55885.93993",
  "status": "COMPLETED",
  "statusCode": "PAYMENT_SUCCESS",
  "statusMessage": "Success",
  "receiptNumber": "RM48474558557",
  "createdAt": "2025-02-18T10:05:00Z",
  "updatedAt": "2025-02-18T10:05:00Z",
  "completedAt": "2025-02-18T10:05:00Z"
}

Example Implementation

Here is a simple example of how to implement a callback endpoint using Node.js and Express:

const express = require('express');
const app = express();
app.use(express.json());

app.post('/callback', async (req, res) => {
  try {
    // Extract the callback data
    const callbackData = req.body;
    
    // Get the request ID for traceability
    const requestId = req.headers['x-request-id'];
    
    console.log(`Received callback for transaction: ${callbackData.partnerReference}`);
    console.log(`Request ID: ${requestId}`);
    console.log(`Status: ${callbackData.status} (${callbackData.statusCode})`);
    
    // Process the callback according to the transaction status
    switch (callbackData.status) {
      case 'COMPLETED':
        // Handle successful transaction
        await updateTransactionInDatabase(callbackData);
        break;
      case 'FAILED':
        // Handle failed transaction
        await handleFailedTransaction(callbackData);
        break;
      // Handle other statuses as needed
    }
    
    // Always respond with 200 OK to acknowledge receipt
    res.status(200).send({ received: true });
  } catch (error) {
    console.error('Error processing callback:', error);
    // Still respond with 200 OK to prevent retries
    res.status(200).send({ received: true });
  }
});

app.listen(3000, () => {
  console.log('Callback server listening on port 3000');
});

Best Practices

  1. Validate Transaction Status: Since callbacks are not authenticated, always verify important status changes using the Transaction Status endpoint.

  2. Implement Idempotency: The same callback might be sent multiple times if your service is temporarily unavailable. Ensure your processing logic is idempotent to handle duplicate callbacks gracefully.

  3. Respond Quickly: Your callback endpoint should process the notification asynchronously and respond with a 200 status code as quickly as possible.

  4. Log Everything: Store all callback data for troubleshooting and reconciliation purposes.

  5. Handle All Status Codes: Be prepared to handle all possible transaction statuses, including intermediate states and error conditions.

PreviousTransaction Status