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 SettingsIntegrations
  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,
  "transactions": [
    {
      "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:
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()}")