> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.crisscross.money/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.crisscross.money/_mcp/server.

# Mobile Number Format

> Canonical E.164 format, country-aware normalisation, the trunk-zero exception, per-country calling codes, and the format rules CrissCross enforces.

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.

```text
Country: ISO 3166-1 alpha-3   KEN
Number:  canonical E.164      +254721755042
```

| Flow                   | Country field                          | Number field                       |
| ---------------------- | -------------------------------------- | ---------------------------------- |
| Collect — mobile money | `payerDetails.location` on the session | `paymentDetails.payerMobileNumber` |
| Payout — mobile wallet | `recipient.country`                    | `recipient.phoneNumber`            |
| Account validation     | `country`                              | `accountIdentifier`                |

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:

| Form                      | Example         |
| ------------------------- | --------------- |
| International E.164       | `+254721755042` |
| International without `+` | `254721755042`  |
| National                  | `0721755042`    |

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:

```regex
^\+[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.

```text
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, Gabon, Burkina Faso, and the Republic of the Congo it is part of the national significant number and is retained.

| Country               | Calling code | National input | Canonical E.164  |
| --------------------- | ------------ | -------------- | ---------------- |
| Côte d'Ivoire         | `225`        | `0700000000`   | `+2250700000000` |
| Benin                 | `229`        | `0100000000`   | `+2290100000000` |
| Gabon                 | `241`        | `06000000`     | `+24106000000`   |
| Burkina Faso          | `226`        | `01000000`     | `+22601000000`   |
| Republic of the Congo | `242`        | `061234567`    | `+242061234567`  |

Contrast with trunk-prefix markets:

| Country | Calling code | National input | Canonical E.164  |
| ------- | ------------ | -------------- | ---------------- |
| Kenya   | `254`        | `0721755042`   | `+254721755042`  |
| Ghana   | `233`        | `0541234567`   | `+233541234567`  |
| Nigeria | `234`        | `08012345678`  | `+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:

| Country                          | ISO alpha-3 | Calling code | Leading national `0`     |
| -------------------------------- | ----------- | ------------ | ------------------------ |
| Benin                            | `BEN`       | `229`        | **Significant — retain** |
| Burkina Faso                     | `BFA`       | `226`        | **Significant — retain** |
| Cameroon                         | `CMR`       | `237`        | Not used                 |
| Republic of the Congo            | `COG`       | `242`        | **Significant — retain** |
| Côte d'Ivoire                    | `CIV`       | `225`        | **Significant — retain** |
| Democratic Republic of the Congo | `COD`       | `243`        | Trunk prefix — drop      |
| Ethiopia                         | `ETH`       | `251`        | Trunk prefix — drop      |
| Gabon                            | `GAB`       | `241`        | **Significant — retain** |
| Ghana                            | `GHA`       | `233`        | Trunk prefix — drop      |
| Kenya                            | `KEN`       | `254`        | Trunk prefix — drop      |
| Malawi                           | `MWI`       | `265`        | Trunk prefix — drop      |
| Mozambique                       | `MOZ`       | `258`        | Not used                 |
| Nigeria                          | `NGA`       | `234`        | Trunk prefix — drop      |
| Rwanda                           | `RWA`       | `250`        | Trunk prefix — drop      |
| Senegal                          | `SEN`       | `221`        | Not used                 |
| Sierra Leone                     | `SLE`       | `232`        | Trunk prefix — drop      |
| Tanzania                         | `TZA`       | `255`        | Trunk prefix — drop      |
| Togo                             | `TGO`       | `228`        | Not used                 |
| Uganda                           | `UGA`       | `256`        | Trunk prefix — drop      |
| Zambia                           | `ZMB`       | `260`        | Trunk prefix — drop      |

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

See [Supported Destinations](/payout-supported-destinations) for live rails per market and the [per-country pages](/payment-method-mobile-money#supported-countries) 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

```regex
^\+?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

```regex
^\+?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 validation](/api-reference/payouts/verification) — `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](/payout-verification-sandbox-testing) for sandbox usage.

> **Note**
>
> `POST /v1/verification/mobile` is deprecated. Use `/v1/accounts/validate`. See [Mobile Number Verification](/payout-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

```text
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

* [Mobile Money](/payment-method-mobile-money) — payment flow, per-country operators, sandbox test numbers
* [Mobile Wallet Payouts](/payout-mobile-wallet) — payouts to mobile money wallets
* [Supported Destinations](/payout-supported-destinations) — currencies, countries, and rails
* [Conventions](/conventions) — identifiers, idempotency, pagination, and error shapes