SchoolPay API Documentation

Welcome to the SchoolPay API documentation. Choose a category below to explore our integration options.

Authentication (Sync API)

All requests require a security hash for authentication. The hash is an MD5 hash of specific parameters concatenated with your school's API password.

Note: Your API password should be kept secret and never shared or exposed in client-side code.
Hash Formula:
MD5(schoolCode + identifyingDate + password)
  • schoolCode: Your unique school identifier.
  • identifyingDate: The transaction date (for single date) or fromDate (for range requests).
  • password: Your assigned transactions API password.
GET /AndroidRS/SyncSchoolTransactions/{schoolCode}/{transactionDate}/{requestHash}
Active
Description

Fetches transactions for a school on a specific date. Returns both regular transactions and supplementary fee payments.

Path Parameters
Parameter Type Description
schoolCode String The school code (numeric)
transactionDate String Date in YYYY-MM-DD format
requestHash String MD5(schoolCode + transactionDate + password)
Response Structure

A JSON object containing returnCode, transactions, and supplementaryFeePayments.

Sample Response JSON
{
    "returnCode": 0,
    "returnMessage": "3 transaction(s) found (1 regular, 2 supplementary fee)",
    "supplementaryFeePayments": [
        {
            "amount": "150000.00",
            "paymentDateAndTime": "2023-08-22 13:35:36",
            "schoolpayReceiptNumber": "18843597",
            "settlementBankCode": "CENTENARY",
            "sourceChannelTransDetail": "1000000001,Jim Kapere,UNIFORM FEES UNIFORM FEES",
            "sourceChannelTransactionId": "21882064988",
            "sourcePaymentChannel": "MTN MobileMoney",
            "studentClass": "JUNIORTWO",
            "studentName": "Jim Kapere",
            "studentPaymentCode": "1000000001",
            "studentRegistrationNumber": "",
            "supplementaryFeeDescription": "UNIFORM FEES",
            "supplementaryFeeId": "20",
            "transactionCompletionDateAndTime": "2023-08-22 13:35:36",
            "transactionCompletionStatus": "Completed"
        },
        {
            "amount": "35000.00",
            "paymentDateAndTime": "2023-08-22 13:36:53",
            "schoolpayReceiptNumber": "18843615",
            "settlementBankCode": "CENTENARY",
            "sourceChannelTransDetail": "1000000002,Sam Kikoobe,UNIFORM FEES UNIFORM FEES",
            "sourceChannelTransactionId": "21882082108",
            "sourcePaymentChannel": "MTN MobileMoney",
            "studentClass": "J3",
            "studentName": "Sam Kikoobe",
            "studentPaymentCode": "1000000002",
            "studentRegistrationNumber": "",
            "supplementaryFeeDescription": "UNIFORM FEES",
            "supplementaryFeeId": "20",
            "transactionCompletionDateAndTime": "2023-08-22 13:36:53",
            "transactionCompletionStatus": "Completed"
        }
    ],
    "transactions": [
        {
            "amount": "350000",
            "paymentDateAndTime": "2023-08-22 12:45:42",
            "schoolpayReceiptNumber": "18843014",
            "settlementBankCode": "CENTENARY",
            "sourceChannelTransDetail": "PHIONAH NABALAMBA",
            "sourceChannelTransactionId": "90269163351",
            "sourcePaymentChannel": "Airtel Money",
            "studentName": "Rachelle  Faith",
            "studentPaymentCode": "1005416321",
            "studentRegistrationNumber": "",
            "transactionCompletionStatus": "Completed"
        }
    ]
}
Code Samples
$schoolCode = "123456";
$date = "2024-01-15";
$password = "your_secret_password";
$hash = strtoupper(md5($schoolCode . $date . $password));

$url = "https://schoolsuite.co.ug/AndroidRS/SyncSchoolTransactions/$schoolCode/$date/$hash";
$response = file_get_contents($url);
$data = json_decode($response, true);
const axios = require('axios');
const crypto = require('crypto');

const schoolCode = "123456";
const date = "2024-01-15";
const password = "your_secret_password";
const hash = crypto.createHash('md5')
    .update(schoolCode + date + password)
    .digest('hex').toUpperCase();

