CollectUG Payments API

Welcome to CollectUG Payments API. This API allows you to accept mobile money and card payments, withdraw funds to mobile money, and receive real-time transaction updates via webhooks.

Base URL
All API requests should be made to your CollectUG instance:
https://collectug.com/api
Key Features
  • Accept Payments: Receive mobile money and card payments
  • Send Money: Withdraw funds to mobile money numbers
  • Real-time Updates: Webhook callbacks for transaction status
  • Transaction History: View all your transactions
  • Secure: API key authentication and HTTPS enforcement

Authentication

All API requests require authentication using an API key. Your API key can be found in your merchant dashboard under Settings → Integrations.

All endpoints require authentication
Authentication Header
Include your API key in the Authorization header as a Bearer token:
HTTP Header
X-API-KEY: YOUR_API_KEY
Content-Type: application/json
Getting Your API Key
  1. Log into your CollectUG merchant dashboard
  2. Go to Settings → Integrations
  3. Generate your API key
  4. Copy and store it securely
  5. Configure allowed IP addresses if needed

Configure Callback URL

Set up a default webhook URL to receive transaction status updates. This URL will be used for all transactions unless you specify a different URL per transaction.

POST /api/merchant/callback-url
Configure your default webhook URL. This endpoint requires your API key in the Authorization header.
Request Body
Field Type Required Description
callback_url Required string Yes Your HTTPS webhook URL. Must start with https://
Example Request
curl -X POST https://collectug.com/api/merchant/callback-url \
  -H "Authorization: Bearer sk_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "callback_url": "https://your-app.com/webhooks/collectug"
  }'
Responses
200 - Success
{
                          "success": true,
                          "message": "Callback URL updated successfully",
                          "callback_url": "https://your-app.com/webhooks/collectug",
                          "callback_verified": true
                        }
                    
422 - Validation Error
{
  "success": false,
  "message": "Invalid callback URL format",
  "errors": {
    "callback_url": ["The callback_url must start with https://"]
  }
}

Deposit Funds

Accept payments from customers via mobile money or Visa card. Use this endpoint to initiate a payment collection.

POST /api/credit-account
Collect payment from a customer. Supports both mobile money (MTN, Airtel) and Visa card payments.
Mobile Money Payment
Field Type Required Description
amount Required number Yes Amount to collect (minimum: 1)
phoneNumber Required string Yes Customer's phone number (e.g., 0776913451)
callback_url string No Specific webhook URL for this transaction (overrides default)
merchant_reference string No Your internal reference ID for this transaction
customer_email string No Customer's email for receipt
Visa Card Payment
Field Type Required Description
amount Required number Yes Amount to charge
cardNumber Required string Yes 13-16 digit card number
cardholderName Required string Yes Name on the card
expiryDate Required string Yes Expiry in MM/YY format (e.g., "12/25")
cvv Required string Yes 3-4 digit CVV code
callback_url string No Specific webhook URL for this transaction
Mobile Money Example
curl -X POST https://collectug.com/api/credit-account \
  -H "Authorization: Bearer sk_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 10000,
    "phoneNumber": "0776913451",
    "merchant_reference": "ORDER-12345",
    "customer_email": "customer@example.com",
    "callback_url": "https://your-app.com/order/12345/callback"
  }'
Visa Card Example
curl -X POST https://collectug.com/api/credit-account \
  -H "Authorization: Bearer sk_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 15000,
    "cardNumber": "4111111111111111",
    "cardholderName": "John Doe",
    "expiryDate": "12/25",
    "cvv": "123",
    "callback_url": "https://your-app.com/order/12345/callback"
  }'
Mobile Money Response
200 - Success
{
  "message": "Deposit initiated successfully. Customer will receive a confirmation prompt on their phone.",
  "transaction": {
    "transaction_id": "TXN_ABC123XYZ",
    "amount": 10000,
    "status": "pending",
    "phone_number": "256776913451"
  }
}
Visa Card Response
200 - Success
{
  "message": "Card payment processed successfully",
  "transaction": {
    "transaction_id": "TXN_DEF456UVW",
    "amount": 15000,
    "status": "completed",
    "card_last4": "1111"
  }
}

