Phone Number Formats

How to format mobile numbers for each supported country.

Format Rules

All phone numbers must be in E.164 format without the leading + sign:

output.txtText
{country_code}{subscriber_number}

The country code is required. Leading zeros from local format must be removed.

Country Reference

OperatorPrefixExample
MTN MoMo2567XX, 2568XX256700123456
Airtel Money2567XX, 2575X256752123456

Local → International:

output.txtText
0700 123 456  →  256700123456   (remove 0, add 256)
+256 700 123 456  →  256700123456   (remove +)
OperatorPrefixExample
Safaricom M-Pesa2547XX254712345678
Airtel Money2547XX254733123456

Local → International:

output.txtText
0712 345 678  →  254712345678   (remove 0, add 254)
+254 712 345 678  →  254712345678  (remove +)
OperatorPrefixExample
Vodacom M-Pesa2557XX255712345678
Tigo2556XX, 2567XX255651234567
Airtel2556XX, 2557XX255685123456

Local → International:

output.txtText
0712 345 678  →  255712345678   (remove 0, add 255)
OperatorPrefixExample
MTN MoMo2507XX250780123456
Airtel Money2507XX250720123456

Local → International:

output.txtText
0780 123 456  →  250780123456   (remove 0, add 250)

Validation Pattern

RohoPay validates phone numbers server-side. The accepted pattern is:

pattern.regexRegex
^(256|254|255|250)[0-9]{7,12}$
  • Must start with a supported country code: 256, 254, 255, or 250
  • Followed by 7–12 digits

Normalizing Numbers in Code

TypeScriptTypeScript
function normalizePhone(raw: string, defaultCountryCode = "256"): string {
  // Strip all non-digit characters
  let digits = raw.replace(/\D/g, "");

  // Handle +XXX format
  if (raw.startsWith("+")) {
    return digits; // already has country code
  }

  // Handle local format starting with 0
  if (digits.startsWith("0")) {
    digits = digits.slice(1);
  }

  // Prepend country code if not already present
  const supported = ["256", "254", "255", "250"];
  for (const code of supported) {
    if (digits.startsWith(code)) return digits;
  }

  return defaultCountryCode + digits;
}

// Examples:
normalizePhone("0700 123 456", "256");   // → "256700123456"
normalizePhone("+254712345678");          // → "254712345678"
normalizePhone("256700123456");           // → "256700123456"
PythonPython
import re

SUPPORTED_CODES = ["256", "254", "255", "250"]

def normalize_phone(raw: str, default_country_code: str = "256") -> str:
    digits = re.sub(r"\D", "", raw)
    
    if raw.startswith("+"):
        return digits
    
    if digits.startswith("0"):
        digits = digits[1:]
    
    for code in SUPPORTED_CODES:
        if digits.startswith(code):
            return digits
    
    return default_country_code + digits

Test Numbers

In test mode (with a test_ key), use Iotec's sandbox numbers to simulate payments. The last digit selects the outcome. Both the short form (0111...) and the 256 country-prefix form (256111...) are accepted; the public hosted checkout requires the 256 prefix.

Phone (short)Phone (256)Outcome
011177777(0-9)25611177777(0-9)✅ Success
011177799(0-9)25611177799(0-9)❌ Failed
011177778(0-9)25611177778(0-9)⏳ Pending
011177779(0-9)25611177779(0-9)🔄 SentToVendor

Example: 256111777771 (success) or 0111777995 (failed).

💡

Test numbers only work with test_ API keys. In live mode, phone numbers must be real international-format numbers starting with 256, 254, 255, or 250.

Validation Errors

If you send an invalid phone number, you receive:

response.jsonJSON
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "phone: must be a valid international format (256XXXXXXXXX, 254XXXXXXXXX, 255XXXXXXXXX, or 250XXXXXXXXX)"
  }
}