Token & API Documentation

Integrate PAYHIIVE using your token for checkout, webhooks, and payments. Get your token from Dashboard → Tokens.

Getting Started

Welcome to the PAYHIIVE API documentation. This guide will help you integrate PAYHIIVE payment gateway into your applications.

Prerequisites

  • An active PAYHIIVE account
  • A token from your dashboard (Dashboard → Tokens)
  • Basic knowledge of REST APIs and HTTP requests

Step 1: Get Your Token

  1. Log in to your PAYHIIVE dashboard
  2. Go to Tokens (in the sidebar)
  3. Complete your profile (required to generate a token)
  4. Click "Generate Live Token" or use Sandbox for testing
  5. Choose your environment:
    • Sandbox: For testing (no real money)
    • Live: For production (requires KYC approval)
  6. Copy your token (it is shown once; store it securely)

Important: Your token is only shown once when generated. Copy and store it securely. If you lose it, generate a new token from Dashboard → Tokens.

Note: Use a Sandbox token for testing and a Live token for production. Never expose your token in client-side code (browser, mobile apps). Always call the API from your backend server.

Step 2: Test Your Connection

Before integrating, test your token using the test feature on the Tokens page or by making a test API call.

SDK & Plugins

Integrate PAYHIIVE seamlessly with your application using our official SDKs and plugins. These tools are designed to make integration easier and faster.

API Libraries

We provide official libraries for Node.js, Python, and PHP. Install one of them, then run the command below in your terminal.

Click "Copy" next to the command, paste in your terminal, and press Enter. Click "View Docs" to see full documentation.

Node.js Library

Official Node.js library for the PAYHIIVE API.

npm install payhiive-node

Python Library

Official Python library for the PAYHIIVE API.

pip install payhiive-python

PHP Library

Official PHP library for the PAYHIIVE API.

composer require payhiive/payhiive-php

Available Plugins

WordPress Plugin

Accept mobile money payments on your WordPress site with our official plugin.

Installation Guides

WordPress Plugin Installation

  1. Download the plugin zip file from above
  2. Go to WordPress admin panel → Plugins → Add New → Upload Plugin
  3. Upload the downloaded zip file and click "Install Now"
  4. After installation, click "Activate Plugin"
  5. Go to PAYHIIVE in the WordPress menu and enter your token (from Dashboard → Tokens)
  6. Configure your payment settings and start accepting payments!

Authentication (Using Your Token)

All API requests require your token. Get it from Dashboard → Tokens. Your token starts with sk_ — it is the only key you need.

Headers

Header Description Required
Authorization Bearer sk_your_token — your token from Dashboard → Tokens. Required
Content-Type Should be application/json Required

Example Request

Use your token in the Authorization header when making any API call:

curl -X POST https://payhiive.com/api/v1/payments \ -H "Authorization: Bearer sk_your_token" \ -H "Content-Type: application/json" \ -d '{ "amount": 10000, "currency": "UGX", "phone_number": "256700000000", "provider": "MTN_MOMO_UGA", "description": "Payment for order #123" }'

Security: Never expose your token in client-side code. Keep it only on your server.

Fees & Pricing

PAYHIIVE charges platform fees on transactions. Fees are added on top of the amount you want to collect, so you receive the exact amount you requested.

API Transaction Fees

For transactions made through the API:

Fee Percentage
2.50%
Fixed Fee
0 UGX

Payment Link Transaction Fees

For transactions made through payment links:

Fee Percentage
4.00%
Fixed Fee
0 UGX

API Fee Calculation Example (Fees On Top)

If you want to collect 10,000 UGX via API:

  • Amount You Want to Collect: 10,000 UGX
  • Platform Fee (2.50% + 0): 250 UGX
  • Total Amount Customer Pays: 10,250 UGX
  • Amount Credited to Your Account: 10,000 UGX (exact amount you requested)

Payment Link Fee Calculation Example (Fees On Top)

If you want to collect 10,000 UGX via Payment Link:

  • Amount You Want to Collect: 10,000 UGX
  • Platform Fee (4.00% + 0): 400 UGX
  • Total Amount Customer Pays: 10,400 UGX
  • Amount Credited to Your Account: 10,000 UGX (exact amount you requested)

Payout/Withdrawal Fees

For withdrawals/payouts made through the API:

Fee Percentage
0.00%
Fixed Fee
0 UGX

Payout Fee Calculation Example

If you withdraw 10,000 UGX:

  • Withdrawal Amount: 10,000 UGX
  • Payout Fee (0.00% + 0): 0 UGX
  • Amount Sent to Recipient: 10,000 UGX

Note: Fees are added on top of the transaction amount. If you want to collect 10,000 UGX, the customer will pay 10,000 UGX plus the platform fee, and you will receive the full 10,000 UGX in your account.

Base URL

The base URL for all API requests:

https://payhiive.com/api/v1

Important: Always use HTTPS in production. Replace 127.0.0.1:8001 with your actual domain when going live.

API Endpoints

Payments

Create Payment

POST /payments

Create a new payment transaction.

Request Body

Parameter Type Description Required
amount integer Amount in UGX (e.g., 10000 = 10,000 UGX) Required
currency string Currency code (UGX) Required
phone_number string Customer mobile money phone number (e.g., 256700000000) Required
provider string Mobile money provider: MTN_MOMO_UGA or AIRTEL_OAPI_UGA Required
description string Payment description Optional
metadata object Additional metadata (key-value pairs) Optional

Example Request

POST https://payhiive.com/api/v1/payments Headers: Authorization: Bearer sk_your_token Content-Type: application/json Body: { "amount": 10000, "currency": "UGX", "phone_number": "256700000000", "provider": "MTN_MOMO_UGA", "description": "Payment for order #123", "metadata": { "order_id": "123", "product_id": "456" } }

Example Response (Success)

{ "success": true, "data": { "id": 123, "transaction_id": "TXN-ABC123XYZ", "deposit_id": "DEP-123456789", "amount": 10000, "currency": "UGX", "status": "pending", "provider": "payment_provider", "message": "Payment request sent successfully", "created_at": "2025-12-10T12:00:00Z" } }

Example Response (Error)

{ "success": false, "message": "Provider MTN_MOMO_UGA is not enabled. Please contact support to enable this provider.", "error_code": "PROVIDER_NOT_ENABLED" }

Note: The transaction status will be pending initially. It will be updated to completed or failed via webhook or when you check the status. The net_amount and fee are calculated and will be reflected in your account balance once the transaction is completed.

Transaction Status Values

Status Description
pending Payment request sent, waiting for customer to approve
processing Customer has approved, payment is being processed
completed Payment successfully completed and funds credited
failed Payment failed (customer declined, insufficient funds, etc.)
cancelled Payment was cancelled

Get Payment Status

GET /payments/{transaction_id}

Retrieve the current status and details of a specific payment transaction.

Response Example

{ "success": true, "data": { "id": 123, "transaction_id": "TXN-ABC123XYZ", "reference": "b6a677d8-8a3d-4d2d-9de5-d439510d7c62", "amount": 10000, "currency": "UGX", "status": "completed", "redirect_url": "https://your-website.com/success", "created_at": "2025-12-10T12:00:00Z", "updated_at": "2025-12-10T12:05:00Z" } }

