API Documentation

Complete guide to integrating SikaPay Ghana into your application. Accept Mobile Money payments in minutes.

Getting Started

SikaPay GH provides a simple REST API to accept Mobile Money payments in Ghana. Base URL: https://api.sikapaygh.com

Quick Start Steps:

  1. 1Create account at sikapaygh.com/register
  2. 2Get API keys from Dashboard → Settings → API Keys
  3. 3Test with test keys (sk_test_*) in sandbox
  4. 4Go live with live keys (sk_live_*)

Authentication

All API requests require your secret key in the Authorization header:

javascript
Authorization: Bearer sk_live_your_secret_key

⚠️ Important: Never expose secret keys in client-side code. Always make API calls from your server.

API Keys

Key TypePrefixUsage
Test Secret Keysk_test_Server-side, sandbox
Live Secret Keysk_live_Server-side, production
Test Public Keypk_test_Client-side, sandbox
Live Public Keypk_live_Client-side, production

OTP Login (SMS Verification)

SikaPay supports passwordless login using SMS OTP verification. This is ideal for merchants who prefer to login using their phone number instead of remembering passwords.

How OTP Login Works

  1. 1Merchant enters their registered email address
  2. 2System sends a 6-digit OTP code via SMS to their registered phone number
  3. 3Merchant enters the OTP code to verify and login
  4. 4JWT token is returned for authenticated access

Step 1: Request OTP

Send a request to receive an OTP code via SMS. The code is sent from sender ID sikapay.

javascript
// POST https://api.sikapaygh.com/api/v1/auth/login/request-otp

const response = await fetch('https://api.sikapaygh.com/api/v1/auth/login/request-otp', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    email: 'merchant@company.com'
  })
});

const result = await response.json();

// Success Response:
{
  "status": true,
  "message": "OTP sent successfully",
  "data": {
    "email": "merchant@company.com",
    "phone": "024****567",        // Masked phone number
    "expires_in": 600             // OTP valid for 10 minutes (600 seconds)
  }
}

// Error Response (account not found):
{
  "status": false,
  "message": "No account found with this email"
}

Note: The OTP is valid for 10 minutes and can only be used once. Maximum 3 verification attempts are allowed per OTP.

Step 2: Verify OTP & Login

After the merchant receives the SMS, verify the OTP code to complete login and receive a JWT token.

javascript
// POST https://api.sikapaygh.com/api/v1/auth/login/verify-otp

const response = await fetch('https://api.sikapaygh.com/api/v1/auth/login/verify-otp', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    email: 'merchant@company.com',
    otp: '123456'                  // 6-digit code from SMS
  })
});

const result = await response.json();

// Success Response:
{
  "status": true,
  "message": "Login successful",
  "data": {
    "merchant": {
      "id": "64abc123...",
      "email": "merchant@company.com",
      "business_name": "My Shop Ghana",
      "phone": "0241234567",
      "is_verified": true,
      "is_live": true
    },
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  }
}

// Error Responses:
{
  "status": false,
  "message": "Invalid OTP code"           // Wrong code
}
{
  "status": false,
  "message": "OTP has expired"            // Code expired (>10 mins)
}
{
  "status": false,
  "message": "Maximum attempts exceeded"  // Too many wrong attempts
}

Resend OTP

If the merchant didn't receive the SMS or it expired, they can request a new OTP. There's a 60-second cooldown between resend requests.

javascript
// POST https://api.sikapaygh.com/api/v1/auth/login/resend-otp

const response = await fetch('https://api.sikapaygh.com/api/v1/auth/login/resend-otp', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    email: 'merchant@company.com'
  })
});

const result = await response.json();

// Success Response:
{
  "status": true,
  "message": "OTP resent successfully",
  "data": {
    "email": "merchant@company.com",
    "phone": "024****567",
    "expires_in": 600
  }
}

// Rate limit error (requested too soon):
{
  "status": false,
  "message": "Please wait at least 1 minute before requesting a new OTP"
}

SMS Message Format

The merchant will receive an SMS like this from sender "sikapay":

SikaPay Login: Your verification code is 123456. Valid for 10 minutes. If you did not request this, please ignore.

Security Note: OTP codes are one-time use only. Once verified, the code cannot be used again. Never share OTP codes with anyone - SikaPay staff will never ask for your OTP.

Accept Payments

Initialize Payment

Create a payment and redirect customer to hosted checkout:

javascript
// POST https://api.sikapaygh.com/v1/transaction/initialize

const response = await fetch('https://api.sikapaygh.com/v1/transaction/initialize', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_live_your_secret_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    amount: 100.00,           // Amount in GHS
    email: 'customer@email.com',
    currency: 'GHS',
    callback_url: 'https://yoursite.com/payment/callback',
    metadata: {
      order_id: '12345',
      customer_name: 'Kwame Asante'
    }
  })
});

