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 | E£ | 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 |
{
"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) |
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()
]);
}
Code Examples
Implementation examples in multiple programming languages for initiating payments.
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());
}
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
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;
}
}
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
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;
}
}
}
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;
}
}
}
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
}
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;
}
}
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 -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