Click Airtime

Phone Number Formatting

How to correctly format international phone numbers for the Click Airtime API, including E.164 format, country codes, and validation.

Correct phone number formatting is critical for successful airtime top-ups. This guide explains the formats accepted by the Click Airtime API and provides validation examples.

E.164 Format

The international standard for phone number formatting is E.164. An E.164 number consists of:

+[country code][subscriber number]
  • Maximum 15 digits total (including country code)
  • Always starts with + followed by the country code
  • No spaces, dashes, or parentheses

Examples

CountryE.164 FormatCountry CodeSubscriber Number
Ghana+233541112259233541112259
Kenya+254722123456254722123456
Nigeria+23480312345672348031234567
Tanzania+255712345678255712345678
South Africa+2782123456727821234567
Mozambique+258841234567258841234567
United Kingdom+447911123456447911123456

API Format Requirements

Version 2 API

The V2 API requires E.164 format with the + prefix:

+233541112259

Version 1 API

The V1 API accepts international format without the + prefix:

233541112259

When migrating from V1 to V2, simply prepend + to all existing phone numbers. See the Migration Guide for more details.

Validation

Basic Validation

Before sending a phone number to the API, perform basic client-side validation:

function isValidE164(phoneNumber) {
  // E.164: + followed by 1-15 digits
  const e164Regex = /^\+[1-9]\d{1,14}$/;
  return e164Regex.test(phoneNumber);
}

// Examples
console.log(isValidE164('+233541112259'));  // true
console.log(isValidE164('233541112259'));   // false (no + prefix)
console.log(isValidE164('+0541112259'));    // false (starts with 0)
console.log(isValidE164('+233'));           // true (valid but too short for Ghana)
import re

def is_valid_e164(phone_number: str) -> bool:
    """Validate E.164 phone number format."""
    pattern = r'^\+[1-9]\d{1,14}$'
    return bool(re.match(pattern, phone_number))

# Examples
print(is_valid_e164('+233541112259'))  # True
print(is_valid_e164('233541112259'))   # False
print(is_valid_e164('+0541112259'))    # False
function isValidE164(string $phoneNumber): bool {
    return preg_match('/^\+[1-9]\d{1,14}$/', $phoneNumber) === 1;
}

// Examples
var_dump(isValidE164('+233541112259'));  // true
var_dump(isValidE164('233541112259'));   // false
var_dump(isValidE164('+0541112259'));    // false

Library-Based Validation

For production use, we recommend the google-libphonenumber library which provides comprehensive phone number parsing, formatting, and validation:

const { PhoneNumberUtil, PhoneNumberFormat } = require('google-libphonenumber');
const phoneUtil = PhoneNumberUtil.getInstance();

function validateAndFormat(phoneNumber, defaultCountry = null) {
  try {
    const parsed = phoneUtil.parse(phoneNumber, defaultCountry);

    if (!phoneUtil.isValidNumber(parsed)) {
      return { valid: false, error: 'Invalid phone number' };
    }

    return {
      valid: true,
      e164: phoneUtil.format(parsed, PhoneNumberFormat.E164),
      country: phoneUtil.getRegionCodeForNumber(parsed),
      countryCode: parsed.getCountryCode(),
    };
  } catch (error) {
    return { valid: false, error: error.message };
  }
}

// Examples
console.log(validateAndFormat('+233541112259'));
// { valid: true, e164: '+233541112259', country: 'GH', countryCode: 233 }

console.log(validateAndFormat('0541112259', 'GH'));
// { valid: true, e164: '+233541112259', country: 'GH', countryCode: 233 }

console.log(validateAndFormat('541112259', 'GH'));
// { valid: true, e164: '+233541112259', country: 'GH', countryCode: 233 }
import phonenumbers

def validate_and_format(phone_number, default_country=None):
    try:
        parsed = phonenumbers.parse(phone_number, default_country)

        if not phonenumbers.is_valid_number(parsed):
            return {'valid': False, 'error': 'Invalid phone number'}

        return {
            'valid': True,
            'e164': phonenumbers.format_number(parsed, phonenumbers.PhoneNumberFormat.E164),
            'country': phonenumbers.region_code_for_number(parsed),
            'country_code': parsed.country_code,
        }
    except phonenumbers.NumberParseException as e:
        return {'valid': False, 'error': str(e)}

# Examples
print(validate_and_format('+233541112259'))
# {'valid': True, 'e164': '+233541112259', 'country': 'GH', 'country_code': 233}

print(validate_and_format('0541112259', 'GH'))
# {'valid': True, 'e164': '+233541112259', 'country': 'GH', 'country_code': 233}

Common Formatting Issues

Local Numbers

Users often enter local numbers without the country code. You should either:

  1. Require E.164 input from the start
  2. Accept local numbers with a country selector and format them server-side
// Convert local Ghanaian number to E.164
function formatGhanaNumber(localNumber) {
  // Remove leading zero if present
  const cleaned = localNumber.replace(/^0/, '');
  return `+233${cleaned}`;
}

formatGhanaNumber('0541112259');  // '+233541112259'
formatGhanaNumber('541112259');   // '+233541112259'

Common Mistakes

InputProblemCorrect Format
0541112259Local format, missing country code+233541112259
00233541112259Uses 00 international prefix instead of ++233541112259
+233 054 111 2259Contains spaces+233541112259
+233-054-111-2259Contains dashes+233541112259
233541112259Missing + prefix (valid for V1, invalid for V2)+233541112259

Supported Countries

Click Airtime supports airtime top-ups to over 150 countries. Use the catalog endpoint to check whether a specific phone number is supported and see available products.

Network Detection: The Click Airtime API automatically detects the mobile network operator (MNO) for each phone number using HLR (Home Location Register) lookup. If a number has been ported to a different network, you can override the detection by specifying the airtimeAccountId in the V2 API.