Getting Transaction Reference

The transaction reference is a unique identifier (UUID format) that is returned in the response when you create a payment or retrieve payment status. This reference can be used for tracking, reconciliation, and webhook verification.

To get the transaction reference:

  1. From Payment Response: When you create a payment using POST /payments, the reference is included in the response.
  2. From Status Check: When you retrieve payment status using GET /payments/{transaction_id}, the reference field is included in the response data.
  3. From Dashboard: You can also view the transaction reference in your merchant dashboard at https://payhiive.com/customer/dashboard/recent-transactions.

Note: The transaction reference is different from the transaction_id. The reference is typically a UUID format (e.g., b6a677d8-8a3d-4d2d-9de5-d439510d7c62) and is used for provider-specific tracking, while the transaction_id is the internal transaction identifier used when calling the API with your token.

Step-by-Step: Integrating Transaction Reference in Your System

This guide will walk you through integrating transaction reference tracking into your application system.

Step 1: Set Up Your Token
  1. Log in to your merchant dashboard at https://payhiive.com/customer/login
  2. Navigate to Dashboard → Tokens
  3. Generate a new token (Dashboard → Tokens)
  4. Store your token and public identifier securely in your application's environment variables (e.g. in .env):
    PAYHIIVE_TOKEN=sk_your_token API_BASE_URL=https://payhiive.com/api/v1
Step 2: Create a Payment Request

When creating a payment, make a POST request to the payments endpoint:

POST https://payhiive.com/api/v1/payments Headers: Authorization: Bearer sk_your_token Content-Type: application/json Body: { "amount": 10000, "currency": "UGX", "phone_number": "256700000000", "provider": "MTN_MOMO_UGA", "description": "Payment for order #123" }

The response will include a transaction_id:

{ "success": true, "data": { "id": 123, "transaction_id": "TXN-ABC123XYZ", "amount": 10000, "currency": "UGX", "status": "pending", "created_at": "2025-12-10T12:00:00Z" } }
Step 3: Retrieve the Transaction Reference

After creating a payment, use the transaction_id to retrieve the full transaction details, including the reference:

GET https://payhiive.com/api/v1/payments/{transaction_id} Headers: Authorization: Bearer sk_your_token Content-Type: application/json

The response will include the reference field:

{ "success": true, "data": { "id": 123, "transaction_id": "TXN-ABC123XYZ", "reference": "b6a677d8-8a3d-4d2d-9de5-d439510d7c62", "amount": 10000, "currency": "UGX", "status": "completed", "created_at": "2025-12-10T12:00:00Z", "updated_at": "2025-12-10T12:05:00Z" } }
Step 4: Store the Reference in Your Database

Save both the transaction_id and reference in your database for future reference and reconciliation:

// Example: Store transaction in your database INSERT INTO orders ( order_id, payment_transaction_id, payment_reference, amount, status, created_at ) VALUES ( 'ORDER-12345', 'TXN-ABC123XYZ', 'b6a677d8-8a3d-4d2d-9de5-d439510d7c62', 10000, 'pending', NOW() );
Step 5: Check Payment Status Using Reference

You can verify payment status by checking the transaction using either the transaction_id or by querying your database using the stored reference:

// Check status via API GET https://payhiive.com/api/v1/payments/TXN-ABC123XYZ // Or query your database SELECT * FROM orders WHERE payment_reference = 'b6a677d8-8a3d-4d2d-9de5-d439510d7c62';
Step 6: Complete Code Example (PHP)
<?php // Configuration $apiBaseUrl = 'https://payhiive.com/api/v1'; $token = 'sk_your_token'; // Step 1: Create Payment function createPayment($amount, $phoneNumber, $provider, $description) { global $apiBaseUrl, $token; $data = [ 'amount' => $amount, 'currency' => 'UGX', 'phone_number' => $phoneNumber, 'provider' => $provider, 'description' => $description ]; $ch = curl_init($apiBaseUrl . '/payments'); 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 ' . $token, 'Content-Type: application/json' ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); return json_decode($response, true); } // Step 2: Get Transaction Reference function getTransactionReference($transactionId) { global $apiBaseUrl, $token; $ch = curl_init($apiBaseUrl . '/payments/' . $transactionId); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $token, 'Content-Type: application/json' ]); $response = curl_exec($ch); curl_close($ch); $data = json_decode($response, true); if ($data['success'] && isset($data['data']['reference'])) { return $data['data']['reference']; } return null; } // Usage Example $payment = createPayment(10000, '256700000000', 'MTN_MOMO_UGA', 'Order #12345'); if ($payment['success']) { $transactionId = $payment['data']['transaction_id']; // Get the transaction reference $reference = getTransactionReference($transactionId); // Store in your database // INSERT INTO orders (order_id, transaction_id, reference, status) // VALUES ('ORDER-12345', $transactionId, $reference, 'pending'); echo "Transaction ID: " . $transactionId . "\n"; echo "Reference: " . $reference . "\n"; } ?>
Step 7: Complete Code Example (Node.js/JavaScript)
// Configuration const API_BASE_URL = 'https://payhiive.com/api/v1'; const TOKEN = 'sk_your_token'; // Step 1: Create Payment async function createPayment(amount, phoneNumber, provider, description) { const response = await fetch(`${API_BASE_URL}/payments`, { method: 'POST', headers: { 'Authorization': `Bearer ${TOKEN}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ amount: amount, currency: 'UGX', phone_number: phoneNumber, provider: provider, description: description }) }); return await response.json(); } // Step 2: Get Transaction Reference async function getTransactionReference(transactionId) { const response = await fetch(`${API_BASE_URL}/payments/${transactionId}`, { method: 'GET', headers: { 'Authorization': `Bearer ${TOKEN}`, 'Content-Type': 'application/json' } }); const data = await response.json(); if (data.success && data.data.reference) { return data.data.reference; } return null; } // Usage Example async function processPayment() { const payment = await createPayment( 10000, '256700000000', 'MTN_MOMO_UGA', 'Order #12345' ); if (payment.success) { const transactionId = payment.data.transaction_id; const reference = await getTransactionReference(transactionId); // Store in your database // await db.query( // 'INSERT INTO orders (order_id, transaction_id, reference, status) VALUES (?, ?, ?, ?)', // ['ORDER-12345', transactionId, reference, 'pending'] // ); console.log('Transaction ID:', transactionId); console.log('Reference:', reference); } } processPayment();
Step 8: Verify Reference in Dashboard

You can also verify the transaction reference by viewing it in your merchant dashboard:

  1. Log in to your dashboard at https://payhiive.com/customer/login
  2. Navigate to Dashboard → Recent Transactions
  3. Find your transaction and check the Reference column
  4. The reference will be displayed in UUID format (e.g., b6a677d8-8a3d-4d2d-9de5-d439510d7c62)

Best Practices:

  • Always store both transaction_id and reference in your database
  • Use the reference for reconciliation with payment provider records
  • Use the transaction_id for status checks and when calling the API (with your token)
  • Display the reference to customers for transaction tracking and support inquiries
  • Keep your token secure and never expose it in client-side code