axios.get(`https://schoolsuite.co.ug/AndroidRS/SyncSchoolTransactions/${schoolCode}/${date}/${hash}`)
    .then(res => console.log(res.data));
import requests
import hashlib

school_code = "123456"
date = "2024-01-15"
password = "your_secret_password"

hash_input = school_code + date + password
request_hash = hashlib.md5(hash_input.encode()).hexdigest().upper()

url = f"https://schoolsuite.co.ug/AndroidRS/SyncSchoolTransactions/{school_code}/{date}/{request_hash}"
response = requests.get(url)
print(response.json())
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import java.security.MessageDigest;

public class SyncTransactions {
    public static void main(String[] args) throws Exception {
        String schoolCode = "123456";
        String date = "2024-01-15";
        String password = "your_secret_password";
        
        String input = schoolCode + date + password;
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] hashBytes = md.digest(input.getBytes());
        StringBuilder sb = new StringBuilder();
        for (byte b : hashBytes) sb.append(String.format("%02X", b));
        String hash = sb.toString();

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://schoolsuite.co.ug/AndroidRS/SyncSchoolTransactions/" + schoolCode + "/" + date + "/" + hash))
            .header("Accept", "application/json")
            .build();

        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.body());
    }
}
using System;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

class Program {
    static async Task Main() {
        string schoolCode = "123456";
        string date = "2024-01-15";
        string password = "your_secret_password";

        string input = schoolCode + date + password;
        using (MD5 md5 = MD5.Create()) {
            byte[] inputBytes = Encoding.ASCII.GetBytes(input);
            byte[] hashBytes = md5.ComputeHash(inputBytes);
            string hash = Convert.ToHexString(hashBytes).ToUpper();

            using HttpClient client = new HttpClient();
            client.DefaultRequestHeaders.Add("Accept", "application/json");
            string url = $"https://schoolsuite.co.ug/AndroidRS/SyncSchoolTransactions/{schoolCode}/{date}/{hash}";
            string response = await client.GetStringAsync(url);
            Console.WriteLine(response);
        }
    }
}
Try it out
GET /AndroidRS/SchoolRangeTransactions/{schoolCode}/{fromDate}/{toDate}/{requestHash}
Active
Description

Fetches transactions for a school within a date range (max 31 days). Returns both regular transactions and supplementary fee payments.

Path Parameters
Parameter Type Description
schoolCode String The school code (numeric)
fromDate String Start date in YYYY-MM-DD format
toDate String End date in YYYY-MM-DD format
requestHash String MD5(schoolCode + fromDate + password)
Response Structure

A JSON object containing returnCode, transactions, and supplementaryFeePayments.

Sample Response JSON
{
    "returnCode": 0,
    "returnMessage": "3 transaction(s) found (1 regular, 2 supplementary fee)",
    "supplementaryFeePayments": [
        {
            "amount": "150000.00",
            "paymentDateAndTime": "2023-08-22 13:35:36",
            "schoolpayReceiptNumber": "18843597",
            "settlementBankCode": "CENTENARY",
            "sourceChannelTransDetail": "1000000001,Jim Kapere,UNIFORM FEES UNIFORM FEES",
            "sourceChannelTransactionId": "21882064988",
            "sourcePaymentChannel": "MTN MobileMoney",
            "studentClass": "JUNIORTWO",
            "studentName": "Jim Kapere",
            "studentPaymentCode": "1000000001",
            "studentRegistrationNumber": "",
            "supplementaryFeeDescription": "UNIFORM FEES",
            "supplementaryFeeId": "20",
            "transactionCompletionDateAndTime": "2023-08-22 13:35:36",
            "transactionCompletionStatus": "Completed"
        },
        {
            "amount": "35000.00",
            "paymentDateAndTime": "2023-08-22 13:36:53",
            "schoolpayReceiptNumber": "18843615",
            "settlementBankCode": "CENTENARY",
            "sourceChannelTransDetail": "1000000002,Sam Kikoobe,UNIFORM FEES UNIFORM FEES",
            "sourceChannelTransactionId": "21882082108",
            "sourcePaymentChannel": "MTN MobileMoney",
            "studentClass": "J3",
            "studentName": "Sam Kikoobe",
            "studentPaymentCode": "1000000002",
            "studentRegistrationNumber": "",
            "supplementaryFeeDescription": "UNIFORM FEES",
            "supplementaryFeeId": "20",
            "transactionCompletionDateAndTime": "2023-08-22 13:36:53",
            "transactionCompletionStatus": "Completed"
        }
    ],
    "transactions": [
        {
            "amount": "350000",
            "paymentDateAndTime": "2023-08-22 12:45:42",
            "schoolpayReceiptNumber": "18843014",
            "settlementBankCode": "CENTENARY",
            "sourceChannelTransDetail": "PHIONAH NABALAMBA",
            "sourceChannelTransactionId": "90269163351",
            "sourcePaymentChannel": "Airtel Money",
            "studentName": "Rachelle  Faith",
            "studentPaymentCode": "1005416321",
            "studentRegistrationNumber": "",
            "transactionCompletionStatus": "Completed"
        }
    ]
}
Code Samples
$schoolCode = "123456";
$fromDate = "2024-01-01";
$toDate = "2024-01-31";
$password = "your_secret_password";
$hash = strtoupper(md5($schoolCode . $fromDate . $password));

