Mobile Number Format
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.
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:
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:
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.
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.
Contrast with trunk-prefix markets:
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:
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
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
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 validation — POST /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
Next steps
- Mobile Money — payment flow, per-country operators, sandbox test numbers
- Mobile Wallet Payouts — payouts to mobile money wallets
- Supported Destinations — currencies, countries, and rails
- Conventions — identifiers, idempotency, pagination, and error shapes