Developer - Api Documentation

Introduction

This section describes the Umva Pay payment gateway API.


Our API uses cURL requests, returns JSON responses, and supports test mode. Use sandbox URL for testing and live URL for production.

Authenticate requests with your API key. Test mode ensures no live data is affected.

Supported Currencies

Available currencies for transactions.


Name Symbol Code
United States Dollar $ USD
Rwandan Francs R₣ RWF
Euros Є EUR
Pound £ GBP
Ghanaian Cedi GH₵ GHS
Kenyan Shilling KSh KES
Malawian Kwacha K MWK
Nigerian Naira NGN
Sierra Leonean Leone Le SLL
Tanzanian Shilling Tsh TZS
Ugandan Shilling USh UGX
Central African CFA Franc BEAC FCFA XAF
CFA Franc CFA XOF
South African Rand R ZAR
Ethiopian Birr Br ETB
Egyptian pound EGP
Australian dollar A$ AUD
Indian Rupee INR
Congolese Franc FC CDF
BNB Smart Chain (BSC) USDT.BEP20 USDT.BEP20
USDT-TRON USDT.TRC20 USDT.TRC20
Zambian Kwacha ZK ZMW

Get API Key

Access your API credentials.


Login to Umva Pay merchant account. No account? Sign Up

Navigate to API Key in your dashboard. You will find Public and Secret keys. Generate new keys if needed, but never share them.

Initiate Payment

Start a payment process.


Live Endpoint: https://pay.umva.net/payment/initiate

Test Endpoint: https://pay.umva.net/sandbox/payment/initiate

Test Email: [email protected]

Test Code: 222666

Method: POST

Parameter Type Description
public_key string(50) Required Your Public API key
identifier string(20) Required Unique payment identifier
currency string(4) Required Currency code (e.g., USD)
amount decimal Required Payment amount
details string(100) Required Payment description
ipn_url string Required IPN callback URL
success_url string Required Success redirect URL
cancel_url string Required Cancel redirect URL
site_logo string Required Your logo URL
checkout_theme string Optional Theme: dark/light (default: light)
customer_name string(30) Required Customer name
customer_email string(30) Required Customer email
Example Response
{
    "success": "ok",
    "message": "Payment Initiated. Redirect to url.",
    "url": "http://example.com/initiate/payment/checkout?payment_id=eJSAASDxdrt4DASDASVNASJA7893232432cvmdsamnvASF"
}

{
    "error": "true",
    "message": "Invalid api key"
}

{
    "error": "true",
    "message": "Invalid currency"
}

{
    "error": "true",
    "message": "Amount must be greater than zero"
}

{
    "error": "true",
    "message": "Missing required parameter: identifier"
}

Instant Payment Notification (IPN)

Validate and process payment notifications.


Receive real-time payment updates at your specified IPN URL.

Endpoint: Your IPN URL

Method: POST

Parameter Type Description
status string Payment status (success/failed)
identifier string Unique payment identifier
signature string Security hash for verification
data array Transaction details (amount, currency, transaction_id, charges)
PHP IPN Validation Example
try {
    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
        throw new Exception('Invalid request method');
    }

    $status = $_POST['status'] ?? throw new Exception('Missing status parameter');
    $signature = $_POST['signature'] ?? throw new Exception('Missing signature parameter');
    $identifier = $_POST['identifier'] ?? throw new Exception('Missing identifier parameter');
    $data = $_POST['data'] ?? throw new Exception('Missing data parameter');

    if (!is_array($data)) {
        throw new Exception('Invalid data format');
    }

    // Verify signature
    $customKey = ($data['amount'] ?? '') . $identifier;
    $secret = 'YOUR_SECRET_KEY';
    $mySignature = strtoupper(hash_hmac('sha256', $customKey, $secret));

    if ($signature !== $mySignature) {
        throw new Exception('Invalid signature');
    }

    if ($identifier !== 'YOUR_GIVEN_IDENTIFIER') {
        throw new Exception('Invalid identifier');
    }

    if ($status !== 'success') {
        throw new Exception('Payment failed: ' . $status);
    }

    // Validate data contents
    if (empty($data['amount']) || empty($data['currency']) || empty($data['transaction_id'])) {
        throw new Exception('Incomplete transaction data');
    }

    // Process successful payment
    // Add your business logic here (e.g., update order status, send notifications)

    http_response_code(200);
    echo json_encode(['status' => 'success']);

} catch (Exception $e) {
    http_response_code(400);
    error_log('IPN Error: ' . $e->getMessage());
    echo json_encode([
        'error' => true,
        'message' => $e->getMessage()
    ]);
}

