Overview

HoneyCoin is a leading mobile money aggregator across East Africa, providing unified access to multiple mobile network operators. With FundKit’s HoneyCoin integration, you can process payments across Uganda, Kenya, and Tanzania through a single provider.
HoneyCoin specializes in cross-border payments and multi-operator support, making it ideal for businesses operating across multiple East African countries.

Coverage & Capabilities

Supported Countries

Uganda

Networks: MTN, Airtel Currency: UGX Features: Collections, Payouts, Status Check

Kenya

Networks: Safaricom, Airtel Currency: KES Features: Collections, Payouts, Status Check

Tanzania

Networks: Vodacom, Airtel, Tigo Currency: TZS Features: Collections, Status Check

Capabilities

  • Collections - Charge customers via mobile money
  • Payouts - Send money to recipients
  • Status Checking - Real-time transaction status
  • Webhooks - Instant status notifications
  • Multi-currency - UGX, KES, TZS support
  • Cross-border - Process payments across countries
  • Bulk operations - Process multiple transactions
  • Refunds - Available on request

Installation

npm install @fundkit/honeycoin

Configuration

Basic Setup

import { HoneyCoin } from '@fundkit/honeycoin';

const honeycoin = new HoneyCoin({
  apiKey: process.env.HONEYCOIN_API_KEY!,
  publicKey: process.env.HONEYCOIN_PUBLIC_KEY!,
  environment: 'sandbox', // or 'production'
});

Configuration Options

apiKey
string
required
Your HoneyCoin API key. Get this from your HoneyCoin dashboard.
publicKey
string
required
Your HoneyCoin public key for webhook signature verification.
environment
'sandbox' | 'production'
default:"sandbox"
Environment mode. Use sandbox for testing, production for live payments.
timeout
number
default:"30000"
Request timeout in milliseconds.
retries
number
default:"3"
Number of retry attempts for failed requests.
webhookUrl
string
URL to receive webhook notifications for transaction updates.

Advanced Configuration

const honeycoin = new HoneyCoin({
  apiKey: process.env.HONEYCOIN_API_KEY!,
  publicKey: process.env.HONEYCOIN_PUBLIC_KEY!,
  environment: 'production',

  // Advanced options
  timeout: 45000,
  retries: 5,
  retryDelay: 2000,

  // Webhook configuration
  webhookUrl: 'https://api.myapp.com/webhooks/honeycoin',
  webhookSecret: process.env.HONEYCOIN_WEBHOOK_SECRET,

  // Rate limiting
  rateLimit: {
    requests: 100,
    window: 60000, // Per minute
  },

  // Custom headers
  headers: {
    'User-Agent': 'MyApp/1.0',
    'X-Source': 'mobile-app',
  },

  // Logging
  logger: customLogger,
  logLevel: 'info', // 'debug', 'info', 'warn', 'error'
});

Getting API Credentials

Sandbox Credentials

For testing, you can get sandbox credentials instantly:
1

Visit HoneyCoin Developer Portal

Go to developer.honeycoin.io and create an account
2

Create Sandbox Application

Click “Create App” and select “Sandbox Environment”
3

Get Your Keys

Copy your API Key and Public Key from the dashboard
4

Set Environment Variables

HONEYCOIN_API_KEY=hc_test_your_api_key_here
HONEYCOIN_PUBLIC_KEY=pk_test_your_public_key_here

Production Credentials

For live payments, you need to complete HoneyCoin’s onboarding:
  1. Business Registration - Submit business documents 2. Compliance Review - KYC/AML verification (2-5 business days) 3. Integration Testing - Complete test scenarios 4. Go-Live Approval - Final review and approval 5. Production Keys - Receive live API credentials
Production approval typically takes 3-7 business days. Plan accordingly for your launch timeline.

Usage Examples

Basic Collection

import { PaymentClient } from '@fundkit/core';
import { HoneyCoin } from '@fundkit/honeycoin';

const honeycoin = new HoneyCoin({
  apiKey: process.env.HONEYCOIN_API_KEY!,
  publicKey: process.env.HONEYCOIN_PUBLIC_KEY!,
  environment: 'sandbox',
});

const client = new PaymentClient({
  apiKey: process.env.FUNDKIT_API_KEY!,
  providers: [honeycoin],
  environment: 'sandbox',
});

