Test mode
Every workspace has two sets of keys: one for production and one for testing. Same API, same routes, same payment page. With a test key, no aggregator is called and no money moves: you build and verify your integration before your identity is even verified.
The two sets of keys
Section titled “The two sets of keys”| Production | Test | Role |
|---|---|---|
af_live_pub_... |
af_test_pub_... |
Public key (widget, SoftPay): create a session and read its status |
af_live_sec_... |
af_test_sec_... |
Secret key (server): everything else, and the signing of webhooks |
Test keys live in API and Logs, below the production keys, and are rotated separately. Until your identity is verified, your workspace stays in sandbox and only test keys exist: a production key would answer 403 with the code identity_unverified. Once verified, production keys appear and the Sandbox switch unlocks.
What happens with a test key
Section titled “What happens with a test key”- You create a session as usual. The response carries
"livemode": false. - The payment page shows a “Test mode” banner and, once the method and phone number are chosen, offers two buttons: simulate a successful payment or simulate a failure. If the workspace has no gateway yet, a placeholder method “Mobile Money (test)” is offered so the flow can be completed.
- The transaction moves to
SUCCESSorFAILEDwithprovider: "sandbox", and your webhook receivespayment.completedorpayment.failedexactly as in production, with"livemode": false.
curl -X POST https://cartflox.com/api/v1/checkout/sessions \ -H "Authorization: Bearer af_test_sec_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "amount": 5000, "currency": "XOF", "customer_email": "test@example.com" }'{ "id": "cmu8a1b2c0001xyz", "object": "checkout.session", "url": "https://checkout.cartflox.com/cmu8a1b2c0001xyz", "order_id": "CS-MU8A1B-2C0X1", "amount": 5000, "currency": "XOF", "status": "pending", "livemode": false, "created": "2026-09-19T08:00:00.000Z"}Simulate the outcome without opening the page
Section titled “Simulate the outcome without opening the page”For automated tests, the outcome can also be triggered through the API, without a key: the session identifier, which cannot be guessed, is enough.
/api/checkout/sandboxSettle a test paymentcurl -X POST https://cartflox.com/api/checkout/sandbox \ -H "Content-Type: application/json" \ -d '{ "transactionId": "cmu8a1b2c0001xyz", "issue": "succes" }'issue is succes or echec. The route rejects a production transaction (HTTP 403) and a transaction that is already settled (HTTP 409).
Test webhooks
Section titled “Test webhooks”Test events go to your production address, with livemode: false, unless you register a separate test address:
curl -X PATCH https://cartflox.com/api/v1/config/webhook \ -H "Authorization: Bearer af_test_sec_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "webhookUrl": "https://staging.mystore.com/webhooks/cartflox", "mode": "test" }'The signature of a test event is computed with your test secret key. Verify the signature with the key of the same world as the event (livemode).
Isolated data
Section titled “Isolated data”- Test payments never appear in your production lists, statistics, exports or notifications. A test key only reads test sessions, and the other way round.
- To see them in the dashboard: the “Sandbox” switch at the top of the page. It never blocks your real payments: the keys decide the world of a payment. A workspace whose identity is not verified yet stays in sandbox, switch locked.
- Test transactions are deleted after 90 days.
Limits of test mode
Section titled “Limits of test mode”| Not available | Why |
|---|---|
Money transfers (POST /v1/transfers) |
They move money out: HTTP 403, code test_mode. |
Payment links (POST /v1/payment-links) |
A link lives in production. Create a test session instead. |
| Real bank card | The card form is not mounted in test mode: simulate the outcome. |