Plugins


Ready-made plugins for popular CMS.

WooCommerce Plugin

Prestashop Plugin

Whmcs Plugin

Code Examples


Implementation examples in multiple programming languages for initiating payments.

PHP
try {
    $params = [
        'identifier' => 'DFU80XZIKS',
        'currency' => 'USD',
        'amount' => 100.00,
        'details' => 'Purchase T-shirt',
        'ipn_url' => 'http://example.com/ipn',
        'cancel_url' => 'http://example.com/cancel',
        'success_url' => 'http://example.com/success',
        'public_key' => 'your_public_key',
        'site_logo' => 'http://example.com/logo.png',
        'customer_name' => 'John Doe',
        'customer_email' => '[email protected]'
    ];

    // Validate parameters
    foreach (['identifier', 'currency', 'amount', 'public_key', 'customer_email'] as $key) {
        if (empty($params[$key])) {
            throw new Exception("Missing required parameter: $key");
        }
    }

    $ch = curl_init('https://pay.umva.net/payment/initiate');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $params,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_TIMEOUT => 30
    ]);

    $response = curl_exec($ch);
    if (curl_errno($ch)) {
        throw new Exception('cURL error: ' . curl_error($ch));
    }
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($httpCode !== 200) {
        throw new Exception('HTTP error: ' . $httpCode);
    }

    $result = json_decode($response, true);
    if (!$result) {
        throw new Exception('Invalid JSON response');
    }

    if (isset($result['error']) && $result['error'] === 'true') {
        throw new Exception($result['message'] ?? 'Unknown API error');
    }

    if (empty($result['url'])) {
        throw new Exception('Missing redirect URL in response');
    }

    return $result['url'];
} catch (Exception $e) {
    error_log('Payment Initiation Error: ' . $e->getMessage());
    throw new Exception('Failed to initiate payment: ' . $e->getMessage());
}
Python
import requests
import json
from requests.exceptions import RequestException, HTTPError, Timeout

def initiate_payment():
    try:
        payload = {
            'identifier': 'DFU80XZIKS',
            'currency': 'USD',
            'amount': 100.00,
            'details': 'Purchase T-shirt',
            'ipn_url': 'http://example.com/ipn',
            'cancel_url': 'http://example.com/cancel',
            'success_url': 'http://example.com/success',
            'public_key': 'your_public_key',
            'site_logo': 'http://example.com/logo.png',
            'customer_name': 'John Doe',
            'customer_email': '[email protected]'
        }

        # Validate required fields
        required = ['identifier', 'currency', 'amount', 'public_key', 'customer_email']
        for field in required:
            if not payload.get(field):
                raise ValueError(f"Missing required field: {field}")

        response = requests.post(
            'https://pay.umva.net/payment/initiate',
            data=payload,
            verify=False,
            timeout=30
        )
        response.raise_for_status()

        result = response.json()
        if result.get('error') == 'true'):
            raise ValueError(result.get('message', 'Unknown API error'))

        if not result.get('url'):
            raise ValueError('Missing redirect URL in response')

        return result['url']

    except Timeout:
        print('Request timed out')
        raise
    except HTTPError as e:
        print(f'HTTP error: {e.response.status_code}')
        raise
    except RequestException as e:
        print(f'Network error: {str(e)}')
        raise
    except json.JSONDecodeError:
        print('Invalid JSON response')
        raise
    except ValueError as e:
        print(f'Validation error: {str(e)}')
        raise
    except Exception as e:
        print(f'Unexpected error: {str(e)}')
        raise
JavaScript/Node.js
const axios = require('axios');