Withdraw Funds

Send money to a mobile money number. Use this endpoint to disburse funds to customers, pay suppliers, or send refunds.

POST /api/debit-account
Send funds to a mobile money number. The system will check your balance and apply transaction charges.
Request Parameters
Field Type Required Description
amount Required number Yes Amount to send (minimum: 10,000)
phoneNumber Required string Yes Recipient's phone number (e.g., 0776913451)
callback_url string No Specific webhook URL for this transaction
Example Request
curl -X POST https://collectug.com/api/debit-account \
  -H "Authorization: Bearer sk_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 50000,
    "phoneNumber": "0776913451",
    "callback_url": "https://your-app.com/payouts/callback"
  }'
Response
200 - Success
{
  "message": "Withdrawal initiated successfully. Funds will be sent to your number",
  "transaction": {
    "transaction_id": "TXN_GHI789RST",
    "amount": 50000,
    "status": "pending",
    "phone_number": "256776913451"
  },
}
422 - Insufficient Balance
{
                          "message": "Insufficient balance for withdrawal",
                          "available_balance": 20000,
                          "requested_amount": 50000,
                          "required_total": 51210
                        }
                    

Get Transactions

Retrieve your transaction history with filtering options. Use this endpoint to sync transactions with your accounting system.

GET /api/transactions
Fetch your transaction history with optional filters. Supports both GET and POST methods.
Query Parameters
Parameter Type Required Description
status string No Filter by status: pending, completed, failed
start_date date No Start date (YYYY-MM-DD)
end_date date No End date (YYYY-MM-DD)
page number No Page number for pagination
Example Request
curl -X GET \
  "https://collectug.com/api/transactions?status=completed&start_date=2024-01-01&end_date=2024-01-31&page=1" \
  -H "Authorization: Bearer sk_live_your_api_key_here"
Response
200 - Success
{
  "success": true,
  "data": [
    {
      "transaction_id": "TXN_ABC123",
      "amount": 10000,
      "status": "completed",
      "transaction_type": "deposit",
      "service_provider": "mtn",
      "created_at": "2024-01-15T10:30:00Z",
      "phone_number": "256776913451",
      "external_transaction_id": "EXT123456",
      "callback_sent": true
    }
  ],
  "summary": {
    "total": 50,
    "total_amount": 1250000,
    "completed_count": 45,
    "pending_count": 3,
    "failed_count": 2
  },
  "pagination": {
    "current_page": 1,
    "last_page": 3,
    "per_page": 20,
    "total": 50
  }
}

Webhook Callbacks

CollectUG sends HTTP POST callbacks to your configured URL when transaction status changes. This allows you to update your system in real-time.

How Webhooks Work
  1. You configure a callback URL (default or per transaction)
  2. When a transaction status changes, we POST to your URL
  3. You verify the signature and update your system
  4. You respond with HTTP 200 to acknowledge receipt
Callback URL Priority
  • Transaction-specific URL: If you provide callback_url in a transaction request, that URL will be used for that transaction only
  • Default URL: If no transaction-specific URL, your configured default callback URL is used
  • HTTPS Required: All callback URLs must use HTTPS
Callback Payload
When a transaction status changes, we send a POST request with this JSON payload:
Webhook Payload
{
  "transaction_id": "TXN_ABC123",
  "external_transaction_id": "EXT123456",
  "amount": 10000,
  "status": "completed",
  "currency": "UGX",
  "timestamp": "2024-01-15T10:30:00Z",
  "merchant_reference": "ORDER-12345",
  "customer_email": "customer@example.com",
  "service_provider": "mtn",
  "transaction_type": "deposit",
  "phone_number": "256776913451",
  "callback_source": "request",
  "signature": "hmac_sha256_signature_here"
}
Verifying Signatures
For security, verify the signature in each webhook using your webhook secret:
📚 Complete Webhook Guide: For detailed webhook implementation examples in multiple programming languages, security best practices, and troubleshooting tips, see our comprehensive Webhook Integration Guide.
PHP Example
// Get the signature from header or payload
$receivedSignature = $_POST['signature'];

