pluspesa.com

PlusPesa API Documentation

Welcome to the PlusPesa API documentation. This guide will help you integrate our payment gateway into your application. PlusPesa provides a secure, reliable, and easy-to-use payment solution for businesses across Africa.

Our API follows REST principles and uses JSON for request and response bodies. All requests must be made over HTTPS.

Base URL: https://api.pluspesa.com/v2/

Authorization

PlusPesa uses API keys to authenticate requests. You can obtain your API keys from your PlusPesa Dashboard. Your API keys carry many privileges, so be sure to keep them secure. Do not share your secret API keys in publicly accessible areas.

Authentication to the API is performed via HTTP Basic Auth. Provide your API key as the basic auth username value. You do not need to provide a password.

POST /auth/token
Request Example
// Using cURL
curl -X POST https://api.pluspesa.com/v2/auth/token \
  -u "your_api_key:" \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "client_credentials"
}'

// Using Node.js
const axios = require('axios');

const authResponse = await axios.post(
  'https://api.pluspesa.com/v2/auth/token',
  { grant_type: 'client_credentials' },
  {
    auth: {
      username: 'your_api_key',
      password: ''
    }
  }
);

const accessToken = authResponse.data.access_token;
Successful Response:
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600
}

Transaction Request

To initiate a payment transaction, send a POST request to the transaction endpoint with the required parameters. The customer will be redirected to the PlusPesa payment page to complete the transaction.

POST /transactions
Parameter Type Required Description
amount number Yes Transaction amount in the smallest currency unit (e.g., cents)
currency string Yes Three-letter ISO currency code (e.g., "TZS", "KES", "UGX")
reference string Yes Your unique transaction reference
customer_email string Yes Customer's email address
customer_phone string Yes Customer's phone number in international format
callback_url string Yes URL where we'll send transaction status updates
return_url string No URL to redirect customer after payment completion
description string No Description of the transaction item
Node.js Example
const axios = require('axios');
const FormData = require('form-data');

const createTransaction = async () => {
  const formData = new FormData();
  formData.append('amount', '50000'); // 50,000 TZS
  formData.append('currency', 'TZS');
  formData.append('reference', 'ORDER-123456');
  formData.append('customer_email', 'customer@example.com');
  formData.append('customer_phone', '+255712345678');
  formData.append('callback_url', 'https://yourdomain.com/callback');
  formData.append('return_url', 'https://yourdomain.com/success');
  formData.append('description', 'Premium Plan Subscription');
  
  const response = await axios.post(
    'https://api.pluspesa.com/v2/transactions',
    formData,
    {
      headers: {
        ...formData.getHeaders(),
        'Authorization': `Bearer ${accessToken}`
      }
    }
  );
  
  return response.data;
};

// Usage
createTransaction()
  .then(data => console.log('Transaction created:', data))
  .catch(error => console.error('Error:', error));

Callback

PlusPesa will send a POST request to your callback URL with the transaction status whenever there's an update. Your server must respond with a 200 OK status to acknowledge receipt.

Important: Always verify the transaction status by making a request to our API. Do not rely solely on the callback data as the source of truth.
Callback Handler (Node.js)
const express = require('express');
const router = express.Router();

// Verify the signature to ensure the request is from PlusPesa
const verifySignature = (req) => {
  const signature = req.headers['x-pluspesa-signature'];
  const payload = JSON.stringify(req.body);
  
  // Implement your signature verification logic here
  // Compare with HMAC-SHA256 hash of payload using your webhook secret
  
  return true; // Replace with actual verification
};

router.post('/callback', (req, res) => {
  // Verify the request signature
  if (!verifySignature(req)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  
  const { transaction_id, reference, status, amount, currency } = req.body;
  
  // Update your database with the transaction status
  console.log(`Transaction ${reference} status: ${status}`);
  
  // Process based on status
  if (status === 'completed') {
    // Fulfill the order/service
  } else if (status === 'failed') {
    // Handle failed transaction
  }
  
  // Always respond with 200 OK
  res.status(200).json({ received: true });
});

module.exports = router;

Check Order Status

You can check the status of a transaction at any time by making a GET request to the transaction status endpoint. This is useful for verifying transactions when callbacks might have been missed.

GET /transactions/{reference}
Python Example
import requests
import json

def check_transaction_status(reference, access_token):
    url = f"https://api.pluspesa.com/v2/transactions/{reference}"
    headers = {
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json"
    }
    
    response = requests.get(url, headers=headers)
    
    if response.status_code == 200:
        data = response.json()
        print(f"Status: {data['status']}")
        print(f"Amount: {data['amount']} {data['currency']}")
        return data
    else:
        print(f"Error: {response.status_code}")
        return None

# Usage
status = check_transaction_status("ORDER-123456", "your_access_token")

Create Sub Wallets

Sub wallets allow you to create separate balances for different departments, projects, or users within your organization. Each sub wallet has its own balance and transaction history while being managed under your main account.

POST /wallets/sub
PHP Example
<?php
// Create a sub wallet for a department
$url = "https://api.pluspesa.com/v2/wallets/sub";
$access_token = "your_access_token";

$data = [
    "name" => "Marketing Department",
    "currency" => "TZS",
    "initial_balance" => 1000000, // 1,000,000 TZS
    "description" => "Budget for Q3 marketing campaigns",
    "permissions" => [
        "send",
        "receive",
        "withdraw"
    ]
];

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer $access_token",
    "Content-Type: application/json"
]);

$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($http_code == 201) {
    $wallet = json_decode($response, true);
    echo "Sub wallet created successfully!\n";
    echo "Wallet ID: " . $wallet['id'] . "\n";
    echo "Balance: " . $wallet['balance'] . " " . $wallet['currency'];
} else {
    echo "Error creating sub wallet: " . $response;
}
?>

Disbursement

The disbursement API allows you to send money directly to mobile money wallets, bank accounts, or other payment methods supported by PlusPesa. This is ideal for payroll, vendor payments, refunds, and commissions.

POST /disbursements
Java Example
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import org.json.JSONObject;

public class PlusPesaDisbursement {
    public static void main(String[] args) throws Exception {
        String accessToken = "your_access_token";
        String url = "https://api.pluspesa.com/v2/disbursements";
        
        JSONObject payload = new JSONObject();
        payload.put("amount", 75000); // 75,000 TZS
        payload.put("currency", "TZS");
        payload.put("recipient_phone", "+255712345678");
        payload.put("recipient_name", "John Doe");
        payload.put("reference", "PAYROLL-OCT-001");
        payload.put("description", "October salary payment");
        payload.put("payment_method", "momo"); // momo, bank, card
        
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(url))
            .header("Authorization", "Bearer " + accessToken)
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(payload.toString()))
            .build();
        
        HttpClient client = HttpClient.newHttpClient();
        HttpResponse<String> response = client.send(request, 
            HttpResponse.BodyHandlers.ofString());
        
        if (response.statusCode() == 201) {
            System.out.println("Disbursement successful!");
            System.out.println(response.body());
        } else {
            System.out.println("Disbursement failed with status: " + response.statusCode());
            System.out.println(response.body());
        }
    }
}
Need Help? Visit our Support Center or contact us at support@pluspesa.com