List Payments

GET /payments

Retrieve a list of all your payments. Supports pagination and filtering.

Refunds

Create Refund

POST /refunds

Create a refund for a payment.

Request Body

Parameter Type Description Required
payment_id string ID of the payment to refund Required
amount integer Refund amount in cents (optional, defaults to full amount) Optional
reason string Reason for refund Optional

Checkout Pages (Using Your Token)

PAYHIIVE provides hosted checkout pages that you can redirect your customers to for secure payment processing. Authenticate with your token (Dashboard → Tokens) when creating payment intents. This is the easiest way to accept payments without handling sensitive payment data yourself.

Creating a Payment Intent

To create a payment intent, make a POST request to the payments endpoint with the payment details.

Create Payment Intent

POST /payments

Create a new payment intent and get a secure checkout URL to redirect your customer to.

Note: Currency is fixed to UGX for payment intents. The amount should be provided as a decimal number (e.g., 50000.00 for 50,000 UGX).

Request Body

Parameter Type Description Required
amount decimal Payment amount (e.g., 50000.00 for 50,000 UGX) Required
description string Payment description (max 500 characters) Optional
callback_url string Webhook URL to receive payment status updates Optional

Example Request

POST https://payhiive.com/api/v1/payments Headers: Authorization: Bearer sk_your_token Content-Type: application/json Body: { "amount": 50000.00, "description": "Payment for Order #12345", "callback_url": "https://yoursite.com/webhooks/payment-status" }

Example Response

{ "reference": "PHV_MPDJWT5TLC", "checkout_url": "https://payhiive.com/checkout/PHV_MPDJWT5TLC" }

Redirecting to Checkout

After creating a payment intent, redirect your customer to the checkout_url provided in the response.

Important: Always use the checkout_url from the response. Never construct the URL manually or allow the frontend to modify the amount or payment details.

JavaScript Example

// Create payment intent const response = await fetch('https://payhiive.com/api/v1/payments', { method: 'POST', headers: { 'Authorization': 'Bearer sk_your_token', 'Content-Type': 'application/json' }, body: JSON.stringify({ amount: 50000.00, // Amount as decimal (50,000 UGX) description: 'Payment for Order #12345', callback_url: 'https://yoursite.com/webhooks/payment-status' }) }); const data = await response.json(); if (data.reference && data.checkout_url) { // Redirect customer to secure checkout page window.location.href = data.checkout_url; } else { console.error('Failed to create payment intent:', data); }

PHP Example

<?php $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://payhiive.com/api/v1/payments'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ 'amount' => 50000.00, // Amount as decimal (50,000 UGX) 'description' => 'Payment for Order #12345', 'callback_url' => 'https://yoursite.com/webhooks/payment-status' ])); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer sk_your_token', 'Content-Type: application/json' ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $data = json_decode($response, true); if ($httpCode === 201 && isset($data['checkout_url'])) { // Redirect customer to secure checkout page header('Location: ' . $data['checkout_url']); exit; } else { // Handle error echo 'Payment failed: ' . ($data['message'] ?? 'Unknown error'); } ?>

Checking Payment Status

After redirecting your customer to the checkout page, you can check the payment status using the status endpoint.

Get Payment Status

GET /checkout/{reference}/status

Check the status of a payment intent using the reference returned when creating the payment.

Example Request

GET https://payhiive.com/checkout/PHV_MPDJWT5TLC/status Headers: Accept: application/json

Example Response

{ "success": true, "data": { "reference": "PHV_MPDJWT5TLC", "status": "paid", "transaction_status": "completed", "transaction_id": "TXN-ABCDEFGHIJKL", "is_paid": true, "is_completed": true } }

Automatic Payment Provider Check: The status endpoint automatically queries the payment provider's API directly if the payment is still pending. This ensures you get real-time status updates even if webhooks are delayed.

Payment Intent Statuses

Status Description
pending Payment intent created, waiting for customer to pay
paid Payment successfully completed
failed Payment failed
expired Payment intent expired (default: 24 hours)

Checkout Page Features

  • Secure Payment Processing: All payment data is handled securely by PAYHIIVE with SSL encryption
  • Mobile Money Payments: Supports MTN Mobile Money and Airtel Money
  • Mobile Optimized: Fully responsive design optimized for mobile devices
  • Real-time Status Updates: Automatic status polling to track payment progress
  • Expiration Management: Payment intents expire after 24 hours for security
  • Email Notifications: Merchants receive email notifications when payments are completed
  • Webhook Support: Instant payment notifications via webhooks

Best Practice: Always verify the payment status on your server using the reference and status endpoint, rather than relying solely on the redirect. This ensures the payment was actually completed.

Payment Intent Checkout (Hosted Checkout)

PAYHIIVE provides a secure hosted checkout page for payment intents. This is the recommended way to accept payments as it ensures merchants never control payment amounts, currency, or recipient information on the frontend. All payment data is stored server-side and fetched from the database using a secure, unguessable reference.

⚡ Quick Start - Copy & Paste Ready

Copy these code snippets and replace with your token. That's it!

Default Checkout URL Format (Copy This)

https://payhiive.com/checkout/PHV_MPDJWT5TLC

This is an example. Replace PHV_MPDJWT5TLC with the actual reference from the response

JavaScript/React - Copy & Paste

// Step 1: Replace with your token from Dashboard → Tokens
const API_BASE_URL = 'https://payhiive.com/api/v1';
const TOKEN = 'sk_your_token';  // Your token from Dashboard → Tokens

// Step 2: Function to create payment and redirect to checkout
async function redirectToPayHiveCheckout(amount, description) {
  try {
    // Create payment intent via API
    const response = await fetch(`${API_BASE_URL}/payments`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${TOKEN}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        amount: amount,           // e.g., 50000.00 for 50,000 UGX
        description: description,  // e.g., "Order #12345"
        callback_url: 'https://yoursite.com/webhooks/payment'  // Optional: for webhooks
      })
    });

    const data = await response.json();

    // Step 3: Redirect customer to checkout page
    if (data.checkout_url) {
      window.location.href = data.checkout_url;  // ← This redirects to PayHive checkout
      return { success: true, reference: data.reference };
    } else {
      throw new Error(data.message || 'Failed to create payment');
    }
  } catch (error) {
    console.error('Payment error:', error);
    alert('Payment failed: ' + error.message);
    return { success: false, error: error.message };
  }
}

// Step 4: Use it in your "Pay Now" button
document.getElementById('pay-button').addEventListener('click', async () => {
  await redirectToPayHiveCheckout(50000.00, 'Payment for Order #12345');
  // Customer will be automatically redirected to checkout page
});

// Notes:
// - Replace API_BASE_URL with your PayHive instance URL
// - Get your token from: Dashboard → Tokens
// - The checkout_url from the response is the redirect destination
// - Amount is in smallest currency unit (50000.00 = 50,000 UGX)
// - Always call this from your backend in production (keep token secure)

PHP - Copy & Paste

