Integration Guide
Connect your application with Payme Africa using our secure HMAC-authenticated REST API. Follow this guide to authenticate and process transactions.
Authentication
All API requests must be authenticated using a custom HMAC-SHA256 signature. Include these headers with every request.
| Header | Description |
|---|---|
Content-Type Required |
Must be application/json |
X-App-ID Required |
Your unique App Identifier (e.g., MOBILE_APP_01) |
X-Timestamp Required |
Current Unix timestamp (integer). Used for signature and replay attack protection. |
X-Signature Required |
Base64 encoded HMAC‑SHA256 hash of MinifiedJSONBody + Timestamp using your
App Secret. |
X-Sandbox Optional |
Set to 1 to run in sandbox mode. Transactions are simulated and balance is
isolated. |
Replay Protection: Requests with a timestamp older than 5 minutes will be automatically rejected. Always use the current Unix timestamp.
Integration Flows
Understand the end-to-end process for the most common integration scenarios.
1. Mobile Collection (Push)
Initiate payment → Customer receives USSD prompt → Enters PIN → You receive webhook confirmation.
2. Disbursement (Payout)
Check balance → Lookup Recipient (optional) → Submit Payout → Funds delivered instantly.
3. Card Tokenization & Pay
Redirect to Hosted Checkout → Save Card → Receive Token → Charge Token later for one-tap payments.
4. VCN Lifecycle
Submit Details → Issue Card → Show Details (Secure) → User pays online → Funds deducted from your app balance.
Collection (Receive Money)
Initiate a USSD push payment to a customer's mobile wallet. The customer will receive a prompt on their handset to confirm payment.
| Parameter | Type | Description |
|---|---|---|
action Required |
string | Must be "collection" |
amount Required |
integer | Amount in TZS. Must be greater than 0. |
msisdn Required |
string | Customer's phone number in international format (e.g., 255700000000) |
reference Required |
string | Your unique transaction reference. Must be globally unique per client. |
callback_url Optional |
string | URL to receive webhook notifications for this specific transaction. |
{
"action": "collection",
"amount": 1000,
"msisdn": "255700000000",
"reference": "ORDER_101",
"callback_url": "https://yourapp.com/callback"
}
{
"status": "success",
"transaction_id": "901",
"payment_status": "PENDING",
"provider_response": {
"result": "SUCCESS",
"resultcode": "000",
"message": "Payment notification logged"
}
}
Disbursement (Send Money)
Send funds to various channels. Use the channel field to route the
disbursement to the correct network or bank.
Card Payments & Checkout
There are two ways to process card payments: using a Hosted Checkout (for new cards) or Stored Card Tokens (for one-tap payments).
Important: Card payments with no billing info will be rejected by Selcom. Ensure all billing_* fields are provided.
Hosted Checkout (New Cards)
Use the checkout action to receive a payment_gateway_url where the customer can enter their card details.
{
"action": "checkout",
"amount": 10000,
"reference": "INV-1001",
"billing_firstname": "John",
"billing_lastname": "Doe",
"billing_address_1": "969 Market Street",
"billing_city": "San Francisco",
"billing_state_or_region": "CA",
"billing_postcode_or_pobox": "94103",
"billing_country": "US",
"billing_phone": "255000000000",
"redirect_url": "https://yourapp.com/success",
"cancel_url": "https://yourapp.com/cancel"
}
Stored Card Payment (One-tap)
Use the card-payment action with a previously obtained card_token.
{
"action": "card-payment",
"amount": 5000,
"reference": "INV-202",
"card_token": "CT_987654321",
"buyer_userid": "user_123",
"gateway_buyer_uuid": "GB_uuid_001"
}
Card Management
List and delete stored card tokens for a user. This allows you to provide a "saved cards" experience in your checkout flow.
List Stored Cards
| Parameter | Description |
|---|---|
buyer_userid Required |
The internal ID of your customer. |
gateway_buyer_uuid Optional |
Specific UUID if known. |
{
"status": "success",
"data": [
{
"card_token": "CT_987654321",
"card_number": "411111XXXXXX1111",
"expiry": "12/26",
"card_type": "VISA"
}
]
}
Delete Card
Parameter in URL: id (The index or card token to remove)
Virtual Card Network (VCN)
Issue and manage secure virtual cards for your customers. These cards can be used for online payments worldwide.
Issue New VCN
{
"msisdn": "255700000000",
"email": "user@example.com",
"name": "John Doe"
}
Change VCN Status
| Field | Value |
|---|---|
status |
"BLOCK" or "UNBLOCK" |
Show Full Card Details
⚠️ Secure Endpoint: Only call when the user enters their PIN on your UI.
Get VCN Details & Balance
Mobile Wallet & Selcom Pesa
{
"action": "disbursement",
"amount": 5000,
"msisdn": "255700000000",
"channel": "CASHIN",
"reference": "PAYOUT_001"
}
{
"status": "success",
"transaction_id": "902",
"payment_status": "COMPLETED",
"financials": {
"system_profit": 55,
"provider_fee": 345,
"total_deductible": 5400
}
}
Bank Transfer (Qwiksend)
| Parameter | Type | Description |
|---|---|---|
action Required |
string | "disbursement" |
channel Required |
string | "BANK" for Qwiksend bank transfer |
amount Required |
integer | Amount in TZS |
msisdn Required |
string | Sender's phone number |
recipient_bank_code Required |
string | Bank code (e.g., CRDB). See Channels section. |
recipient_account Required |
string | Recipient's bank account number |
recipient_name Optional |
string | Recipient's full name |
remarks Optional |
string | Transaction memo or notes |
reference Required |
string | Your unique transaction reference |
{
"action": "disbursement",
"channel": "BANK",
"amount": 50000,
"msisdn": "255700000000",
"recipient_bank_code": "CRDB",
"recipient_account": "01J12345678900",
"recipient_name": "John Doe",
"reference": "SALARY_BATCH_01",
"remarks": "February Salary"
}
Name Lookup
Validate recipient details before sending funds. Supports wallet (mobile money), bank account, and Selcom Pesa lookups.
Wallet Lookup
{
"type": "wallet",
"channel": "vodacom",
"msisdn": "255754000000"
}
Bank Account Lookup
{
"type": "bank",
"bank_code": "CRDB",
"account_number": "01J12345678900"
}
Sample Response
{
"status": "success",
"name": "Jane Doe",
"original_data": { ... }
}
Transaction Query
Check the current status of a transaction using your internal reference. For pending transactions, the middleware will automatically attempt a live status check with the provider.
{
"reference": "ORDER_101"
}
{
"status": "SUCCESS",
"reference": "ORDER_101",
"amount": 1000,
"currency": "TZS",
"payment_status": "COMPLETED",
"created_at": "2024-01-15 10:30:00"
}
Account Summary
Retrieve a financial summary for your application including total volume, success counts, and overall success rate.
{} // No body required
{
"status": "SUCCESS",
"data": {
"total_volume": 4200000,
"total_count": 182,
"success_count": 175,
"failed_count": 5,
"pending_count": 2,
"success_rate": 96.15
}
}
Webhooks (Callbacks)
Payme Africa does not require pre-registration of webhooks. Instead, you must provide a callback_url in each /transact request. The gateway will send an asynchronous POST request to this URL when the transaction reaches a final state.
Status Descriptions
| Field | Value | Description |
|---|---|---|
result |
"SUCCESS" |
The final outcome of the transaction was successful. |
result |
"FAILED" |
The transaction failed at the provider or was cancelled. |
payment_status |
"PENDING" |
Awaiting customer action (PIN entry). |
payment_status |
"COMPLETED" |
Funds have been successfully transferred. |
payment_status |
"FAILED" |
The payment process stopped due to an error. |
Sample Webhook Payload
{
"transid": "7945454515",
"reference": "ORDER_101",
"result": "SUCCESS",
"payment_status": "COMPLETED",
"amount": "1000",
"msisdn": "255700000000"
}
Verifying Webhook Signatures
To ensure the webhook came from the middleware, you must
verify the X-Middleware-Signature header.
Algorithm:
Base64( HMAC_SHA256( Payload + X-Timestamp, Your_Shared_Secret ) )
$payload = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_TIMESTAMP'];
$signature = $_SERVER['HTTP_X_MIDDLEWARE_SIGNATURE'];
$expected = base64_encode(
hash_hmac('sha256', $payload . $timestamp, $secret, true)
);
if (hash_equals($signature, $expected)) {
// ✓ Verified — process the webhook safely
}
Testing Webhooks: Use the Webhook Testing tool in the Developer Portal to fire a
simulated test_ping event to your registered URL without needing a real transaction.
Transaction Result Codes
Common result codes returned in API responses and webhook payloads.
| Code | Description | Action Required |
|---|---|---|
000 |
Success | Transaction completed successfully. Deliver value. |
021 |
Pending | Transaction initiated. Wait for callback or poll /api/v1/query. |
009 |
Failed | Generic failure. Check account status or entered details. |
052 |
Insufficient Balance | Customer has insufficient funds in their wallet. |
056 |
User Cancelled | Customer cancelled the USSD push request. |
INS_FUNDS |
Insufficient App Balance | Your middleware application balance is too low for this disbursement (fees included). |
SERVICE_DISABLED |
Service Not Enabled | The requested service (collection/disbursement) is disabled for your application. |
OUT_OF_RANGE |
Amount Out of Range | The requested amount is outside the min/max allowed for this service tier. |
Supported Channels & Banks
Use these codes in the channel and recipient_bank_code
request fields.
Mobile Networks
| Channel Code | Network / Provider |
|---|---|
CASHIN |
Universal — Any carrier (auto-detected) |
vodacom |
M-Pesa (Vodacom) |
airtel |
Airtel Money |
tigo |
Tigo Pesa (MIC Tanzania) |
halotel |
HaloPesa |
zantel |
EzyPesa (Zantel) |
ttcl |
T-Pesa (TTCL) |
SELCOM_PESA |
Selcom Pesa |
Popular Banks (Qwiksend)
| Bank Code | Bank Name |
|---|---|
CRDB |
CRDB Bank |
NMB |
NMB Bank |
NBC |
NBC Bank |
EXIM |
Exim Bank |
STANBIC |
Stanbic Bank |
ABSA |
Absa Bank |
DTB |
Diamond Trust Bank |
KCB |
KCB Bank |