async function initiatePayment() {
    try {
        const payload = {
            identifier: 'DFU80XZIKS',
            currency: 'USD',
            amount: 100.00,
            details: 'Purchase T-shirt',
            ipn_url: 'http://example.com/ipn',
            cancel_url: 'http://example.com/cancel',
            success_url: 'http://example.com/success',
            public_key: 'your_public_key',
            site_logo: 'http://example.com/logo.png',
            customer_name: 'John Doe',
            customer_email: '[email protected]'
        };

        // Validate required fields
        const required = ['identifier', 'currency', 'amount', 'public_key', 'customer_email'];
        for (const field of required) {
            if (!payload[field]) {
                throw new Error(`Missing required field: ${field}`);
            }
        }

        const response = await axios.post('https://pay.umva.net/payment/initiate', payload, {
            httpsAgent: new (require('https').Agent)({ rejectUnauthorized: false }),
            timeout: 30000
        });

        if (response.data.error === 'true') {
            throw new Error(response.data.message || 'Unknown API error');
        }

        if (!response.data.url) {
            throw new Error('Missing redirect URL in response');
        }

        return response.data.url;
    } catch (error) {
        console.error('Payment Error:', error.message);
        if (error.response) {
            console.error('API Response:', error.response.data);
        } else if (error.code === 'ECONNABORTED') {
            console.error('Request timed out');
        }
        throw error;
    }
}
Ruby
require 'httparty'
require 'json'

def initiate_payment
  begin
    payload = {
      identifier: 'DFU80XZIKS',
      currency: 'USD',
      amount: 100.00,
      details: 'Purchase T-shirt',
      ipn_url: 'http://example.com/ipn',
      cancel_url: 'http://example.com/cancel',
      success_url: 'http://example.com/success',
      public_key: 'your_public_key',
      site_logo: 'http://example.com/logo.png',
      customer_name: 'John Doe',
      customer_email: '[email protected]'
    }

    # Validate required fields
    %w[identifier currency amount public_key customer_email].each do |field|
      raise ArgumentError, "Missing required field: #{field}" if payload[field.to_sym].nil?
    end

    response = HTTParty.post(
      'https://pay.umva.net/payment/initiate',
      body: payload,
      verify: false,
      timeout: 30
    )

    result = JSON.parse(response.body)
    if result['error'] == 'true'
      raise StandardError, result['message'] || 'Unknown API error'
    end

    unless result['url']
      raise StandardError, 'Missing redirect URL in response'
    end

    result['url']
  rescue HTTParty::Error => e
    puts "Network error: #{e.message}"
    raise
  rescue JSON::ParserError
    puts 'Invalid JSON response'
    raise
  rescue Timeout::Error
    puts 'Request timed out'
    raise
  rescue StandardError => e
    puts "Error: #{e.message}"
    raise
  end
end
Java
import java.net.http.*;
import java.net.URI;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;

public class PaymentClient {
    public String initiatePayment() throws Exception {
        try {
            Map payload = Map.of(
                "identifier", "DFU80XZIKS",
                "currency", "USD",
                "amount", 100.00,
                "details", "Purchase T-shirt",
                "ipn_url", "http://example.com/ipn",
                "cancel_url", "http://example.com/cancel",
                "success_url", "http://example.com/success",
                "public_key", "your_public_key",
                "site_logo", "http://example.com/logo.png",
                "customer_name", "John Doe",
                "customer_email", "[email protected]"
            );

            // Validate required fields
            String[] required = {"identifier", "currency", "amount", "public_key", "customer_email"};
            for (String field : required) {
                if (!payload.containsKey(field) || payload.get(field) == null) {
                    throw new IllegalArgumentException("Missing required field: " + field);
                }
            }

            HttpClient client = HttpClient.newBuilder().build();
            String json = new ObjectMapper().writeValueAsString(payload);
            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://pay.umva.net/payment/initiate"))
                .header("Content-Type", "application/json")
                .timeout(Duration.ofSeconds(30))
                .POST(HttpRequest.BodyPublishers.ofString(json))
                .build();

            HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
            if (response.statusCode() != 200) {
                throw new Exception("HTTP error: " + response.statusCode());
            }

            Map result = new ObjectMapper().readValue(response.body(), Map.class);
            if ("true".equals(result.get("error"))) {
                throw new Exception((String) result.getOrDefault("message", "Unknown API error"));
            }

            String url = (String) result.get("url");
            if (url == null) {
                throw new Exception("Missing redirect URL in response");
            }

            return url;
        } catch (Exception e) {
            System.err.println("Payment Error: " + e.getMessage());
            throw e;
        }
    }
}
C#
using System;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;

