Verification Sandbox Testing

Test account validation scenarios for bank and mobile money in the sandbox

The sandbox environment lets you exercise account verification without calling real providers. A deterministic sandbox provider resolves every request based on the last digit of the account identifier (bank account number or mobile-money number), so you can reproduce each outcome — verified, name mismatch, not found, and the asynchronous pending flow — on demand.

All examples use the current, unified verification endpoint POST /accounts/validate (poll with GET /accounts/validate/{id}). The older /verification/mobile and /verification/bank-account endpoints are deprecated — see Mobile Number Verification and Bank Account Verification.

Sandbox verification is available for both mobile_money and bank_account account types across Kenya (KEN), Rwanda (RWA), Ghana (GHA) and Tanzania (TZA). The same last-digit rules apply to every market and both account types.

How scenarios are triggered

Set the last digit of accountIdentifier to the scenario you want:

Last digitResulting statusBehaviour
3not_foundNo account exists for the identifier. failureReason is populated; no name is returned.
5name_mismatchThe provider returns a minor permutation of the accountHolderName you supplied.
7pendingThe provider is still resolving. Poll GET /accounts/validate/{id}; the sandbox validation settles on pending (it does not flip to verified).
9name_mismatchThe provider returns a different name (drawn from a fixed lookup, deterministic per identifier).
0,1,2,4,6,8verifiedThe account is valid. accountHolderName you supplied is echoed back; if you supply none, a deterministic name is generated.

Default behaviour: any identifier whose last digit is not 3, 5, 7 or 9 resolves to verified.

Mobile Number Verification

Send accountType: mobile_money and put the recipient’s mobile number in accountIdentifier. bankCode is not required for mobile money.

Example: Verified (Kenya)

1{
2 "merchantId": "123e4567-e89b-12d3-a456-426614174000",
3 "country": "KEN",
4 "accountType": "mobile_money",
5 "accountIdentifier": "254712345670",
6 "accountHolderName": "Jane Doe"
7}

Response (200 OK):

1{
2 "id": "018f4a1b-2c3d-7e4f-8a9b-0c1d2e3f4a5b",
3 "status": "verified",
4 "accountHolderName": "Jane Doe",
5 "provider": "sandbox"
6}

Example: Name mismatch (Ghana)

1{
2 "merchantId": "123e4567-e89b-12d3-a456-426614174000",
3 "country": "GHA",
4 "accountType": "mobile_money",
5 "accountIdentifier": "233241234569",
6 "accountHolderName": "Jane Doe"
7}

Response (200 OK):

1{
2 "id": "018f4a1b-2c3d-7e4f-8a9b-0c1d2e3f4a5c",
3 "status": "name_mismatch",
4 "accountHolderName": "Kwame Mensah",
5 "provider": "sandbox",
6 "failureReason": "Sandbox name mismatch scenario (suffix-9)"
7}

Test numbers by country

Change the final digit to select the scenario (see the table above). The prefixes below are representative sandbox numbers; only the last digit is significant.

CountryExample identifierVerified (0)Not found (3)Pending (7)
Kenya (KEN)2547123456X0254712345670254712345673254712345677
Rwanda (RWA)2507881234X0250788123450250788123453250788123457
Ghana (GHA)2332412345X0233241234560233241234563233241234567
Tanzania (TZA)2557123456X0255712345670255712345673255712345677

Bank Account Verification

Send accountType: bank_account, put the account number in accountIdentifier, and include bankCode. In sandbox the bankCode is not validated against a real institution, so any non-empty value works.

Example: Verified (Tanzania)

1{
2 "merchantId": "123e4567-e89b-12d3-a456-426614174000",
3 "country": "TZA",
4 "accountType": "bank_account",
5 "accountIdentifier": "0100200300400",
6 "bankCode": "TZ-CRDB",
7 "accountHolderName": "Amina Juma"
8}

Response (200 OK):

1{
2 "id": "018f4a1b-2c3d-7e4f-8a9b-0c1d2e3f4a5d",
3 "status": "verified",
4 "accountHolderName": "Amina Juma",
5 "provider": "sandbox"
6}

Example: Account not found (Kenya)

1{
2 "merchantId": "123e4567-e89b-12d3-a456-426614174000",
3 "country": "KEN",
4 "accountType": "bank_account",
5 "accountIdentifier": "0100200300403",
6 "bankCode": "KE-EQUITY"
7}

Response (200 OK):

1{
2 "id": "018f4a1b-2c3d-7e4f-8a9b-0c1d2e3f4a5e",
3 "status": "not_found",
4 "provider": "sandbox",
5 "failureReason": "Sandbox account-not-found scenario (suffix-3)"
6}

Test account numbers by country

Only the last digit is significant; use any bankCode.

CountryExample bankCodeVerified (0)Name mismatch (5)Not found (3)
Kenya (KEN)KE-EQUITY010020030040001002003004050100200300403
Rwanda (RWA)RW-BK010020030040001002003004050100200300403
Ghana (GHA)GH-STANBIC010020030040001002003004050100200300403
Tanzania (TZA)TZ-CRDB010020030040001002003004050100200300403

Polling pending validations

Any identifier ending in 7 returns status: pending with an id. Poll until you observe the terminal state:

$curl https://api.crisscross.money/v1/accounts/validate/018f4a1b-2c3d-7e4f-8a9b-0c1d2e3f4a5b \
> -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Because the sandbox provider is stateless, a pending scenario stays pending — it is intended to let you exercise the poll loop and your handling of the asynchronous case, not to simulate an eventual success.

Important notes

  • Sandbox only. These rules apply only in the sandbox. Production validation uses real account numbers/phone numbers and real providers.
  • Deterministic. The same identifier always produces the same result (including the generated name for the 5/9 mismatch scenarios), so results are stable across retries and consistent with the validation cache.
  • Name matching. Supply accountHolderName to exercise the name_mismatch branch. Without it, a 5/9 identifier still returns name_mismatch using a generated name.
  • Country codes. Use 3-letter ISO country codes in country (KEN, RWA, GHA, TZA) — these are country codes, not currency codes.

Next steps