// Remove signature from data before hashing
$data = $_POST;
unset($data['signature']);

// Generate expected signature
$expectedSignature = hash_hmac('sha256', json_encode($data), $yourWebhookSecret);

// Verify
if (hash_equals($expectedSignature, $receivedSignature)) {
    // Signature is valid
    http_response_code(200);
} else {
    // Invalid signature
    http_response_code(400);
}

PHP Integration Example

Example PHP code for integrating with CollectUG Payments API.

Complete PHP Example
<?php

class CollectUGClient {
    private $apiKey;
    private $baseUrl;

    public function __construct($apiKey, $baseUrl = 'https://collectug.com/api') {
        $this->apiKey = $apiKey;
        $this->baseUrl = $baseUrl;
    }

    public function createDeposit($amount, $phoneNumber, $options = []) {
        $data = [
            'amount' => $amount,
            'phoneNumber' => $phoneNumber,
        ];

        if (isset($options['callback_url'])) {
            $data['callback_url'] = $options['callback_url'];
        }

        if (isset($options['merchant_reference'])) {
            $data['merchant_reference'] = $options['merchant_reference'];
        }

        return $this->request('/credit-account', $data);
    }

    public function createWithdrawal($amount, $phoneNumber, $callbackUrl = null) {
        $data = [
            'amount' => $amount,
            'phoneNumber' => $phoneNumber,
        ];

        if ($callbackUrl) {
            $data['callback_url'] = $callbackUrl;
        }

        return $this->request('/debit-account', $data);
    }

    public function getTransactions($filters = []) {
        return $this->request('/transactions', $filters, 'GET');
    }

    private function request($endpoint, $data = [], $method = 'POST') {
        $url = $this->baseUrl . $endpoint;

        $ch = curl_init($url);

        $headers = [
            'Authorization: Bearer ' . $this->apiKey,
            'Content-Type: application/json',
            'Accept: application/json',
        ];

        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        if ($method === 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        } elseif ($method === 'GET' && !empty($data)) {
            $url .= '?' . http_build_query($data);
            curl_setopt($ch, CURLOPT_URL, $url);
        }

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

        return [
            'status' => $statusCode,
            'body' => json_decode($response, true)
        ];
    }
}

// Usage example
$client = new CollectUGClient('sk_live_your_api_key_here');

// Create a deposit
$result = $client->createDeposit(10000, '0776913451', [
    'merchant_reference' => 'ORDER-12345',
    'callback_url' => 'https://your-app.com/webhook'
]);

if ($result['status'] === 200) {
    echo "Transaction created: " . $result['body']['transaction']['transaction_id'];
} else {
    echo "Error: " . $result['body']['message'];
}

Node.js Integration Example

Example Node.js code for integrating with CollectUG Payments API.

Node.js Example
const axios = require('axios');

class CollectUGClient {
    constructor(apiKey, baseUrl = 'https://collectug.com/api') {
        this.apiKey = apiKey;
        this.baseUrl = baseUrl;
        this.client = axios.create({
            baseURL: baseUrl,
            headers: {
                'Authorization': `Bearer ${apiKey}`,
                'Content-Type': 'application/json',
                'Accept': 'application/json'
            }
        });
    }

    async createDeposit(amount, phoneNumber, options = {}) {
        const data = {
            amount,
            phoneNumber,
            ...options
        };

        try {
            const response = await this.client.post('/credit-account', data);
            return response.data;
        } catch (error) {
            throw new Error(error.response?.data?.message || error.message);
        }
    }

    async createWithdrawal(amount, phoneNumber, callbackUrl = null) {
        const data = {
            amount,
            phoneNumber
        };

        if (callbackUrl) {
            data.callback_url = callbackUrl;
        }

        try {
            const response = await this.client.post('/debit-account', data);
            return response.data;
        } catch (error) {
            throw new Error(error.response?.data?.message || error.message);
        }
    }

