Developer Documentation

Integrate ABCM Pay into your website or app from anywhere in the world. Everything you need to accept payments, manage wallets, and sell airtime/data/cable/electricity is below.

Getting Started

Three steps to your first live request:

  1. Create a free account and complete KYC verification.
  2. Go to API Keys in your dashboard to get your X-Api-Key and X-Api-Secret.
  3. VTU services (airtime, data, cable, electricity, exam pins) require a separate approval - contact support once you're ready to go live with those.
Base URL: https://www.test.abcmtech.com/api/v1 — all endpoints below are relative to this.
Sandbox mode: A fully separate test environment at its own base URL - https://www.test.abcmtech.com/sandbox/v1 - with its own keys (get them from your dashboard's Sandbox Mode page). No real money, no real SMS, no real provider is ever contacted. Amounts ending in .01 simulate a failure, .00 always succeeds.

Authentication

Every request must include two headers. There is no OAuth flow or token expiry to manage - your key/secret pair works until you regenerate it.

curl https://www.test.abcmtech.com/api/v1/wallet/balance \
  -H "X-Api-Key: pk_live_xxxxxxxxxxxxxxxx" \
  -H "X-Api-Secret: sk_live_xxxxxxxxxxxxxxxx"
<?php
$ch = curl_init('https://www.test.abcmtech.com/api/v1/wallet/balance');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'X-Api-Key: pk_live_xxxxxxxxxxxxxxxx',
    'X-Api-Secret: sk_live_xxxxxxxxxxxxxxxx',
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://www.test.abcmtech.com/api/v1/wallet/balance', {
    headers: {
        'X-Api-Key': 'pk_live_xxxxxxxxxxxxxxxx',
        'X-Api-Secret': 'sk_live_xxxxxxxxxxxxxxxx',
    },
});
const data = await response.json();
import requests

response = requests.get(
    'https://www.test.abcmtech.com/api/v1/wallet/balance',
    headers={
        'X-Api-Key': 'pk_live_xxxxxxxxxxxxxxxx',
        'X-Api-Secret': 'sk_live_xxxxxxxxxxxxxxxx',
    },
)
data = response.json()
Never expose your X-Api-Secret in client-side/browser code. Keep all API calls server-side.

Virtual Accounts

Generate a dedicated bank account number for each customer so you can identify who paid you, automatically.

POST/virtual-account/create
ParameterTypeDescription
customer_typestringoptionalindividual (default) or business
first_name / last_namestringrequiredCustomer's name - for an individual customer
business_name / cac_numberstringrequiredRegistered name and CAC number (starting RC or BN) - for a business customer
emailstringrequiredCustomer's email
referencestringrequiredYour own unique reference for this account
GET/virtual-account/{accountNumber}

Look up a single virtual account you created.

GET/virtual-accounts

List every virtual account under your merchant.

POST/virtual-account/{accountNumber}/disable

Stop an account from accepting further payments. Use /enable to reverse this.

Wallet

GET/wallet/balance

Returns your available and unsettled wallet balances in real time.

Transactions

GET/transaction/status?reference={reference}

Check the status of any single transaction by its reference.

GET/transactions

Paginated list of all your transactions, newest first.

Payouts

Send money out of your wallet to any Nigerian bank account. Requires payout access to be enabled on your account first.

GET/payout/banks

List of supported banks and their codes.

POST/payout/verify-account
ParameterTypeDescription
bank_codestringrequiredFrom /payout/banks
account_numberstringrequired10-digit NUBAN
POST/payout/transfer
ParameterTypeDescription
amountnumberrequiredAmount in Naira
bank_codestringrequiredDestination bank
account_numberstringrequiredDestination account
referencestringoptionalYour own idempotency reference
GET/payout/status?reference={reference}

VTU Services

Airtime, data, cable TV, electricity, and exam pins - all through one consistent API shape. Requires VTU API access to be explicitly enabled on your account by our team; a valid key/secret pair alone is not enough.

POST/vtu/airtime
ParameterTypeDescription
networkstringrequiredmtn, glo, airtel, or 9mobile
phonestringrequiredRecipient phone number
amountnumberrequired₦50 - ₦50,000
GET/vtu/data-plans
POST/vtu/data
ParameterTypeDescription
phonestringrequiredRecipient phone number
data_plan_idintegerrequiredFrom /vtu/data-plans
GET/vtu/cable-plans
POST/vtu/cable
ParameterTypeDescription
cable_plan_idintegerrequiredFrom /vtu/cable-plans
smart_card_numberstringrequiredSmart card / IUC number
GET/vtu/discos
POST/vtu/electricity
ParameterTypeDescription
disco_idintegerrequiredFrom /vtu/discos
meter_numberstringrequired
meter_typestringrequiredPrepaid or Postpaid
amountnumberrequired₦500 - ₦100,000
GET/vtu/exam-types
POST/vtu/exam
ParameterTypeDescription
exam_type_idintegerrequiredFrom /vtu/exam-types
quantityintegerrequired1-20
GET/vtu/transaction/status?reference={reference}

