Unofficial Python SDK for integrating AzamPay payment services
Supports Pure Python, Django, Flask, FastAPI, and more.
Note: Versions < 0.1.8 supported Mobile Network Operator (MNO) payments only.
Version 0.1.8+ introduces full Bank Payments support.
| Mobile Money (MNO) | Banks |
|---|---|
| M-Pesa | CRDB |
| Airtel Money | NMB |
| Halopesa | |
| Azampesa | |
| Mix by Yas |
pip install azampay-sdk-angaGo to your account at https://developers.azampay.co.tz/ copy client-id, client-secret and app-name details
Create a .env file in your project root and paste the details/configs:
AZAMPAY_ENVIRONMENT=sandbox # Use 'production' for live
AZAMPAY_APP_NAME=your-app-name
AZAMPAY_CLIENT_ID=your-client-id
AZAMPAY_CLIENT_SECRET=your-secretimport uuid
from azampay import AzamPay
try:
# Generate a unique external ID
external_id = str(uuid.uuid4())
# Sample transaction details
mobile = "0712345678"
amount = 5000
currency = "TZS"
provider = "TIGO" # Options: Mpesa, Airtel, Halotel, Azampesa, Tigo
print("Initiating MNO Checkout...")
response, ref = AzamPay.mno_checkout(
mobile_number=mobile,
amount=amount,
currency=currency,
provider=provider,
external_id=external_id
)
print(f"Transaction Reference: {ref}")
print("Response:", response)
except Exception as e:
print("Transaction failed:", str(e))Important: Register your callback URL in the AzamPay Developer Portal.
Create a webhook endpoint to receive payment status updates somewhere in your project.
import json
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from main import Main # Your class
from db import conn # Your DB connection (e.g., pymysql)
@csrf_exempt
def callback_view(request):
if request.method != "POST":
return HttpResponse("Invalid method", status=405)
try:
data = json.loads(request.body.decode("utf-8"))
except Exception:
return HttpResponse("Server error", status=500)
if not data or "utilityref" not in data or "transactionstatus" not in data:
return HttpResponse("Invalid payload", status=400)
utility_ref = data["utilityref"]
status = "success" if data["transactionstatus"].lower() == "success" else "rejected"
######## Your logic to update status in your db, depends on your database codes and setups ###########
main = Main(conn)
count, result = main.all_query_nolimit_s(
"transactions",
'AND status="pending" LIMIT 1',
"reference",
utility_ref
)
if count > 0:
main.update_custom_o(
"transactions",
"status",
status,
"reference",
utility_ref,
'AND status="pending"'
)
################ End of Db save status ######################
return HttpResponse("Transaction updated", status=200)
return HttpResponse("Transaction not found", status=404)
# Example: urls.py will look like
from django.urls import path
from .views import callback_view
urlpatterns = [
path("callback/", callback_view, name="callback"),
]from flask import Flask, request
from main import Main
from db import conn # Your DB connection (e.g., pymysql)
app = Flask(__name__)
@app.route('/callback', methods=['POST'])
def callback():
if request.method != 'POST':
return "Invalid method", 405
try:
data = request.get_json()
except Exception:
return "Server error", 500
if not data or 'utilityref' not in data or 'transactionstatus' not in data:
return "Invalid payload", 400
utility_ref = data['utilityref']
status = 'success' if data['transactionstatus'].lower() == 'success' else 'rejected'
######## Your logic to update status in your db, depends on your database codes and setups ###########
main = Main(conn)
count, result = main.all_query_nolimit_s(
'transactions',
'AND status="pending" LIMIT 1',
'reference',
utility_ref
)
if count > 0:
main.update_custom_o(
'transactions', 'status', status, 'reference', utility_ref, 'AND status="pending"'
)
return "Transaction updated", 200
else:
return "Transaction not found", 404
################ End of Db save status ######################Transaction Status Check & Redirect Page (Optional and you can design according to your code flow or tech)
Create a route to check payment status and redirect users. (Optional and you can design according to your code flow or tech)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Transaction Status</title>
<link href="{{ url_for('static', filename='bootstrap/css/bootstrap.min.css') }}" rel="stylesheet">
</head>
<body class="bg-light d-flex justify-content-center align-items-center" style="height: 100vh;">
<div class="container text-center">
{% if status == 'success' %}
<div class="alert alert-success shadow p-4 rounded" role="alert">
<h1 class="mb-3">Transaction Approved</h1>
<p class="lead">Your payment was successful.</p>
<a href="/" class="btn btn-success mt-3">Go Home</a>
</div>
{% else %}
<div class="alert alert-danger shadow p-4 rounded" role="alert">
<h1 class="mb-3">Transaction Failed</h1>
<p class="lead">Payment failed. Please try again.</p>
<a href="/" class="btn btn-danger mt-3">Try Again</a>
</div>
{% endif %}
</div>
<script src="{{ url_for('static', filename='bootstrap/js/bootstrap.bundle.min.js') }}"></script>
</body>
</html>- Anganile Adam (Anga) – GitHub: tbwahacker
- AzamPay Team – Official Docs
- Tanzania Developer Community – You can now build with AzamPay in Python!
- All Contributors
Found a bug? Open an issue:
GitHub Issues
If you find this SDK useful, please:
- Star this repository
- Share it with fellow developers
Buy me a coffee
M-Pesa: 0685750593 | 0768571150
Email: twaloadam@gmail.com | anganileadam87@gmail.com
MIT License – Free to use, modify, and distribute.
"Feel free to contribute!"
- Fork the repository
- Create a feature branch
- Document your changes
- Submit a Pull Request with a review request
Happy coding! Make payments easy with AzamPay & Python.