const { status, data } = await response.json();

// Response:
{
  "status": true,
  "message": "Transaction initialized",
  "data": {
    "reference": "SKPY_1234567890_abc123",
    "authorization_url": "https://checkout.sikapaygh.com/pay/abc123",
    "access_code": "abc123"
  }
}

// Redirect customer to: data.authorization_url

Verify Payment

After payment, verify the transaction:

javascript
// GET https://api.sikapaygh.com/v1/transaction/verify/:reference

const response = await fetch(
  'https://api.sikapaygh.com/v1/transaction/verify/SKPY_1234567890_abc123',
  {
    headers: {
      'Authorization': 'Bearer sk_live_your_secret_key'
    }
  }
);

const { status, data } = await response.json();

// Response:
{
  "status": true,
  "message": "Transaction retrieved",
  "data": {
    "reference": "SKPY_1234567890_abc123",
    "amount": 100.00,
    "currency": "GHS",
    "status": "success",  // success, failed, pending
    "channel": "mtn",
    "customer": {
      "email": "customer@email.com",
      "phone": "0241234567"
    },
    "paid_at": "2024-01-15T10:30:00.000Z"
  }
}

Direct Charge (Mobile Money)

Charge directly without redirect:

javascript
// POST https://api.sikapaygh.com/v1/charge

const response = await fetch('https://api.sikapaygh.com/v1/charge', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_live_your_secret_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    amount: 50.00,
    email: 'customer@email.com',
    mobile_money: {
      phone: '0241234567',
      provider: 'mtn'  // mtn, vodafone, airteltigo
    }
  })
});

// Customer receives prompt on their phone to authorize payment

Payouts

Create Recipient

javascript
// POST https://api.sikapaygh.com/v1/transferrecipient

const response = await fetch('https://api.sikapaygh.com/v1/transferrecipient', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_live_your_secret_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    type: 'mobile_money',
    name: 'Kwame Asante',
    account_number: '0241234567',
    bank_code: 'MTN'  // MTN, VODA, AIRTELTIGO
  })
});

// Response:
{
  "status": true,
  "data": {
    "recipient_code": "RCP_abc123xyz",
    "name": "Kwame Asante",
    "account_number": "0241234567",
    "bank_code": "MTN"
  }
}

Initiate Transfer

javascript
// POST https://api.sikapaygh.com/v1/transfer

const response = await fetch('https://api.sikapaygh.com/v1/transfer', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_live_your_secret_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    amount: 100.00,
    recipient: 'RCP_abc123xyz',
    reason: 'Salary payment'
  })
});

// Response:
{
  "status": true,
  "data": {
    "reference": "TRF_1234567890",
    "amount": 100.00,
    "status": "pending",
    "recipient": {
      "name": "Kwame Asante",
      "account_number": "0241234567"
    }
  }
}

Webhooks

Webhooks notify your server when events happen. Configure your webhook URL in the dashboard.

Events

EventDescription
charge.successPayment was successful
charge.failedPayment failed
transfer.successPayout was successful
transfer.failedPayout failed

Verify Signature

javascript
const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const hash = crypto
    .createHmac('sha512', secret)
    .update(JSON.stringify(payload))
    .digest('hex');
  
  return hash === signature;
}

// Express.js example:
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-sikapay-signature'];
  
  if (!verifyWebhook(req.body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  
  const { event, data } = req.body;
  
  switch (event) {
    case 'charge.success':
      console.log('Payment received:', data.reference);
      // Update order status in your database
      break;
    case 'transfer.success':
      console.log('Payout sent:', data.reference);
      break;
  }
  
  res.status(200).send('OK');
});

API Reference

Base URL: https://api.sikapaygh.com

MethodEndpointDescription
POST/api/v1/auth/loginLogin with email & password
POST/api/v1/auth/login/request-otpRequest OTP for login
POST/api/v1/auth/login/verify-otpVerify OTP & login
POST/api/v1/auth/login/resend-otpResend OTP code
POST/api/v1/transaction/initializeInitialize payment
GET/api/v1/transaction/verify/:refVerify payment
GET/api/v1/transactionList transactions
POST/api/v1/chargeDirect charge
POST/api/v1/payout/sendSend single payout
POST/api/v1/payout/bulkSend bulk payouts
GET/api/v1/payout/verify/:refVerify payout
GET/api/v1/payout/historyPayout history
POST/api/v1/transferrecipientCreate recipient
GET/api/v1/transferrecipientList recipients
GET/api/v1/balanceGet balance

Mobile Money Providers

ProviderCodePhone Prefix
MTN Mobile MoneyMTN or mtn024, 054, 055, 059
Vodafone CashVODA or vodafone020, 050
AirtelTigo MoneyAIRTELTIGO or airteltigo026, 027, 056, 057

Need Help?

Our developer support team is here to help you integrate SikaPay GH.