$url = "https://schoolsuite.co.ug/AndroidRS/SchoolRangeTransactions/$schoolCode/$fromDate/$toDate/$hash";
$response = file_get_contents($url);
const schoolCode = "123456";
const fromDate = "2024-01-01";
const toDate = "2024-01-31";
const password = "your_secret_password";
const hash = crypto.createHash('md5')
    .update(schoolCode + fromDate + password)
    .digest('hex').toUpperCase();

const url = `https://schoolsuite.co.ug/AndroidRS/SchoolRangeTransactions/${schoolCode}/${fromDate}/${toDate}/${hash}`;
// Similar to single date, but use fromDate for hash
String input = schoolCode + fromDate + password;
// ... MD5 logic ...
String url = "https://schoolsuite.co.ug/AndroidRS/SchoolRangeTransactions/" + schoolCode + "/" + fromDate + "/" + toDate + "/" + hash;
// Similar to single date, but use fromDate for hash
string input = schoolCode + fromDate + password;
// ... MD5 logic ...
string url = $"https://schoolsuite.co.ug/AndroidRS/SchoolRangeTransactions/{schoolCode}/{fromDate}/{toDate}/{hash}";
Try it out
This API enables partners to register and request one-time payments. Payments can be tracked via status inquiry or automated callbacks.

1. API Authentication

Every request to the Adhoc API must be authenticated using an MD5 hash.

Hash Formula: MD5(SchoolCode + IdentifyingReference + Password)
  • SchoolCode: Your unique school identifier (e.g., 809).
  • IdentifyingReference:
    • Use externalReference for Register and Request calls.
    • Use paymentReference for Status Check calls.
  • Password: Your assigned API secret password.
POST https://schoolsuite.co.ug/AndroidRS/AdhocPayments/Register/{SchoolCode}/{Hash}
Active
Description

Generates a unique payment reference for mobile money, bank, or agent payments.

Sample Request Body
{
  "amount": 52000,
  "externalReference": "63140",
  "firstName": "Kapere",
  "lastName": "Lugard",
  "reason": "Admissions 2021",
  "callBackUrl": "https://testsystem.com/callback"
}
Sample Response
{
  "paymentReference": "21AD100011",
  "returnCode": 0,
  "returnMessage": "Request has been processed",
  "status": "PENDING"
}
Try it out
POST https://schoolsuite.co.ug/AndroidRS/AdhocPayments/Request/{SchoolCode}/{Hash}
Active
Description

Triggers an instant mobile money debit request to the payer's phone.

Request Body (with Phone)
{
  "amount": 52000,
  "externalReference": "63140",
  "phoneNumber": "0771000955",
  "firstName": "Kapere",
  "lastName": "Lugard",
  "reason": "Admissions 2021"
}
The phoneNumber should be in local format (e.g., 077...) or international format (25677...).
Success Response
{
  "returnCode": 0,
  "returnMessage": "Debit request sent",
  "paymentReference": "21AD100012",
  "status": "PENDING"
}
GET https://schoolsuite.co.ug/AndroidRS/AdhocPayments/Check/{SchoolCode}/{Hash}/{Reference}
Active
Description