Every VTU purchase returns a reference - use it here to poll status.

Collect Payments

Generate a payment link that shows your customer a dedicated bank account number to transfer into, on your own branded page - never a third-party site. Requires Collect Payments API access to be explicitly enabled on your account by our team.

POST/checkout/create
ParameterTypeDescription
amountnumberrequiredAmount in Naira (minimum ₦100)
descriptionstringoptionalShown on the payment page, e.g. "Invoice #123"
customer_namestringoptional
customer_emailstringoptional
callback_urlstringoptionalWhere your customer is redirected after paying. Defaults to a standard return page if omitted.
curl -X POST "https://www.test.abcmtech.com/api/v1/checkout/create" \
  -H "X-Api-Key: pk_live_xxxxxxxxxxxxxxxx" \
  -H "X-Api-Secret: your-api-secret-key" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 5000,
    "description": "Invoice #123",
    "customer_name": "Jane Doe",
    "customer_email": "jane@example.com"
}'

Response:

{
    "success": true,
    "reference": "CHK-20260829092726-MT2QD1",
    "order_no": "24260829092726346817",
    "checkout_url": "https://checkout.palmpay.com/h5-checkout/?...",
    "amount": 5000,
    "currency": "NGN",
    "status": "pending"
}
GET/checkout/status?reference={reference}

Poll this with the reference from the create response to check whether payment has completed.

Redirect your customer to checkout_url to complete payment. Once paid, we notify your account via webhook and credit your wallet automatically - no need to poll status unless you want to reflect it in your own UI immediately.

Virtual Cards

Issue Visa/Mastercard virtual cards for your customers, fund them, freeze/unfreeze, and track spend - all through one API regardless of which card provider is active on the backend. Requires Virtual Card API access to be explicitly enabled on your account by our team.

POST/virtual-cards/cardholders

Creates (or returns the existing) cardholder profile for an email under your account. A cardholder must complete identity verification before a card can be issued to them.

ParameterTypeDescription
first_namestringrequired
last_namestringrequired
emailstringrequiredAlso used to detect an existing cardholder
phonestringoptional
GET/virtual-cards/cardholders/{id}

Returns the cardholder's current KYC status - poll this after creation until it reads APPROVED before issuing a card.

POST/virtual-cards

Issues a new card. Your wallet is charged the card creation fee shown in your dashboard.

ParameterTypeDescription
cardholder_idintegerrequiredFrom the cardholder creation response
brandstringoptionalVISA (default) or MASTERCARD
labelstringoptionalYour own nickname for the card
GET/virtual-cards

Paginated list of every card issued under your account.

GET/virtual-cards/{id}
POST/virtual-cards/{id}/fund

Loads USD onto the card. Your wallet is charged the funding amount plus the funding fee shown in your dashboard.

ParameterTypeDescription
amountnumberrequiredUSD amount to load onto the card
POST/virtual-cards/{id}/unload
ParameterTypeDescription
amountnumberoptionalLeave blank to unload the full balance
POST/virtual-cards/{id}/freeze
POST/virtual-cards/{id}/unfreeze
POST/virtual-cards/{id}/terminate

Terminate is permanent - the card cannot be reactivated afterward.

GET/virtual-cards/{id}/transactions

Paginated spend history for the card, synced from the card provider on each request.

No transaction PIN is required on these endpoints - your API key/secret is the credential for server-to-server calls, same as every other money-moving endpoint in this API.

Webhooks

Configure your webhook URL in the dashboard under Webhook Settings. We'll POST to it whenever a payment is received on one of your virtual accounts.

{
    "event": "payment.received",
    "data": {
        "reference": "ORDER_123",
        "amount": 10000,
        "currency": "NGN",
        "virtual_account": "0123456789",
        "payer_name": "John Doe",
        "payer_bank": "ACCESS BANK",
        "status": "successful",
        "timestamp": "2026-08-27T14:30:00Z"
    },
    "signature": "sha256=abc123..."
}

Verify the signature against your webhook secret before trusting the payload. Respond with HTTP 200 within a few seconds, or we'll retry.

Error Codes

HTTPerror_codeMeaning
401MISSING_CREDENTIALSX-Api-Key or X-Api-Secret header missing
401INVALID_CREDENTIALSKey/secret pair doesn't match any account
403IP_NOT_WHITELISTEDRequest came from an IP not on your account's API whitelist (only enforced if you've turned it on in API Keys)
403KYC_REQUIREDComplete KYC verification before using the API
403SERVICE_NOT_ENABLEDThis specific service (e.g. VTU) hasn't been enabled for your account yet
429RATE_LIMITED / IP_RATE_LIMITEDToo many requests - see Retry-After / retry_after in the response
422-Validation error - check the message field for details

Rate Limits

Standard endpoints: 60 requests/minute per merchant. Payouts: an additional 20 requests/hour per IP address, on top of your configured per-transaction limits. Rate-limited responses include a retry_after field (seconds) telling you exactly when to try again.

Ready to build?

Create a free account and get your API keys in minutes.

Get Started →