public class PaymentClient
{
    public async Task InitiatePayment()
    {
        try
        {
            using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
            var payload = new
            {
                identifier = "DFU80XZIKS",
                currency = "USD",
                amount = 100.00,
                details = "Purchase T-shirt",
                ipn_url = "http://example.com/ipn",
                cancel_url = "http://example.com/cancel",
                success_url = "http://example.com/success",
                public_key = "your_public_key",
                site_logo = "http://example.com/logo.png",
                customer_name = "John Doe",
                customer_email = "[email protected]"
            };

            // Validate required fields
            if (string.IsNullOrEmpty(payload.identifier) || string.IsNullOrEmpty(payload.currency) ||
                payload.amount <= 0 || string.IsNullOrEmpty(payload.public_key) ||
                string.IsNullOrEmpty(payload.customer_email))
            {
                throw new ArgumentException("Missing required fields");
            }

            var content = new StringContent(
                JsonSerializer.Serialize(payload),
                System.Text.Encoding.UTF8,
                "application/json"
            );

            var response = await client.PostAsync("https://pay.umva.net/payment/initiate", content);
            response.EnsureSuccessStatusCode();

            var json = await response.Content.ReadAsStringAsync();
            using var doc = JsonDocument.Parse(json);
            var result = doc.RootElement;

            if (result.TryGetProperty("error", out var error) && error.GetString() == "true")
            {
                var message = result.TryGetProperty("message", out var msg) 
                    ? msg.GetString() : "Unknown API error";
                throw new Exception(message);
            }

            if (!result.TryGetProperty("url", out var urlProp))
            {
                throw new Exception("Missing redirect URL in response");
            }

            return urlProp.GetString();
        }
        catch (HttpRequestException e)
        {
            Console.WriteLine($"Network error: {e.Message}");
            throw;
        }
        catch (TaskCanceledException)
        {
            Console.WriteLine("Request timed out");
            throw;
        }
        catch (JsonException)
        {
            Console.WriteLine("Invalid JSON response");
            throw;
        }
        catch (Exception e)
        {
            Console.WriteLine($"Error: {e.Message}");
            throw;
        }
    }
}
Go
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
    "time"
)

func initiatePayment() (string, error) {
    payload := map[string]interface{}{
        "identifier":     "DFU80XZIKS",
        "currency":       "USD",
        "amount":         100.00,
        "details":        "Purchase T-shirt",
        "ipn_url":        "http://example.com/ipn",
        "cancel_url":     "http://example.com/cancel",
        "success_url":    "http://example.com/success",
        "public_key":     "your_public_key",
        "site_logo":      "http://example.com/logo.png",
        "customer_name":  "John Doe",
        "customer_email": "[email protected]",
    }

    // Validate required fields
    required := []string{"identifier", "currency", "amount", "public_key", "customer_email"}
    for _, field := range required {
        if _, ok := payload[field]; !ok || payload[field] == nil {
            return "", fmt.Errorf("missing required field: %s", field)
        }
    }

    jsonData, err := json.Marshal(payload)
    if err != nil {
        return "", fmt.Errorf("json marshal error: %v", err)
    }

    client := &http.Client{Timeout: 30 * time.Second}
    resp, err := client.Post("https://pay.umva.net/payment/initiate", "application/json", bytes.NewBuffer(jsonData))
    if err != nil {
        return "", fmt.Errorf("http error: %v", err)
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        return "", fmt.Errorf("http error: status code %d", resp.StatusCode)
    }

    var result map[string]interface{}
    if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
        return "", fmt.Errorf("json decode error: %v", err)
    }

    if errorMsg, ok := result["error"]; ok && errorMsg == "true" {
        msg, _ := result["message"].(string)
        return "", fmt.Errorf("api error: %s", msg)
    }

    url, ok := result["url"].(string)
    if !ok || url == "" {
        return "", fmt.Errorf("missing or invalid url in response")
    }

    return url, nil
}
TypeScript
import axios, { AxiosError } from 'axios';

interface PaymentResponse {
    error?: string;
    message?: string;
    url?: string;
}