<?php
// Step 1: Replace with your token from Dashboard → Tokens
$API_BASE_URL = 'https://payhiive.com/api/v1';
$TOKEN = 'sk_your_token';  // Your token from Dashboard → Tokens

// Step 2: Function to create payment and redirect to checkout
function redirectToPayHiveCheckout($amount, $description) {
    global $API_BASE_URL, $TOKEN;
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $API_BASE_URL . '/payments');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Authorization: Bearer ' . $TOKEN,
        'Content-Type: application/json'
    ]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
        'amount' => $amount,           // e.g., 50000.00 for 50,000 UGX
        'description' => $description, // e.g., "Order #12345"
        'callback_url' => 'https://yoursite.com/webhooks/payment'  // Optional
    ]));
    
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    $data = json_decode($response, true);
    
    // Step 3: Redirect customer to checkout page
    if ($httpCode === 201 && isset($data['checkout_url'])) {
        header('Location: ' . $data['checkout_url']);  // ← This redirects to PayHive checkout
        exit;
    } else {
        die('Payment failed: ' . ($data['message'] ?? 'Unknown error'));
    }
}

// Step 4: Use it when customer clicks "Pay Now"
if (isset($_POST['pay_now'])) {
    redirectToPayHiveCheckout(50000.00, 'Payment for Order #12345');
    // Customer will be automatically redirected to checkout page
}

// Notes:
// - Replace $API_BASE_URL with your PayHive instance URL
// - Get your token from: Dashboard → Tokens
// - The checkout_url from the response is the redirect destination
// - Amount is in smallest currency unit (50000.00 = 50,000 UGX)
// - Always keep token on server, never expose in frontend

Python (Flask/Django) - Copy & Paste

import requests
from flask import redirect  # or: from django.shortcuts import redirect

# Step 1: Replace with your token from Dashboard → Tokens
API_BASE_URL = 'https://payhiive.com/api/v1'
TOKEN = 'sk_your_token'  # Your token from Dashboard → Tokens

# Step 2: Function to create payment and redirect to checkout
def redirect_to_payhive_checkout(amount, description):
    url = f'{API_BASE_URL}/payments'
    headers = {
        'Authorization': f'Bearer {TOKEN}',
        'Content-Type': 'application/json'
    }
    data = {
        'amount': amount,           # e.g., 50000.00 for 50,000 UGX
        'description': description,  # e.g., "Order #12345"
        'callback_url': 'https://yoursite.com/webhooks/payment'  # Optional
    }
    
    response = requests.post(url, json=data, headers=headers)
    result = response.json()
    
    # Step 3: Redirect customer to checkout page
    if response.status_code == 201 and 'checkout_url' in result:
        return redirect(result['checkout_url'])  # ← This redirects to PayHive checkout
    else:
        return {'error': result.get('message', 'Payment failed')}

# Step 4: Use it in your route/view
@app.route('/pay', methods=['POST'])  # Flask example
def pay():
    return redirect_to_payhive_checkout(50000.00, 'Payment for Order #12345')
    # Customer will be automatically redirected to checkout page

# Notes:
# - Replace API_BASE_URL with your PayHive instance URL
# - Get your token from: Dashboard → Tokens
# - The checkout_url from the response is the redirect destination
# - Amount is in smallest currency unit (50000.00 = 50,000 UGX)
# - Keep your token on server, never expose in frontend
# - Install requests: pip install requests

That's it! Just copy the code, replace your token, and redirect to checkout_url. The checkout page handles everything else.

Security Features:

  • Unguessable payment references (PHV_xxxxx format)
  • Amount, currency, and recipient are NEVER read from request
  • All data fetched from database using reference
  • Automatic expiration (configurable, default: 24 hours)
  • Rate limiting on checkout routes
  • No token exposed in frontend

Quick Start Guide: Step-by-Step Instructions

Follow these simple steps to integrate the hosted checkout page into your application:

Step 1: Create a Payment Intent

Make a POST request to /api/v1/payments with the payment amount and description.

POST https://payhiive.com/api/v1/payments Headers: Authorization: Bearer sk_your_token Content-Type: application/json Body: { "amount": 50000.00, "description": "Payment for Order #12345" }

Step 2: Get the Checkout URL

The API will return a response with a checkout_url:

{ "reference": "PHV_MPDJWT5TLC", "checkout_url": "https://payhiive.com/checkout/PHV_MPDJWT5TLC" }

Step 3: Redirect Customer to Checkout

Redirect your customer to the checkout_url from the response. The customer will see a secure checkout page where they can complete the payment.

Important: Always redirect to the checkout_url provided in the response. Never construct the URL manually or trust frontend data.

Step 4: Handle Payment Completion

After the customer completes payment, you can:

  • Use Webhooks: If you provided a callback_url, you'll receive a POST request when payment status changes
  • Poll for Status: Check payment status by querying the payment intent using the reference

Creating a Payment Intent

To create a payment intent, make a POST request to the payments endpoint. This will create a payment intent and return a checkout URL.

Create Payment Intent

POST /api/v1/payments

Create a new payment intent and get a secure checkout URL to redirect your customer to.

Request Body

Parameter Type Description Required
amount decimal Payment amount (e.g., 50000.00 for 50,000 UGX) Required
description string Payment description (max 500 characters) Optional
callback_url string Webhook URL to receive payment status updates Optional

Note: Currency is fixed to UGX for payment intents. The amount should be provided as a decimal number (e.g., 50000.00 for 50,000 UGX).

Example Request

POST https://payhiive.com/api/v1/payments Headers: Authorization: Bearer sk_your_token Content-Type: application/json Body: { "amount": 50000.00, "description": "Payment for Order #12345", "callback_url": "https://yoursite.com/webhooks/payment-status" }

Example Response

{ "reference": "PHV_MPDJWT5TLC", "checkout_url": "https://payhiive.com/checkout/PHV_MPDJWT5TLC" }

How to Redirect Customers to Checkout

After creating a payment intent, you'll receive a checkout_url in the response. Redirect your customer to this URL to complete the payment.

Important: Always use the checkout_url from the response. Never construct the URL manually or allow the frontend to modify the amount or payment details.

What Customers Will See

When customers visit the checkout URL, they will see:

  • PayHive Branding: Professional, secure checkout page
  • Payment Amount: Displayed prominently (read-only, from database)
  • Merchant Name: Your business name
  • Payment Description: Description you provided when creating the payment intent
  • Mobile Money Options: MTN Mobile Money and Airtel Money buttons
  • Secure Form: Fields for customer name, email, and phone number

Complete Integration Examples

JavaScript/React Example (Frontend)

Note: This example shows frontend code, but in production, you should make the API call from your backend server to keep your token secure.