    async getTransactions(filters = {}) {
        try {
            const response = await this.client.get('/transactions', { params: filters });
            return response.data;
        } catch (error) {
            throw new Error(error.response?.data?.message || error.message);
        }
    }

    async verifyWebhookSignature(payload, signature, webhookSecret) {
        const crypto = require('crypto');

        // Remove signature from payload before hashing
        const { signature: _, ...dataToSign } = payload;

        const expectedSignature = crypto
            .createHmac('sha256', webhookSecret)
            .update(JSON.stringify(dataToSign))
            .digest('hex');

        return crypto.timingSafeEqual(
            Buffer.from(signature),
            Buffer.from(expectedSignature)
        );
    }
}

// Usage example
const client = new CollectUGClient('sk_live_your_api_key_here');

async function example() {
    try {
        // Create a deposit
        const deposit = await client.createDeposit(10000, '0776913451', {
            merchant_reference: 'ORDER-12345',
            callback_url: 'https://your-app.com/webhook'
        });

        console.log('Transaction created:', deposit.transaction.transaction_id);

        // Get transactions
        const transactions = await client.getTransactions({
            status: 'completed',
            start_date: '2024-01-01'
        });

        console.log('Total transactions:', transactions.summary.total);

    } catch (error) {
        console.error('Error:', error.message);
    }
}

example();

Python Integration Example

Example Python code for integrating with CollectUG Payments API.

Python Example
import requests
import json
import hmac
import hashlib

class CollectUGClient:
    def __init__(self, api_key, base_url='https://collectug.com/api'):
        self.api_key = api_key
        self.base_url = base_url
        self.session = requests.Session()
        self.session.headers.update({
            'Authorization': f'Bearer {api_key}',
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        })

    def create_deposit(self, amount, phone_number, **kwargs):
        """Create a deposit transaction"""
        data = {
            'amount': amount,
            'phoneNumber': phone_number
        }
        data.update(kwargs)

        response = self.session.post(f'{self.base_url}/credit-account', json=data)
        response.raise_for_status()
        return response.json()

    def create_withdrawal(self, amount, phone_number, callback_url=None):
        """Create a withdrawal transaction"""
        data = {
            'amount': amount,
            'phoneNumber': phone_number
        }

        if callback_url:
            data['callback_url'] = callback_url

        response = self.session.post(f'{self.base_url}/debit-account', json=data)
        response.raise_for_status()
        return response.json()

    def get_transactions(self, **filters):
        """Get transaction history with optional filters"""
        params = filters

        response = self.session.get(f'{self.base_url}/transactions', params=params)
        response.raise_for_status()
        return response.json()

    def verify_webhook_signature(self, payload, signature, webhook_secret):
        """Verify webhook signature"""
        # Remove signature from payload before hashing
        data_to_sign = payload.copy()
        data_to_sign.pop('signature', None)

        # Convert to JSON string
        message = json.dumps(data_to_sign, separators=(',', ':'), sort_keys=True)

        # Calculate expected signature
        expected_signature = hmac.new(
            webhook_secret.encode('utf-8'),
            msg=message.encode('utf-8'),
            digestmod=hashlib.sha256
        ).hexdigest()

        # Compare signatures
        return hmac.compare_digest(signature, expected_signature)

# Usage example
if __name__ == "__main__":
    client = CollectUGClient(api_key='sk_live_your_api_key_here')

    try:
        # Create a deposit
        deposit = client.create_deposit(
            amount=10000,
            phone_number='0776913451',
            merchant_reference='ORDER-12345',
            callback_url='https://your-app.com/webhook'
        )

        print(f"Transaction created: {deposit['transaction']['transaction_id']}")

        # Get recent transactions
        transactions = client.get_transactions(
            status='completed',
            start_date='2024-01-01'
        )

        print(f"Total transactions: {transactions['summary']['total']}")

    except requests.exceptions.RequestException as e:
        print(f"Error: {e}")
        if e.response:
            print(f"Response: {e.response.json()}")