async function initiatePayment(): Promise {
    try {
        const payload = {
            identifier: 'DFU80XZIKS',
            currency: 'USD',
            amount: 100.00,
            details: 'Purchase T-shirt',
            ipn_url: 'http://example.com/ipn',
            cancel_url: 'http://example.com/cancel',
            success_url: 'http://example.com/success',
            public_key: 'your_public_key',
            site_logo: 'http://example.com/logo.png',
            customer_name: 'John Doe',
            customer_email: '[email protected]'
        };

        // Validate required fields
        const requiredFields = ['identifier', 'currency', 'amount', 'public_key', 'customer_email'];
        for (const field of requiredFields) {
            if (!payload[field]) {
                throw new Error(`Missing required field: ${field}`);
            }
        }

        const response = await axios.post('https://pay.umva.net/payment/initiate', payload, {
            httpsAgent: new (require('https').Agent)({ rejectUnauthorized: false }),
            timeout: 30000
        });

        if (response.data.error === 'true') {
            throw new Error(response.data.message || 'Unknown API error');
        }

        if (!response.data.url) {
            throw new Error('Missing redirect URL in response');
        }

        return response.data.url;
    } catch (error) {
        const err = error as AxiosError;
        console.error('Payment Error:', err.message);
        if (err.response) {
            console.error('API Response:', err.response.data);
        } else if (err.code === 'ECONNABORTED') {
            console.error('Request timed out');
        }
        throw error;
    }
}
Swift
import Foundation

struct PaymentResponse: Codable {
    let error: String?
    let message: String?
    let url: String?
}

func initiatePayment(completion: @escaping (Result) -> Void) {
    let payload: [String: Any] = [
        "identifier": "DFU80XZIKS",
        "currency": "USD",
        "amount": 100.00,
        "details": "Purchase T-shirt",
        "ipn_url": "http://example.com/ipn",
        "cancel_url": "http://example.com/cancel",
        "success_url": "http://example.com/success",
        "public_key": "your_public_key",
        "site_logo": "http://example.com/logo.png",
        "customer_name": "John Doe",
        "customer_email": "[email protected]"
    ]

    // Validate required fields
    let required = ["identifier", "currency", "amount", "public_key", "customer_email"]
    for field in required {
        guard payload[field] != nil else {
            completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Missing required field: \(field)"])))
            return
        }
    }

    guard let url = URL(string: "https://pay.umva.net/payment/initiate") else {
        completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"])))
        return
    }

    var request = URLRequest(url: url, timeoutInterval: 30)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")

    do {
        request.httpBody = try JSONSerialization.data(withJSONObject: payload)
    } catch {
        completion(.failure(error))
        return
    }

    URLSession.shared.dataTask(with: request) { data, response, error in
        if let error = error {
            print("Network error: \(error.localizedDescription)")
            completion(.failure(error))
            return
        }

        guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
            completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid HTTP response"])))
            return
        }

        guard let data = data else {
            completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "No data received"])))
            return
        }

        do {
            let result = try JSONDecoder().decode(PaymentResponse.self, from: data)
            if let errorMsg = result.error, errorMsg == "true" {
                let message = result.message ?? "Unknown API error"
                completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: message])))
                return
            }

            guard let url = result.url else {
                completion(.failure(NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Missing redirect URL in response"])))
                return
            }

            completion(.success(url))
        } catch {
            print("JSON decode error: \(error.localizedDescription)")
            completion(.failure(error))
        }
    }.resume()
}
cURL
curl -X POST 'https://pay.umva.net/payment/initiate' \
  --data-urlencode 'identifier=DFU80XZIKS' \
  --data-urlencode 'currency=USD' \
  --data-urlencode 'amount=100.00' \
  --data-urlencode 'details=Purchase T-shirt' \
  --data-urlencode 'ipn_url=http://example.com/ipn' \
  --data-urlencode 'cancel_url=http://example.com/cancel' \
  --data-urlencode 'success_url=http://example.com/success' \
  --data-urlencode 'public_key=your_public_key' \
  --data-urlencode 'site_logo=http://example.com/logo.png' \
  --data-urlencode 'customer_name=John Doe' \
  --data-urlencode '[email protected]' \
  --insecure \
  --connect-timeout 30 \
  --fail

We may use cookies or any other tracking technologies when you visit our website, including any other media form, mobile website, or mobile application related or connected to help customize the Site and improve your experience. learn more

Allow