// Step 1: Create payment intent (call from your backend) async function createPaymentIntent(amount, description) { try { const response = await fetch('https://payhiive.com/api/v1/payments', { method: 'POST', headers: { 'Authorization': 'Bearer sk_your_token', // ⚠️ Keep token on backend! 'Content-Type': 'application/json' }, body: JSON.stringify({ amount: amount, description: description, callback_url: 'https://yoursite.com/webhooks/payment-status' // Optional }) }); const data = await response.json(); // Step 2: Check if payment intent was created successfully if (data.reference && data.checkout_url) { // Step 3: Redirect customer to checkout page window.location.href = data.checkout_url; return { success: true, reference: data.reference }; } else { console.error('Failed to create payment intent:', data); return { success: false, error: data.message || 'Unknown error' }; } } catch (error) { console.error('Error creating payment intent:', error); return { success: false, error: error.message }; } } // Usage example: // When customer clicks "Pay Now" button document.getElementById('pay-button').addEventListener('click', async () => { const result = await createPaymentIntent(50000.00, 'Payment for Order #12345'); if (!result.success) { alert('Failed to create payment: ' + result.error); } // Customer will be automatically redirected to checkout page });
PHP Example (Backend - Recommended)
<?php /** * Step 1: Create Payment Intent * This should be called from your backend server (e.g., when customer clicks "Pay Now") */ function createPaymentIntent($amount, $description, $callbackUrl = null) { $baseUrl = 'https://payhiive.com/api/v1'; $token = 'sk_your_token'; // ⚠️ Keep token secure on your server! $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $baseUrl . '/payments'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); $payload = [ 'amount' => $amount, 'description' => $description ]; if ($callbackUrl) { $payload['callback_url'] = $callbackUrl; } curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $token, 'Content-Type: application/json' ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $data = json_decode($response, true); // Step 2: Check response and get checkout URL if ($httpCode === 201 && isset($data['checkout_url'])) { return [ 'success' => true, 'reference' => $data['reference'], 'checkout_url' => $data['checkout_url'] ]; } else { return [ 'success' => false, 'error' => $data['message'] ?? 'Unknown error' ]; } } // Example: Laravel Controller class PaymentController extends Controller { public function initiateCheckout(Request $request) { // Validate request $request->validate([ 'amount' => 'required|numeric|min:0.01', 'description' => 'nullable|string|max:500' ]); // Step 1: Create payment intent $result = createPaymentIntent( $request->amount, $request->description ?? 'Payment', route('webhooks.payment-status') // Your webhook URL ); // Step 2: Check if successful if ($result['success']) { // Step 3: Redirect customer to checkout page return redirect($result['checkout_url']); } else { // Handle error return back()->withErrors(['error' => $result['error']]); } } } // Example: Plain PHP (when customer clicks "Pay Now") if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['amount'])) { $result = createPaymentIntent( floatval($_POST['amount']), $_POST['description'] ?? 'Payment' ); if ($result['success']) { // Step 3: Redirect customer to checkout header('Location: ' . $result['checkout_url']); exit; } else { // Show error to user die('Payment failed: ' . $result['error']); } } ?>
Python Example (Flask/Django)
import requests from flask import redirect, request, jsonify # For Flask # from django.shortcuts import redirect # For Django def create_payment_intent(amount, description, callback_url=None): """ Step 1: Create a payment intent via API Returns: dict with 'success', 'checkout_url', and 'reference' """ url = 'https://payhiive.com/api/v1/payments' headers = { 'Authorization': 'Bearer sk_your_token', # ⚠️ Keep token on backend! 'Content-Type': 'application/json' } data = { 'amount': amount, 'description': description } if callback_url: data['callback_url'] = callback_url try: response = requests.post(url, json=data, headers=headers) result = response.json() # Step 2: Check if payment intent was created if response.status_code == 201 and 'checkout_url' in result: return { 'success': True, 'checkout_url': result['checkout_url'], 'reference': result['reference'] } else: return { 'success': False, 'error': result.get('message', 'Unknown error') } except Exception as e: return { 'success': False, 'error': str(e) } # Flask Example @app.route('/checkout/initiate', methods=['POST']) def initiate_checkout(): amount = request.json.get('amount') description = request.json.get('description', 'Payment') # Step 1: Create payment intent result = create_payment_intent( amount=amount, description=description, callback_url='https://yoursite.com/webhooks/payment-status' ) if result['success']: # Step 2: Redirect customer to checkout page return redirect(result['checkout_url']) else: return jsonify({'error': result['error']}), 400 # Django Example from django.shortcuts import redirect from django.http import JsonResponse def initiate_checkout(request): if request.method == 'POST': amount = request.POST.get('amount') description = request.POST.get('description', 'Payment') # Step 1: Create payment intent result = create_payment_intent( amount=float(amount), description=description, callback_url='https://yoursite.com/webhooks/payment-status' ) if result['success']: # Step 2: Redirect customer to checkout page return redirect(result['checkout_url']) else: return JsonResponse({'error': result['error']}, status=400)

Checkout Endpoint URL Format

The checkout URL that you receive from the API follows this format:

Checkout URL Structure

https://payhiive.com/checkout/{reference}

Where {reference} is the unguessable payment reference in the format PHV_xxxxx (e.g., PHV_MPDJWT5TLC).

Example Checkout URLs

Here are real examples of checkout URLs you'll receive:

// Example 1: Your actual checkout URL (from your system) https://payhiive.com/checkout/PHV_MPDJWT5TLC // Example 2: Another example format https://payhiive.com/checkout/PHV_DZ4LGW3QM0 // Example 3: Production example (when app_url is set in database) https://payhiive.com/checkout/PHV_MPDJWT5TLC

How to Use the Checkout URL

When you receive the checkout_url from the response, simply redirect your customer to that URL:

// JavaScript/React window.location.href = data.checkout_url; // PHP header('Location: ' . $data['checkout_url']); exit; // Python (Flask) return redirect(result['checkout_url']) // Python (Django) return redirect(result['checkout_url'])

Important: Always use the checkout_url from the response. Do not construct the URL manually. The reference is generated server-side and is cryptographically secure. The format is always https://payhiive.com/checkout/PHV_MPDJWT5TLC where PHV_MPDJWT5TLC is a unique reference (PHV_ + 10 characters).

Checkout URL Breakdown

Component Description Example
Base URL Your PayHive instance URL https://payhiive.com
/checkout/ Checkout route prefix /checkout/
Reference Unique payment intent reference (PHV_ + 10 characters) PHV_MPDJWT5TLC

Complete Flow Diagram

  1. Customer clicks "Pay Now" on your website/app
  2. Your backend calls POST /api/v1/payments with amount and description
  3. API returns checkout_url (e.g., https://payhiive.com/checkout/PHV_MPDJWT5TLC)
  4. Redirect customer to the checkout_url
  5. Customer sees secure checkout page with payment amount and mobile money options
  6. Customer enters phone number and selects network (MTN/Airtel)
  7. Payment processed via mobile money provider - customer approves on their phone
  8. Webhook sent to your callback_url (if provided) with payment status
  9. Customer redirected to success page after payment completes

Payment Intent Statuses

Status Description
pending Payment intent created, waiting for customer to complete payment
paid Payment successfully completed
failed Payment failed (customer declined, insufficient funds, etc.)
expired Payment intent expired (default: 24 hours after creation)

Webhook Notifications

If you provided a callback_url when creating the payment intent, you will receive a POST request to that URL when the payment status changes.

Webhook Payload

POST https://yoursite.com/webhooks/payment-status Content-Type: application/json { "reference": "PHV_MPDJWT5TLC", "status": "paid", "transaction_id": "TXN-ABCDEFGHIJKL", "amount": 50000.00, "currency": "UGX", "net_amount": 48500.00, "timestamp": "2025-01-25T12:00:00Z" }

Webhook Status Values

  • paid - Payment successfully completed
  • failed - Payment failed

Verifying Webhook Requests

Always verify that the webhook request is legitimate by:

  1. Checking the payment reference exists in your system
  2. Verifying the amount matches your records
  3. Updating your order/payment status only after verification

Checking Payment Status

After redirecting your customer to the checkout page, you can check the payment status in several ways:

Method 1: Status Endpoint (Recommended for Real-time Updates)

Poll the status endpoint to check if payment has been completed. The system automatically checks the payment provider directly if the webhook hasn't arrived yet.

GET /checkout/{reference}/status
Example Request
GET https://payhiive.com/checkout/PHV_MPDJWT5TLC/status Headers: Accept: application/json
Example Response
{ "success": true, "data": { "reference": "PHV_MPDJWT5TLC", "status": "paid", "transaction_status": "completed", "transaction_id": "TXN-ABCDEFGHIJKL", "is_paid": true, "is_completed": true } }

Automatic Payment Provider Check: The status endpoint automatically queries the payment provider's API directly if the payment is still pending. This ensures you get real-time status updates even if webhooks are delayed. The system uses the same reliable method as payment links.

JavaScript Polling Example
// Poll payment status every 2 seconds function checkPaymentStatus(reference) { return fetch(`https://payhiive.com/checkout/${reference}/status`, { method: 'GET', headers: { 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest' }, cache: 'no-cache' }) .then(response => response.json()) .then(data => { if (data.success && data.data) { // Check if payment is completed if (data.data.status === 'paid' || data.data.transaction_status === 'completed' || data.data.is_paid === true || data.data.is_completed === true) { return { completed: true, status: data.data }; } // Check if payment failed if (data.data.status === 'failed' || data.data.transaction_status === 'failed') { return { completed: true, failed: true, status: data.data }; } // Still pending return { completed: false, status: data.data }; } return { completed: false, error: 'Invalid response' }; }); } // Usage: Poll every 2 seconds until completed let pollCount = 0; const maxPolls = 60; // 2 minutes const pollInterval = setInterval(async () => { pollCount++; if (pollCount > maxPolls) { clearInterval(pollInterval); console.log('Polling timeout'); return; } const result = await checkPaymentStatus('PHV_MPDJWT5TLC'); if (result.completed) { clearInterval(pollInterval); if (result.failed) { console.log('Payment failed'); } else { console.log('Payment completed!', result.status); // Update your UI or redirect } } }, 2000); // Check every 2 seconds

Method 2: Webhook Notifications (Recommended for Server-side)

If you provided a callback_url, you'll receive a POST request when the payment status changes. This is the most reliable method for server-side applications.

Best Practice: Use webhooks for server-side status updates, and polling for client-side real-time updates. The status endpoint automatically checks the payment provider directly, so you'll get updates even if webhooks are delayed.

How Payment Status Detection Works

The system uses multiple methods to ensure reliable payment status detection:

  1. Webhook Processing: When the payment provider sends a webhook, the system updates the payment intent and transaction status immediately
  2. Direct Payment Provider API Check: If payment is still pending, the status endpoint queries the payment provider's API directly (same method as payment links)
  3. Automatic Status Sync: When checking status, the system automatically updates the payment intent if the payment provider shows it's completed
  4. Real-time Updates: The checkout page polls the status endpoint every 1-3 seconds and redirects to success when payment is detected

Reliability: The system uses the same proven status detection method as payment links, which includes direct payment provider API checks. This ensures payments are detected even if webhooks are delayed or missed.

Security Best Practices

  • Never trust frontend data: All payment amounts, currency, and recipient information are stored server-side and fetched from the database
  • Verify payment status: Always verify payment completion on your server before fulfilling orders
  • Use HTTPS: Always use HTTPS for callback URLs
  • Handle expiration: Payment intents expire after 24 hours (configurable). Handle expired payments gracefully
  • Rate limiting: Checkout routes are rate-limited to prevent abuse

Testing

You can test the checkout page by visiting:

https://payhiive.com/test-checkout

This will create a test payment intent and redirect you to the checkout page.

Troubleshooting

If you encounter issues with the checkout page, here are common problems and solutions:

"Checkout Endpoint Not Found" Error

If you receive the error message "PayHive checkout endpoint not found. Please contact support to verify your API configuration." when creating a payment intent:

  • API Endpoint Issue: Verify you're using the correct endpoint: POST /api/v1/payments
  • API Authentication: Ensure your Authorization: Bearer header is correct and your token is active
  • Route Configuration: This error typically occurs when the checkout URL cannot be generated. Check that the route checkout.payment-intent.show exists
  • Base URL: Verify your application's APP_URL is correctly configured in your .env file

Solution: Check the response. The checkout_url should be in the format: https://payhiive.com/checkout/PHV_MPDJWT5TLC. If the URL is missing or incorrect, check your Laravel logs at storage/logs/laravel.log for route generation errors.

// Example of correct response: { "reference": "PHV_MPDJWT5TLC", "checkout_url": "https://payhiive.com/checkout/PHV_MPDJWT5TLC" } // If you receive an error instead, check: // 1. API authentication headers // 2. API endpoint URL (should be /api/v1/payments) // 3. Server logs for detailed error messages

Checkout Page Shows "Service Temporarily Unavailable"

If customers see the error message "PayHive payment service is temporarily unavailable. Please try again in a few moments or contact support.", this usually indicates:

  • Payment Provider Integration Not Configured: Ensure payment provider API tokens are configured in the admin settings (either live or sandbox tokens)
  • Database Connection Issues: Check that the database is accessible and the payment_intents table exists
  • Service Error: Check the Laravel logs at storage/logs/laravel.log for detailed error messages

Solution: Verify your payment provider integration settings and check server logs. The checkout page will still load even if payment providers are disabled, but payment processing will fail.

Payment Intent Not Found (404 Error)

If you get a 404 error when accessing the checkout URL:

  • Verify the payment intent reference is correct (format: PHV_MPDJWT5TLC or similar PHV_ format)
  • Check that the payment intent exists in the database
  • Ensure the payment intent hasn't been deleted

Payment Intent Expired

If customers see an "expired" message:

  • Payment intents expire after 24 hours by default (configurable)
  • Create a new payment intent for the customer
  • Handle expiration gracefully in your application by checking the expires_at field

No Payment Providers Available

If the checkout page loads but shows no mobile money options:

  • Check that payment provider integration is configured and active
  • Verify that MTN and/or Airtel providers are enabled in the payment provider integration settings
  • Check the integration's enabled_providers field contains MTN_MOMO_UGA and/or AIRTEL_OAPI_UGA

Payment Processing Fails

If payment submission fails:

  • Check that the phone number is in the correct format (Uganda: 9-10 digits, e.g., 0771234567)
  • Verify the selected mobile money network matches the phone number (MTN vs Airtel)
  • Check payment provider API logs for provider-specific errors
  • Ensure the customer's mobile money account is active and can receive USSD prompts

Webhook Not Received

If you're not receiving webhook notifications:

  • Verify your callback_url is publicly accessible (not localhost)
  • Check that your webhook endpoint accepts POST requests
  • Verify your server can receive requests from PayHive's servers
  • Check server logs for incoming webhook requests
  • Ensure your webhook endpoint returns a 200 status code

Best Practice: Always verify payment completion via webhook or by checking the payment intent status server-side. Never rely solely on the customer being redirected to a success page.

Webhooks (Using Your Token)

Webhooks let you receive real-time notifications about payment and account events. When you create a payment or payment intent with your token, you can pass a callback_url; we will POST to that URL when the payment status changes.

Setting Up Webhooks

  1. Go to your dashboard and navigate to API Management → Webhooks
  2. Click Create Webhook
  3. Enter your webhook URL (must be HTTPS)
  4. Select the events you want to listen to
  5. Save your webhook secret (you'll need it to verify requests)

Webhook Events

Event Description
payment.succeeded Triggered when a payment is successfully completed
payment.failed Triggered when a payment fails
payment.refunded Triggered when a payment is refunded
payment.pending Triggered when a payment is pending

Error Handling

All errors follow a consistent format:

{ "success": false, "error": { "code": "invalid_request", "message": "The request is missing required parameters", "details": { "field": "amount", "reason": "Amount must be greater than 0" } } }

Error Codes

Error Code HTTP Status Description Solution
PROVIDER_NOT_CONFIGURED 503 Payment provider not configured Contact support to configure payment provider
PROVIDER_NOT_ENABLED 400 Requested provider (MTN/Airtel) is not enabled Contact support to enable the provider or use a different provider
FEE_EXCEEDS_AMOUNT 400 Total fees exceed transaction amount Increase the transaction amount or adjust fee settings
AUTH_FAILED 401 Invalid or missing token Check that your Authorization: Bearer token is correct
INVALID_REQUEST 400 Invalid request parameters Check required fields: amount, currency, phone_number, provider
NOT_FOUND 404 Transaction not found Verify the transaction_id is correct

Common Issues & Troubleshooting

Issue: "AUTH_FAILED" Error

Possible causes:

  • Missing or incorrect token in headers
  • Token is inactive or revoked
  • Using sandbox keys in production or vice versa

Solution: Verify your token is correct and active in Dashboard → Tokens.

Issue: "PROVIDER_NOT_ENABLED" Error

Possible causes:

  • The provider (MTN_MOMO_UGA or AIRTEL_OAPI_UGA) is not enabled for your account
  • Typo in provider name

Solution: Use the correct provider name: MTN_MOMO_UGA or AIRTEL_OAPI_UGA. Contact support if the provider needs to be enabled.

Issue: Payment Stays in "pending" Status

Possible causes:

  • Customer hasn't approved the payment on their phone
  • Customer's phone is off or out of network coverage
  • Insufficient mobile money balance

Solution: Wait for the customer to approve. Check payment status periodically. Payments typically complete within a few minutes.

Issue: Phone Number Format

Format: Phone numbers must be in international format without the + sign:

  • Correct: 256700000000 (Uganda MTN)
  • Incorrect: +256700000000 or 0700000000

Rate Limiting

API requests are rate-limited to ensure fair usage:

  • Sandbox: 100 requests per minute
  • Live: 1000 requests per minute

Rate limit information is included in response headers:

X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 999 X-RateLimit-Reset: 1639123200

Direct Payments (Without Checkout Page)

You can use the same token (from Dashboard → Tokens at https://payhiive.com/customer/tokens) to collect payments without redirecting customers to the hosted checkout page. This is useful when you want to keep users on your own website or app and collect the phone number and network yourself.

Two ways to accept payments with your token:

  • Hosted checkout: POST /api/v1/payments with amount, description, callback_url → get checkout_url and redirect the customer to our secure page.
  • Direct payment (no checkout): POST /api/v1/payments/direct with amount, currency, phone_number, provider, description → we send the mobile money prompt to the customer's phone; they never leave your site.

Tokens generated from the customer dashboard work for both flows. Use the same Authorization: Bearer header.

Create Direct Payment

POST /payments/direct

Initiate a mobile money payment directly. You collect the customer's phone number and network (MTN or Airtel) on your form; we send the payment request to their phone. No redirect to the checkout page.

Request Body

Parameter Type Description Required
amount integer Amount in UGX (e.g., 10000 = 10,000 UGX) Required
currency string Currency code (UGX) Required
phone_number string Customer mobile money number (e.g., 256700000000) Required
provider string MTN_MOMO_UGA or AIRTEL_OAPI_UGA Required
description string Payment description Optional
metadata object Additional metadata (e.g. order_id) Optional

Example Request

POST https://payhiive.com/api/v1/payments/direct Headers: Authorization: Bearer sk_your_token Content-Type: application/json Body: { "amount": 10000, "currency": "UGX", "phone_number": "256700000000", "provider": "MTN_MOMO_UGA", "description": "Payment for order #123" }

Example Response (Success)

{ "success": true, "data": { "id": 123, "transaction_id": "TXN-ABC123XYZ", "amount": 10000, "currency": "UGX", "status": "pending", "message": "Payment request sent successfully", "created_at": "2025-12-10T12:00:00Z" } }

Reference (UUID): Use transaction_id for status checks. The reference (UUID format, e.g. b6a677d8-8a3d-4d2d-9de5-d439510d7c62) is returned when you call GET /api/v1/payments/{transaction_id}; store it for reconciliation and provider tracking.

Sample Code (Copy & Paste)

React (JavaScript)

const API_BASE = 'https://payhiive.com/api/v1'; const TOKEN = 'sk_your_token'; async function createDirectPayment(amount, currency, phoneNumber, provider, description) { const res = await fetch(`${API_BASE}/payments/direct`, { method: 'POST', headers: { 'Authorization': `Bearer ${TOKEN}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ amount, currency: currency || 'UGX', phone_number: phoneNumber, provider: provider || 'MTN_MOMO_UGA', description: description || '', }), }); const data = await res.json(); if (!data.success) throw new Error(data.message || 'Payment failed'); return data.data; // { transaction_id, status, ... } } async function getPaymentStatus(transactionId) { const res = await fetch(`${API_BASE}/payments/${transactionId}`, { headers: { 'Authorization': `Bearer ${TOKEN}` }, }); const data = await res.json(); if (!data.success) throw new Error(data.message || 'Failed to get status'); return data.data; // includes reference (UUID) for reconciliation } // Usage: collect phone on your form, then: const payment = await createDirectPayment(10000, 'UGX', '256700000000', 'MTN_MOMO_UGA', 'Order #123'); const txId = payment.transaction_id; // store for status polling const status = await getPaymentStatus(txId); const referenceUuid = status.reference; // UUID, e.g. b6a677d8-8a3d-4d2d-9de5-d439510d7c62

Python

import requests API_BASE = 'https://payhiive.com/api/v1' TOKEN = 'sk_your_token' HEADERS = {'Authorization': f'Bearer {TOKEN}', 'Content-Type': 'application/json'} def create_direct_payment(amount, phone_number, provider='MTN_MOMO_UGA', description=''): r = requests.post(f'{API_BASE}/payments/direct', json={ 'amount': amount, 'currency': 'UGX', 'phone_number': phone_number, 'provider': provider, 'description': description, }, headers=HEADERS) data = r.json() if not data.get('success'): raise Exception(data.get('message', 'Payment failed')) return data['data'] # transaction_id, status, ... def get_payment_status(transaction_id): r = requests.get(f'{API_BASE}/payments/{transaction_id}', headers=HEADERS) data = r.json() if not data.get('success'): raise Exception(data.get('message', 'Failed to get status')) return data['data'] # includes reference (UUID) # Usage payment = create_direct_payment(10000, '256700000000', 'MTN_MOMO_UGA', 'Order #123') tx_id = payment['transaction_id'] # store for status / reconciliation status = get_payment_status(tx_id) reference_uuid = status.get('reference') # UUID, e.g. b6a677d8-8a3d-4d2d-9de5-d439510d7c62

PHP (Laravel)

use Illuminate\Support\Facades\Http; $apiBase = 'https://payhiive.com/api/v1'; $token = 'sk_your_token'; function createDirectPayment($amount, $phoneNumber, $provider = 'MTN_MOMO_UGA', $description = '') { global $apiBase, $token; $res = Http::withHeaders([ 'Authorization' => 'Bearer ' . $token, 'Content-Type' => 'application/json', ])->post("{$apiBase}/payments/direct", [ 'amount' => $amount, 'currency' => 'UGX', 'phone_number' => $phoneNumber, 'provider' => $provider, 'description' => $description, ]); $data = $res->json(); if (!($data['success'] ?? false)) { throw new \Exception($data['message'] ?? 'Payment failed'); } return $data['data']; // transaction_id, status, ... } function getPaymentStatus($transactionId) { global $apiBase, $token; $res = Http::withHeaders([ 'Authorization' => 'Bearer ' . $token, ])->get("{$apiBase}/payments/{$transactionId}"); $data = $res->json(); if (!($data['success'] ?? false)) { throw new \Exception($data['message'] ?? 'Failed to get status'); } return $data['data']; // includes reference (UUID) } // Usage (e.g. in a controller) $payment = createDirectPayment(10000, '256700000000', 'MTN_MOMO_UGA', 'Order #123'); $txId = $payment['transaction_id']; // store for status / reconciliation $status = getPaymentStatus($txId); $referenceUuid = $status['reference'] ?? null; // UUID, e.g. b6a677d8-8a3d-4d2d-9de5-d439510d7c62

The customer will receive a mobile money prompt on their phone. Track status via webhook or GET /api/v1/payments/{transaction_id}.

Same token everywhere. The token you create at https://payhiive.com/customer/tokens works for both hosted checkout and direct payments. Use it in your websites and apps with the headers above.

Integration Examples

Here are complete integration examples for different platforms and languages:

PHP (Laravel/Plain PHP)

<?php // Configuration $baseUrl = 'https://payhiive.com/api/v1'; $token = 'sk_your_token'; // Create payment function createPayment($amount, $phoneNumber, $provider, $description = '') { global $baseUrl, $token; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $baseUrl . '/payments'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ 'amount' => $amount, 'currency' => 'UGX', 'phone_number' => $phoneNumber, 'provider' => $provider, // 'MTN_MOMO_UGA' or 'AIRTEL_OAPI_UGA' 'description' => $description ])); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $token, 'Content-Type: application/json' ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode === 200 || $httpCode === 201) { return json_decode($response, true); } return ['success' => false, 'error' => json_decode($response, true)]; } // Usage $result = createPayment(10000, '256700000000', 'MTN_MOMO_UGA', 'Order #123'); if ($result['success']) { echo "Payment created: " . $result['data']['transaction_id']; echo "\nNet amount: " . ($result['data']['net_amount'] ?? 'N/A') . " UGX"; echo "\nFee: " . ($result['data']['fee'] ?? 'N/A') . " UGX"; } else { echo "Error: " . ($result['error']['message'] ?? $result['message'] ?? 'Unknown error'); } ?>

React (JavaScript/TypeScript)

// Install: npm install axios import axios from 'axios'; const API_BASE_URL = 'https://payhiive.com/api/v1'; const TOKEN = 'sk_your_token'; // Create payment function async function createPayment(amount, phoneNumber, provider, description = '') { try { const response = await axios.post( `${API_BASE_URL}/payments`, { amount: amount, currency: 'UGX', phone_number: phoneNumber, provider: provider, // 'MTN_MOMO_UGA' or 'AIRTEL_OAPI_UGA' description: description }, { headers: { 'Authorization': `Bearer ${TOKEN}`, 'Content-Type': 'application/json' } } ); return response.data; } catch (error) { console.error('Payment error:', error.response?.data || error.message); throw error; } } // React Component Example function PaymentButton() { const handlePayment = async () => { try { const result = await createPayment( 10000, '256700000000', 'MTN_MOMO_UGA', 'Order #123' ); if (result.success) { console.log('Payment created:', result.data.transaction_id); console.log('Net amount:', result.data.net_amount, 'UGX'); console.log('Fee:', result.data.fee, 'UGX'); alert('Payment initiated successfully!'); } } catch (error) { alert('Payment failed: ' + (error.response?.data?.error?.message || error.message)); } }; return ( <button onClick={handlePayment}> Pay 10,000 UGX </button> ); } export default PaymentButton;

Python (Flask/Django)

# Install: pip install requests import requests import json # Configuration API_BASE_URL = 'https://payhiive.com/api/v1' TOKEN = 'sk_your_token' def create_payment(amount, phone_number, provider, description=''): """ Create a mobile money payment Args: amount: Amount in UGX phone_number: Customer phone number (e.g., '256700000000') provider: 'MTN_MOMO_UGA' or 'AIRTEL_OAPI_UGA' description: Payment description Returns: dict: API response """ url = f'{API_BASE_URL}/payments' headers = { 'Authorization': f'Bearer {TOKEN}', 'Content-Type': 'application/json' } data = { 'amount': amount, 'currency': 'UGX', 'phone_number': phone_number, 'provider': provider, 'description': description } try: response = requests.post(url, json=data, headers=headers) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: print(f'Error: {e}') if hasattr(e.response, 'json'): return e.response.json() return {'success': False, 'error': {'message': str(e)}} # Usage example if __name__ == '__main__': result = create_payment( amount=10000, phone_number='256700000000', provider='MTN_MOMO_UGA', description='Order #123' ) if result.get('success'): print(f"Payment created: {result['data']['transaction_id']}") print(f"Net amount: {result['data'].get('net_amount', 'N/A')} UGX") print(f"Fee: {result['data'].get('fee', 'N/A')} UGX") else: print(f"Error: {result.get('error', {}).get('message', result.get('message', 'Unknown error'))}")

Security Note: Never expose your token in client-side code (React, browser JavaScript). Always make API calls from your backend server (PHP, Python, Node.js server) to keep your token secure.

Need Help?

If you have any questions or need assistance with the API, please contact our support team: