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:
{country_code}{subscriber_number}
The country code is required. Leading zeros from local format must be removed.
Country Reference
| Operator | Prefix | Example |
|---|---|---|
| MTN MoMo | 2567XX, 2568XX | 256700123456 |
| Airtel Money | 2567XX, 2575X | 256752123456 |
Local → International:
0700 123 456 → 256700123456 (remove 0, add 256)
+256 700 123 456 → 256700123456 (remove +)
| Operator | Prefix | Example |
|---|---|---|
| Safaricom M-Pesa | 2547XX | 254712345678 |
| Airtel Money | 2547XX | 254733123456 |
Local → International:
0712 345 678 → 254712345678 (remove 0, add 254)
+254 712 345 678 → 254712345678 (remove +)
| Operator | Prefix | Example |
|---|---|---|
| Vodacom M-Pesa | 2557XX | 255712345678 |
| Tigo | 2556XX, 2567XX | 255651234567 |
| Airtel | 2556XX, 2557XX | 255685123456 |
Local → International:
0712 345 678 → 255712345678 (remove 0, add 255)
| Operator | Prefix | Example |
|---|---|---|
| MTN MoMo | 2507XX | 250780123456 |
| Airtel Money | 2507XX | 250720123456 |
Local → International:
0780 123 456 → 250780123456 (remove 0, add 250)
Validation Pattern
RohoPay validates phone numbers server-side. The accepted pattern is:
^(256|254|255|250)[0-9]{7,12}$
- Must start with a supported country code:
256,254,255, or250 - Followed by 7–12 digits
Normalizing Numbers in Code
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"
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:
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "phone: must be a valid international format (256XXXXXXXXX, 254XXXXXXXXX, 255XXXXXXXXX, or 250XXXXXXXXX)"
}
}
