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 | |
|---|---|---|
| Card / MoMo / wallet payments | Settle via simulate — no card network, no MoMo, no real wallet touched | Real settlement through the real rail |
| Mandates | Activate immediately, no customer approval step | Requires a real card-save or wallet-PIN approval |
| Webhooks | Sent to your test endpoint; payload carries "environment": "test" inside data.payment | Sent to your live endpoint; "environment": "live" |
| Webhook signatures | Verified against your test endpoint’s own signing secret | Verified against your live endpoint’s own signing secret |
| Rate limits | Shared with live — not more permissive | Same budgets |
What stays the same
- Endpoint URLs (
/v1/api/payment-links,/v1/api/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 — card live vs test credentials, 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_* |
Forcing an outcome in test mode
There’s no matrix of magic test card numbers or test phone numbers. Instead, settle a test payment
link directly with simulate and pick the outcome
yourself:
curl -X POST "$SOXARA_BASE/v1/api/payment-links/{id}/simulate" \
-H "Authorization: Bearer $SOXARA_TEST_KEY" \
-d '{"method": "momo", "outcome": "failed"}'See Test with the sandbox for the full rundown, including mandates, sub-merchants, and card/fleet-card redemption in test mode.
Don’t mix environments
A sxm_test_* key’s payments fire your test endpoint’s webhooks, signed with that endpoint’s
own secret — not your live endpoint’s. Register a separate webhook endpoint per environment
and keep the two secrets in distinct env vars (SOXARA_TEST_WEBHOOK_SECRET,
SOXARA_LIVE_WEBHOOK_SECRET); verifying a test delivery against your live secret (or vice versa)
will fail.