Inquire on the final payment status using the SchoolPay reference.

Sample Response (PAID)
{
  "paymentCode": "21AD100010",
  "receiptNumber": "5615857",
  "status": "PAID",
  "transactionId": "1188814",
  "returnCode": 0
}
Try it out

5. Payment Callback

SchoolPay sends an automated POST request to your callBackUrl upon successful payment.

Callback Payload
{
  "amount": 52000,
  "channelName": "Airtel Money",
  "paymentReference": "21AD100011",
  "receiptNumber": "5615855",
  "status": "PAID",
  "transactionId": "1188813",
  "returnCode": 0
}
Always verify the status field is PAID before updating your system records.
In addition to the Sync API, SchoolPay provides a Web Hook notification service. This allows your system to receive real-time notifications when a payment is made.

How it Works

A school can register a web hook URL in their school portal interface. Once configured and enabled, SchoolPay will send a POST request with a JSON payload to the registered URL for every successful payment.

Important: Your endpoint must be public-facing and capable of receiving POST requests from SchoolPay servers.

Sample Notification Payloads

1. School Fees Payment Payload
{
    "signature": "903203ed81d54a0916dd562886cf8e69a831aaf2f81da501408e93cf25d75b08",
    "type": "SCHOOL_FEES",
    "payment": {
        "amount": "50000",
        "paymentDateAndTime": "2026-01-29 20:01:52",
        "schoolpayReceiptNumber": "18847257",
        "settlementBankCode": "TROPICAL",
        "sourceChannelTransDetail": "John Doe",
        "sourceChannelTransactionId": "TXN_9876543220",
        "sourcePaymentChannel": "MTN MobileMoney",
        "studentName": "Jeremy Kyagulanyi Soran",
        "studentPaymentCode": "1006480152",
        "studentRegistrationNumber": "HIS-252",
        "transactionCompletionStatus": "Completed"
    }
}
2. Supplementary Fees Payment Payload
{
    "signature": "903203ed81d54a0916dd562886cf8e69a831aaf2f81da501408e93cf25d75b08",
    "type": "OTHER_FEES",
    "payment": {
        "amount": "150000.00",
        "paymentDateAndTime": "2023-08-22 13:35:36",
        "schoolpayReceiptNumber": "18843597",
        "settlementBankCode": "CENTENARY",
        "sourceChannelTransDetail": "1001289533,Bronze Ellah Nvanungi,UNIFORM FEES UNIFORM FEES",
        "sourceChannelTransactionId": "21882064988",
        "sourcePaymentChannel": "MTN MobileMoney",
        "studentClass": "JUNIORTWO",
        "studentName": "Bronze Ellah Nvanungi",
        "studentPaymentCode": "1001289533",
        "studentRegistrationNumber": "",
        "supplementaryFeeDescription": "UNIFORM FEES",
        "supplementaryFeeId": "20",
        "transactionCompletionDateAndTime": "2023-08-22 13:35:36",
        "transactionCompletionStatus": "Completed"
    }
}

Security & Verification

Signature Verification

The signature sent in the payload is a SHA256 HEX hash of the concatenation of:

Your School's API Password + schoolpayReceiptNumber

It is highly recommended to verify this signature on the receiving end before accepting the payment to ensure the request is legitimate.

IP Whitelisting

For additional security, we advise implementing IP whitelisting on your server. The source IP addresses of our notification servers can be provided upon request should you need to apply this layer of security.

Server Response

Upon successfully receiving the callback, your server should return an HTTP status 200 (OK).

Note that the response body itself is not processed by SchoolPay; only the HTTP status code is used to determine if the delivery was successful.

Troubleshooting: Why am I not receiving web hook calls?

  • Configuration: Confirm that the Web Hook URL is correctly configured and that Web Hooks are explicitly enabled in the school portal.
  • Single Attempt: Web Hooks are sent only once. If your server is down or unreachable during the attempt, the notification will not be retried.
  • Subscription: Web Hooks are only sent if the school has a valid, active subscription with SchoolPay. If the subscription has expired, notifications will be suppressed.