// Process payment
const transaction = {
  amount: 10000, // 100.00 UGX
  currency: 'UGX',
  operator: 'mtn',
  accountNumber: '256779280949',
  externalId: 'order_12345',
  reason: 'Product purchase',
};

try {
  const result = await client.collection(transaction);
  console.log('Payment initiated:', result);
} catch (error) {
  console.error('Payment failed:', error.message);
}

Multi-Country Payment

// Kenya payment
const kenyaPayment = {
  amount: 5000, // 50.00 KES
  currency: 'KES',
  operator: 'safaricom',
  accountNumber: '254701234567',
  externalId: 'kenya_order_123',
  reason: 'Service payment',
};

// Tanzania payment
const tanzaniaPayment = {
  amount: 20000, // 200.00 TZS
  currency: 'TZS',
  operator: 'vodacom',
  accountNumber: '255754123456',
  externalId: 'tz_order_456',
  reason: 'Product delivery',
};

// Process payments
const [kenyaResult, tanzaniaResult] = await Promise.allSettled([
  client.collection(kenyaPayment),
  client.collection(tanzaniaPayment),
]);

Payout Example

// Send money to a recipient
const payout = {
  amount: 25000, // 250.00 UGX
  currency: 'UGX',
  operator: 'airtel',
  accountNumber: '256701234567',
  externalId: 'payout_789',
  reason: 'Commission payment',

  // Additional payout fields
  recipientName: 'John Doe',
  reference: 'COMM_2024_001',
};

try {
  const result = await honeycoin.payout(payout);
  console.log('Payout sent:', result);
} catch (error) {
  console.error('Payout failed:', error.message);
}

Transaction Limits

Amount Limits by Currency

  • Minimum: 500 UGX - Maximum: 10,000,000 UGX (per transaction) - Daily limit: 20,000,000 UGX (per account) - Monthly limit: 100,000,000 UGX (per account)

Rate Limits

  • API Requests: 100 requests per minute
  • Concurrent Transactions: 50 simultaneous transactions
  • Bulk Operations: 1,000 transactions per batch

Error Handling

Common HoneyCoin Errors

try {
  const result = await client.collection(transaction);
} catch (error) {
  switch (error.code) {
    case 'HC_INSUFFICIENT_FUNDS':
      showMessage('Customer has insufficient balance');
      break;

    case 'HC_INVALID_PHONE':
      showMessage('Invalid phone number format');
      break;

    case 'HC_NETWORK_UNAVAILABLE':
      showMessage('Mobile network is currently unavailable');
      break;

    case 'HC_CUSTOMER_CANCELLED':
      showMessage('Customer cancelled the payment');
      break;

    case 'HC_DUPLICATE_TRANSACTION':
      showMessage('Duplicate transaction detected');
      break;

    case 'HC_ACCOUNT_BLOCKED':
      showMessage('Customer account is temporarily blocked');
      break;

    default:
      showMessage('Payment failed. Please try again.');
      logError(error);
  }
}

Error Details

HC_INSUFFICIENT_FUNDS - Customer doesn’t have enough money HC_CUSTOMER_CANCELLED - Customer declined payment prompt HC_TIMEOUT - Customer didn’t respond to payment prompt HC_INVALID_PIN - Customer entered wrong PIN
HC_INVALID_PHONE - Phone number format is incorrect HC_ACCOUNT_BLOCKED - Customer account is suspended HC_ACCOUNT_NOT_FOUND - Phone number not registered HC_ACCOUNT_LIMIT_EXCEEDED
  • Transaction exceeds account limits
HC_NETWORK_UNAVAILABLE - Mobile network is down HC_PROVIDER_MAINTENANCE - HoneyCoin system maintenance HC_RATE_LIMITED - Too many requests HC_AUTHENTICATION_FAILED - Invalid API credentials

Webhooks

Webhook Configuration

const honeycoin = new HoneyCoin({
  apiKey: process.env.HONEYCOIN_API_KEY!,
  publicKey: process.env.HONEYCOIN_PUBLIC_KEY!,
  webhookUrl: 'https://api.myapp.com/webhooks/honeycoin',
  webhookSecret: process.env.HONEYCOIN_WEBHOOK_SECRET,
});

Webhook Handler

import crypto from 'crypto';
import express from 'express';

const app = express();
app.use(express.raw({ type: 'application/json' }));

