Mobile Number Format

The mobile number contract for mobile money payments and payouts

The mobile number is the account identifier for every mobile money payment and payout. Validate and normalise it before submission; a malformed number is rejected at the operator, after the transaction has been created.


The contract

Submit a country and a mobile number in canonical E.164 form.

Country: ISO 3166-1 alpha-3 KEN
Number: canonical E.164 +254721755042
FlowCountry fieldNumber field
Collect — mobile moneypayerDetails.location on the sessionpaymentDetails.payerMobileNumber
Payout — mobile walletrecipient.countryrecipient.phoneNumber
Account validationcountryaccountIdentifier

The country is required. It supplies the parsing context for locally formatted input and determines how the national number converts to international form. A number that resolves to a country other than the one supplied is invalid.

The leading + is optional on submission — CrissCross accepts +254721755042 and 254721755042 identically. Some examples elsewhere in these docs omit it. Normalise to the + form on your side regardless, so that a single canonical value is stored, logged, and reconciled.


Validation rules

1. Require both fields. Neither the number nor the country may be omitted, and neither may be inferred from the other.

2. Accept common input formats. In your own interface, accept:

FormExample
International E.164+254721755042
International without +254721755042
National0721755042

Spaces, hyphens, parentheses, dots, and slashes may be accepted as separators and stripped on submission.

3. Parse with a maintained numbering-plan library. Use libphonenumber or an equivalent binding — libphonenumber-js, google-libphonenumber, phonenumbers — with the selected country supplied as the parsing context. National numbering plans change as ranges are allocated and reassigned; the metadata must be updatable. A hand-written regular expression is not a sufficient validator.

4. Require isValid(), not isPossible(). isPossible() checks length only. isValid() checks the number against the country’s national numbering plan.

5. Require a mobile-capable number type. Where the library reports a type, accept MOBILE and FIXED_LINE_OR_MOBILE and reject all others. FIXED_LINE_OR_MOBILE is returned in countries whose numbering plans do not separate the two and is not an error.

6. Verify the canonical output. Take the library’s E.164 output and confirm it matches:

^\+[1-9]\d{7,14}$

One leading +, a non-zero first digit, 15 digits maximum. No separators, extensions, short codes, or service codes.

7. Confirm the country matches. Compare the parsed country against the country supplied. Reject a mismatch.

country = KEN, number = +233541234567 invalid
country = KEN, number = +254721755042 valid

Length does not establish country. An international-format number is not valid for a given country merely because its total digit count is plausible.

8. Reject ambiguous input. Letters, extensions, short codes, empty values, and over-long numbers are errors. An unprefixed number is only international if it begins with the calling code for the supplied country.


The trunk-zero exception

Unconditionally stripping the leading zero from a national number is incorrect.

In most markets the leading 0 is a trunk prefix and is dropped when the calling code is applied. In Côte d’Ivoire, Benin, and Gabon it is part of the national significant number and is retained.

CountryCalling codeNational inputCanonical E.164
Côte d’Ivoire2250700000000+2250700000000
Benin2290100000000+2290100000000
Gabon24106000000+24106000000

Contrast with trunk-prefix markets:

CountryCalling codeNational inputCanonical E.164
Kenya2540721755042+254721755042
Ghana2330541234567+233541234567
Nigeria23408012345678+2348012345678

A numbering-plan library applies this distinction automatically. A custom normaliser must encode and maintain the exception list, which expands as markets are added.


Country calling codes

Markets where CrissCross supports mobile money:

CountryISO alpha-3Calling codeLeading national 0
BeninBEN229Significant — retain
Burkina FasoBFA226Not used
CameroonCMR237Not used
Côte d’IvoireCIV225Significant — retain
EthiopiaETH251Trunk prefix — drop
GabonGAB241Significant — retain
GhanaGHA233Trunk prefix — drop
KenyaKEN254Trunk prefix — drop
NigeriaNGA234Trunk prefix — drop
RwandaRWA250Trunk prefix — drop
SenegalSEN221Not used
Sierra LeoneSLE232Trunk prefix — drop
TanzaniaTZA255Trunk prefix — drop
TogoTGO228Not used
UgandaUGA256Trunk prefix — drop
ZambiaZMB260Trunk prefix — drop

Not used indicates national numbers are not written with a leading zero.

See Supported Destinations for live rails per market and the per-country pages for available operators.


Format rules enforced by CrissCross

CrissCross applies a format check before a mobile money transaction reaches the operator. Two markets have explicit rules; a number that fails is rejected before submission to the provider.

Kenya

^\+?254[17]\d{8}$

Twelve digits excluding +, calling code 254, national number beginning 7 or 1. Local forms such as 0712345678 must already be in international form; this check does not convert them. The 2542…, 2543…, 2546…, and 2549… ranges are rejected.

Ghana

^\+?233[25]\d{8}$

Twelve digits excluding +, calling code 233, national number beginning 2 or 5. The 03… landline range is rejected.

Both rules validate the full mobile range rather than binding prefixes to individual operators. Mobile number portability means a prefix does not identify a carrier, and prefix-to-carrier tables produce false rejections as ranges are reallocated. Do not use a carrier-prefix list as a primary validator.


Format validation is not account validation

A well-formed number is not necessarily in service, registered to the expected holder, enrolled for mobile money, or held at the selected operator.

Use account validationPOST /v1/accounts/validate with accountType: mobile_money — to confirm the account against the provider and retrieve the account holder name where the operator exposes it. See Verification Sandbox Testing for sandbox usage.

POST /v1/verification/mobile is deprecated. Use /v1/accounts/validate. See Mobile Number Verification.


Provider-specific formatting

Operators require the number in differing shapes — international digits without +, national 0… form, or the calling code stripped. CrissCross performs this translation per connector.

Submit canonical E.164 in all cases. Do not pre-format for a specific operator or reproduce a format taken from a provider’s own documentation; routing may change without notice to the integration.


Reference algorithm

validateMobileNumber(rawNumber, countryAlpha3):
1. Reject if rawNumber or countryAlpha3 is absent.
2. Convert countryAlpha3 (KEN) to the alpha-2 code the
numbering library expects (KE).
3. parsed = parse(rawNumber, alpha2)
4. Reject if parsing fails.
5. Reject unless parsed.isValid().
6. Reject unless parsed.country == alpha2.
7. Where a number type is available, reject unless it is
MOBILE or FIXED_LINE_OR_MOBILE.
8. e164 = parsed.number
9. Reject unless e164 matches ^\+[1-9]\d{7,14}$
10. Submit e164 with countryAlpha3.
11. Where beneficiary confirmation is required, call
/v1/accounts/validate.

Next steps