> 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.

# Testing Overview

> How the CrissCross sandbox works, how test scenarios are triggered, and how to work through testing an integration before going live.

Every CrissCross integration is tested in the sandbox before it processes real money. The sandbox runs on the same endpoints as production and behaves the same way from your code's point of view — but no prompt reaches a real handset, no operator is contacted, and no funds move.

This section is the testing plan: which endpoints to call, what data to send to produce a given outcome, and what you should see back. Start with the "Your First" page for each product you use, then work through the scenarios that apply to you — they're grouped by flow rather than by error code, because the flow is what changes the calls you make. Afterwards it doubles as a reference you can dip into for a single scenario.

### Which parts you need

Collect, Payouts and Exchange can each be used on their own, so you only need to test the ones you use:

| If you…                                                               | Test     | Start with                                         |
| --------------------------------------------------------------------- | -------- | -------------------------------------------------- |
| Take payments from customers                                          | Collect  | [Your First Payment](/testing-first-payment)       |
| Send money to third parties — suppliers, customers, employees         | Payouts  | [Your First Payout](/testing-first-payout)         |
| Convert between currencies or stablecoins                             | Exchange | [Your First Trade](/testing-first-trade)           |
| Withdraw your own Exchange balance to your own bank account or wallet | Exchange | [Your First Withdrawal](/testing-first-withdrawal) |

If you use more than one, test each. For example, if you collect in one currency and convert to another before paying out, run the Collect, Exchange and Payouts tests. If you only collect and CrissCross settles to you on a fixed schedule, you don't need to test withdrawals at all.

Every product finishes at [Going Live](/testing-going-live).

### Before you start

You will need:

* Sandbox `client_id`, `client_secret` and, for Collect and Payouts, `merchantId`.
* Network access to `https://api.crisscross.money`.
* An HTTPS endpoint for webhooks. You can complete the first test without one by polling, but every scenario after that is easier to observe with webhooks running. See [Webhooks](/core-concepts-webhooks).

### How the sandbox works

There is **no separate sandbox URL**. Every request goes to `https://api.crisscross.money`, and your credentials decide the environment — a sandbox `client_id` and `client_secret` put you in the sandbox, production credentials put you in production. This means the only difference between your test and live integration is which secret you load.

Sandbox is enabled by default on every test merchant account. You will have been given a sandbox `client_id`, `client_secret` and `merchantId` during onboarding, alongside the production set.

Exchange works the same way. The one difference is that your sandbox Exchange balances start at zero, and your account manager funds them. See [Exchange Sandbox](/exchange-sandbox).

> **Warning**
>
> Because the URL is identical, a misconfigured secret is the difference between a test and a real payment. Keep the two credential sets in separate secret stores, and never fall back to production credentials when a sandbox call fails.

### How scenarios are triggered

Sandbox outcomes are **deterministic** — you choose what happens, by the value you put in one field:

| What you are testing    | Field                              | How it matches                        | Example        | Full list                                                            |
| ----------------------- | ---------------------------------- | ------------------------------------- | -------------- | -------------------------------------------------------------------- |
| Collect — mobile money  | `paymentDetails.payerMobileNumber` | The whole number, normalised to E.164 | `0970000005`   | [Mobile Money Trigger Numbers](/testing-trigger-numbers)             |
| Payouts — mobile money  | `recipient.phoneNumber`            | Last two digits                       | `254723993112` | [Payout Trigger Endings](/payout-sandbox-testing)                    |
| Payouts — bank transfer | `recipient.accountNumber`          | Last two digits                       | `0123456712`   | [Payout Trigger Endings](/payout-sandbox-testing)                    |
| Account validation      | The account number validated       | Last two digits                       | `0123456712`   | [Verification Sandbox Testing](/payout-verification-sandbox-testing) |

Anything not listed succeeds, so you reach for a trigger deliberately — and conversely, randomly generated payout test data can land on a trigger ending by accident.

Methods with no trigger table test against the provider's own environment instead: same calls, test data from your solutions engineer.

Exchange has no trigger values. Trades and withdrawals succeed in the sandbox, and you test failures by setting up the state that causes them — an expired quote, a balance that's too low, a beneficiary that isn't active yet. See [Your First Trade](/testing-first-trade#then-try-the-failures). Failures that come from outside your request, such as a withdrawal returned by the bank, can't be produced in the sandbox yet.

### What the sandbox does not prove

The sandbox tests your integration, not the market. Operator prompts and timeouts, payer limits, settlement timing and name matching all vary by market and only show up live. For Exchange, so do real deposit crediting times and the document-based compliance review of fiat beneficiaries. Before launching a market, your solutions engineer runs a small-value live pass with you on production credentials. See [Going Live](/testing-going-live).