app.post('/webhooks/honeycoin', (req, res) => {
  const signature = req.headers['x-honeycoin-signature'];
  const payload = req.body;

  // Verify webhook signature
  const expectedSignature = crypto
    .createHmac('sha256', process.env.HONEYCOIN_WEBHOOK_SECRET!)
    .update(payload)
    .digest('hex');

  if (signature !== `sha256=${expectedSignature}`) {
    return res.status(400).json({ error: 'Invalid signature' });
  }

  const event = JSON.parse(payload.toString());

  // Handle different event types
  switch (event.type) {
    case 'transaction.completed':
      handleTransactionCompleted(event.data);
      break;

    case 'transaction.failed':
      handleTransactionFailed(event.data);
      break;

    case 'transaction.pending':
      handleTransactionPending(event.data);
      break;

    case 'payout.completed':
      handlePayoutCompleted(event.data);
      break;

    default:
      console.log('Unknown event type:', event.type);
  }

  res.status(200).json({ received: true });
});

function handleTransactionCompleted(transaction) {
  console.log('Transaction completed:', transaction.externalId);

  // Update your database
  updateTransactionStatus(transaction.externalId, 'completed');

  // Send confirmation to customer
  sendConfirmationEmail(transaction.customerEmail, transaction);

  // Fulfill the order
  fulfillOrder(transaction.externalId);
}

Webhook Events

transaction.completed

Payment was successful and money has been transferred

transaction.failed

Payment failed due to various reasons (insufficient funds, etc.)

transaction.pending

Payment is waiting for customer confirmation

transaction.timeout

Payment timed out waiting for customer response

payout.completed

Payout was successfully sent to recipient

payout.failed

Payout failed to process

Testing in Sandbox

Test Phone Numbers

HoneyCoin provides special test phone numbers for different scenarios:
// Test numbers for different outcomes
const testNumbers = {
  // Uganda
  success: '256779000001', // Always succeeds
  insufficientFunds: '256779000002', // Always fails with insufficient funds
  timeout: '256779000003', // Always times out
  cancelled: '256779000004', // Customer cancels

  // Kenya
  successKenya: '254701000001', // Always succeeds
  failKenya: '254701000002', // Always fails

  // Tanzania
  successTanzania: '255754000001', // Always succeeds
  failTanzania: '255754000002', // Always fails
};

// Test transaction
const testTransaction = {
  amount: 5000,
  currency: 'UGX',
  operator: 'mtn',
  accountNumber: testNumbers.success,
  externalId: 'test_' + Date.now(),
  reason: 'Test payment',
};

Sandbox Environment Features

Sandbox transactions complete immediately without actual SMS prompts
Use specific test numbers to simulate different scenarios
Webhooks work the same as production for testing your integration
Test as much as you want without hitting rate limits

Production Checklist

Before going live with HoneyCoin:

Credentials

  • Production API keys obtained - [ ] Webhook URL configured - [ ] Environment set to ‘production’ - [ ] Credentials stored securely

Error Handling

  • All error codes handled - [ ] Retry logic implemented - [ ] User-friendly error messages - [ ] Logging and monitoring setup

Webhooks

  • Webhook endpoint secured (HTTPS) - [ ] Signature verification implemented - [ ] Idempotency handling added - [ ] Event types handled properly

Testing

  • End-to-end testing completed - [ ] Cross-country payments tested - [ ] Error scenarios tested - [ ] Load testing performed

Best Practices

Security

// Good: Store credentials securely
const honeycoin = new HoneyCoin({
  apiKey: process.env.HONEYCOIN_API_KEY!,
  publicKey: process.env.HONEYCOIN_PUBLIC_KEY!
});

// Bad: Hardcode credentials
// const honeycoin = new HoneyCoin({
//   apiKey: 'hc_live_123456789',
//   publicKey: 'pk_live_abcdefghi'
// });

Idempotency

// Good: Use unique external IDs
const externalId = `order_${orderId}_${timestamp}`;

// Bad: Non-unique IDs
// const externalId = 'payment';

Webhooks

// Good: Always verify webhook signatures
const isValid = verifyWebhookSignature(
  payload, 
  signature, 
  webhookSecret
);

if (!isValid) {
  return res.status(400).end();
}

Timeouts

// Good: Handle timeouts gracefully
try {
  const result = await client.collection(transaction);
} catch (error) {
  if (error.code === 'HC_TIMEOUT') {
    // Check status instead of immediate retry
    const status = await client.getTransaction({
      provider: 'honeycoin',
      txId: error.transactionId
    });
  }
}

Support & Resources

Next Steps