Click Airtime

Migration Guide: V1 to V2

Step-by-step guide to migrate your integration from the Click Airtime Version 1 API to the Version 2 API.

The Version 2 API offers significant improvements including API key authentication, standardized responses, product catalog lookup, and comprehensive error handling. We strongly recommend migrating all existing V1 integrations.

What Changes in V2

Side-by-Side Comparison

FeatureV1 APIV2 API
AuthenticationHeader-based (email + token)API key (Bearer ce_live_xxx)
Base Path/adp/*/v2/*
Send AirtimePOST /adp/topupPOST /v2/topups
Check BalancesGET /adp/balancesGET /v2/balance
Transaction HistoryGET /adp/transactionsGET /v2/topups
Product CatalogNot availableGET /v2/catalog/lookup
WebhooksNot availableReal-time status callbacks
Response Formatcode: "1"/"0"success: true/false with structured errors
IdempotencyextRefId fieldIdempotency-Key header
Rate Limits60 req/min (topup)300 req/min (configurable per plan)
Phone FormatWithout + prefixE.164 with + prefix

Endpoint Mapping

V1 EndpointV2 EndpointNotes
POST /adp/topupPOST /v2/topupsSimplified request body
GET /adp/balancesGET /v2/balanceReturns wallet-level balances
GET /adp/balances/:idGET /v2/balanceSingle balance endpoint
GET /adp/transactionsGET /v2/topupsAdds pagination, filtering, sorting
N/AGET /v2/catalog/lookupNew: product catalog lookup

Migration Steps

Update Authentication

Replace header-based auth with API key authentication. Generate an API key from the Enterprise Portal under Settings > API Keys.

// V1: Header-based authentication
const response = await fetch('https://api.clickairtime.com/adp/balances', {
  headers: {
    'X-Click-Airtime-Email': 'your@email.com',
    'X-Click-Airtime-Token': 'your-api-token',
  },
});
// V2: API key authentication
const response = await fetch('https://api.clickairtime.com/v2/balance', {
  headers: {
    'Authorization': 'Bearer ce_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  },
});

API keys do not expire, but can be revoked at any time from the Enterprise Portal. See Authentication for details.

Update Top-up Calls

The V2 API uses a simplified request body with phone_number, network_id, and amount.

// V1: Single call to send airtime
const result = await fetch('https://api.clickairtime.com/adp/topup', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Click-Airtime-Email': 'your@email.com',
    'X-Click-Airtime-Token': 'your-api-token',
  },
  body: JSON.stringify({
    msisdn: '233541112259',
    amount: 5,
    extRefId: 'txn_001',
  }),
}).then(r => r.json());

if (result.code === '1') {
  console.log('Success');
}
// V2: Create topup with API key auth
const result = await fetch('https://api.clickairtime.com/v2/topups', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer ce_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    'Content-Type': 'application/json',
    'Idempotency-Key': 'txn_001',
  },
  body: JSON.stringify({
    phone_number: '+233541112259',
    network_id: 42,
    amount: { value: 5, currency: 'GHS' },
  }),
}).then(r => r.json());

if (result.success) {
  console.log('Transaction created:', result.data.id);
}

Update Balance Checks

// V1: Get all balances
const balances = await fetch('https://api.clickairtime.com/adp/balances', {
  headers: {
    'X-Click-Airtime-Email': 'your@email.com',
    'X-Click-Airtime-Token': 'your-api-token',
  },
}).then(r => r.json());

// V1: Each network has a separate balance
balances.data.forEach(b => {
  console.log(`${b.serviceName}: ${b.balance} ${b.currency}`);
});
// V2: Get wallet balance
const balance = await fetch('https://api.clickairtime.com/v2/balance', {
  headers: {
    'Authorization': 'Bearer ce_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  },
}).then(r => r.json());

// V2: Wallet balance
console.log(`${balance.data.currency}: ${balance.data.available}`);

Update Transaction Lookups

// V1: Search by phone number
const txns = await fetch(
  'https://api.clickairtime.com/adp/transactions?msisdn=233541112259',
  {
    headers: {
      'X-Click-Airtime-Email': 'your@email.com',
      'X-Click-Airtime-Token': 'your-api-token',
    },
  }
).then(r => r.json());
// V2: Full pagination and filtering
const txns = await fetch(
  'https://api.clickairtime.com/v2/topups?phone_number=%2B233541112259&page=1&limit=20',
  {
    headers: {
      'Authorization': 'Bearer ce_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    },
  }
).then(r => r.json());

console.log(`Total: ${txns.meta.total}, Page: ${txns.meta.page}`);

Update Error Handling

// V1: Check string code field
const result = await sendTopup();

if (result.code === '0') {
  // Parse the message string to understand the error
  console.error('Failed:', result.message);
}
// V2: Structured error codes
const result = await sendTopup();

if (!result.success) {
  switch (result.error.code) {
    case 'INSUFFICIENT_BALANCE':
      // Handle low balance
      break;
    case 'INVALID_PHONE_NUMBER':
      // Handle bad phone number
      break;
    case 'NETWORK_NOT_FOUND':
      // Handle unsupported destination
      break;
    default:
      console.error(`Error ${result.error.code}: ${result.error.message}`);
  }
}

Update Phone Number Formatting

The V2 API requires E.164 format (with the + prefix), while V1 used numbers without the prefix.

// V1 format: no plus prefix
const v1Phone = '233541112259';

// V2 format: E.164 with plus prefix
const v2Phone = '+233541112259';

// Simple conversion
function convertToV2Format(v1Phone) {
  return v1Phone.startsWith('+') ? v1Phone : `+${v1Phone}`;
}

Checklist

Use this checklist to track your migration progress:

  • Generate an API key from the Enterprise Portal
  • Replace header-based auth with Authorization: Bearer API key
  • Update top-up calls to use POST /v2/topups
  • Update balance checks to use GET /v2/balance
  • Update transaction lookups to use GET /v2/topups
  • Add + prefix to all phone numbers (E.164 format)
  • Replace code === "1" checks with success === true
  • Implement structured error handling using error.code
  • Add Idempotency-Key header for transaction creation
  • Set up webhooks for asynchronous status updates (optional)
  • Test all flows in the sandbox environment
  • Switch production traffic to V2 endpoints

Need help migrating? Contact our developer support team at developers@clickairtime.com for personalized migration assistance.