Environments
Soxara has two environments — test and live — accessible through the same base URL. Which environment your request lands in is determined by the prefix on your API key, not the URL.
Base URL: https://api.soxara.com
Test key: sxm_test_<random> → test mode (sandbox rails)
Live key: sxm_live_<random> → live mode (real money)This mirrors Stripe’s model. There’s no sandbox.api.soxara.com — you swap one character in your key and you’re in the other environment.
What changes between environments
| Test mode | Live mode | |
|---|---|---|
| Stripe charges | Test mode — no money moves; Stripe’s test cards work | Real cards, real money |
| MTN MoMo | Sandbox API; returns synthetic responses; no MoMo PIN prompt on user phone | Real MTN production API; user gets a real PIN prompt |
| Orange Money | Sandbox API | Live API |
| Soxara wallets | Test-mode merchants can debit test wallets only, never real user wallets | Live wallets, real balances |
| Webhooks | Sent to your test webhook URL; payload has "livemode": false | Sent to your live webhook URL; "livemode": true |
| Webhook signatures | Verified against your test signing secret | Verified against your live signing secret |
| Rate limits | Generous for development | Lower; production-grade |
| Audit trail | Stored separately; doesn’t pollute live reports | Stored in your live business dashboard |
What stays the same
- Endpoint URLs (
/v1/payments,/v1/webhook-endpoints, etc.) - Request/response shapes
- Error codes and the envelope
- Webhook event names and payloads (down to field names)
- Idempotency semantics
So you build once, test against sxm_test_* keys, and ship to production by swapping in your sxm_live_* keys. No code changes, no URL changes, no library swap.
How requests are routed
When the gateway receives a request:
- It reads the
Authorization: Bearer sxm_(live|test)_...header. - The prefix tells it which environment your request runs in. The gateway stamps
X-Soxara-Env: liveorX-Soxara-Env: teston the upstream request. - Downstream services (payments, MoMo, wallet, etc.) read that header and pick the right provider credentials per request — Stripe live key vs test key, MTN production vs sandbox, etc.
- Every transaction row stored in our database carries the env. Test data and live data never mix in reports or webhooks.
Picking the right key to test with
A test merchant account in Soxara can mint both test and live keys. Use them like this:
| Use case | Key |
|---|---|
| Local development | sxm_test_* |
| CI / integration tests | sxm_test_* (with X-Idempotency-Key randomized per test run) |
| Staging environment that hits real customers’ real cards | sxm_live_* (but with a low spending ceiling — talk to support to scope it down) |
| Production | sxm_live_* |
Test cards & test phones
In test mode, use Stripe’s standard test card numbers — they all work the same way they do in Stripe’s docs:
| Card number | Behavior |
|---|---|
4242 4242 4242 4242 | Always succeeds |
4000 0000 0000 0002 | Always declines (generic_decline) |
4000 0000 0000 9995 | Insufficient funds |
4000 0027 6000 3184 | Requires 3DS authentication |
For MoMo in test mode, any well-formed Liberian MSISDN returns a synthetic “approved” response after a 5-second delay. There’s no real PIN prompt.
Don’t mix environments
A sxm_test_* key sent to a production webhook URL will fail signature verification. Likewise a sxm_live_* key against a test signing secret. Keep your sandbox and production webhook URLs and signing secrets separate — store them as distinct env vars in your app (SOXARA_TEST_WEBHOOK_SECRET, SOXARA_LIVE_WEBHOOK_SECRET).