A payment simulation platform for mobile money APIs. Test your integrations without moving real money.
Quick Start
Get up and running in 3 steps:
Get an API Key
No signup needed. Just create a key:
curl -X POST http://localhost:8000/sandbox/v1/api-keys \
-H "Content-Type: application/json" \
-d '{"owner_id": "my_app", "label": "Dev Key"}'
Save the raw_key — it is shown only once.
Create Wallets
curl -X POST http://localhost:8000/sandbox/v1/wallets \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_KEY" \
-d '{"owner_id":"my_app","wallet_type":"user","currency":"UGX","initial_balance":500000}'
Make a Payment
curl -X POST http://localhost:8000/sandbox/v1/payments/request-to-pay \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_KEY" \
-d '{
"payer_wallet_id": "PAYER_WALLET_ID",
"payee_wallet_id": "PAYEE_WALLET_ID",
"amount": 10000,
"currency": "UGX",
"description": "Test payment"
}'
Authentication
All endpoints (except API key creation) require the X-API-Key header:
X-API-Key: sk_sandbox_xxxxxxxxxxxx...
Keys are scoped by owner_id — each owner sees only their own data.
Response Format
{
"status": "success", // "success" | "failed" | "pending"
"data": { ... }, // resource or null on error
"message": "Human-readable"
}
Paginated list responses also include total, limit, offset.
API Keys
Create and manage API keys for sandbox access.
No auth required. The raw_key is returned only once.
| Field | Type | Required | Description |
|---|---|---|---|
owner_id | string | Yes | Your app identifier (1-64 chars) |
environment | string | No | sandbox (default) |
label | string | No | Human-friendly label |
// Response 201
{
"status": "success",
"data": {
"id": "01KP69ZR37...",
"key_prefix": "sk_sandbox_0",
"owner_id": "my_app",
"label": "Dev Key",
"active": true,
"created_at": "2026-04-14T15:33:01Z",
"raw_key": "sk_sandbox_06955d6ef821..."
}
}
Returns details about the currently authenticated API key.
Returns all API keys belonging to the authenticated owner.
Permanently deactivates the key. Must belong to authenticated owner.
Wallets
Virtual mobile money wallets. Balance is computed from an append-only ledger.
| Field | Type | Required | Description |
|---|---|---|---|
owner_id | string | Yes | Your app identifier |
wallet_type | string | No | user, merchant, or system |
currency | string | No | 3-letter code, default UGX |
initial_balance | integer | No | Starting balance in minor units |
Query params: limit (1-100, default 50), offset (default 0).
Returns wallet details. Balance is recomputed from ledger on every call.
Payments
Simulate mobile money request-to-pay (collection) flows.
| Field | Type | Required | Description |
|---|---|---|---|
payer_wallet_id | string | Yes | Wallet to debit |
payee_wallet_id | string | Yes | Wallet to credit |
amount | integer | Yes | Amount in minor units (> 0) |
currency | string | No | Default UGX |
description | string | No | Payment description (max 256) |
idempotency_key | string | No | Prevents duplicate processing |
// Response 201
{
"status": "success",
"data": {
"id": "01KP6B...",
"type": "payment",
"status": "success",
"amount": 10000,
"fee": 150,
"net_amount": 9850,
"currency": "UGX"
}
}
Query params: limit, offset.
Returns transaction. Owner-scoped.
Transfers
Wallet-to-wallet money movement.
| Field | Type | Required | Description |
|---|---|---|---|
source_wallet_id | string | Yes | Wallet to debit |
destination_wallet_id | string | Yes | Wallet to credit |
amount | integer | Yes | Amount in minor units |
currency | string | No | Default UGX |
description | string | No | Transfer description |
Query: limit, offset.
Returns transfer by ID. Owner-scoped.
Webhooks
Subscribe to real-time event notifications. Events are signed with HMAC-SHA256.
Payloads include X-Tupane-Signature. Use the secret returned on registration to verify.
Events: payment.success, payment.failed, payment.pending, transfer.completed, transfer.failed
{ "url": "https://myapp.com/webhooks", "events": ["payment.success"] }
Returns all active webhook endpoints for your owner.
Deactivates the endpoint. No further events will be sent.
Query: limit (1-100), offset. Shows delivery status per event.
Simulations
Control sandbox behaviour — inject failures, set fees, add delays.
Returns current simulation settings (fees, success rate, delays).
{ "mode": "random", "fee_percentage": 2.5, "success_rate": 0.85, "processing_delay_ms": 2000 }
{ "transaction_types": ["payment"] } // force payments to fail
{ "transaction_types": ["payment","transfer"] } // force all to fail
{ "transaction_types": [] } // clear forced failures
{ "processing_delay_ms": 3000 }
Sandbox Management
Deletes all wallets, transactions, ledger entries, webhooks, and simulation configs. API keys are preserved.
// Response
{
"status": "success",
"data": { "ledger_entries": 12, "transactions": 6, "wallets": 2, "webhook_endpoints": 1 },
"message": "Sandbox data reset successfully. API keys were preserved."
}
API Console
Test endpoints live. HTTP status and response time shown inline.
1Create an API Key
🔑 Your API Key
All steps below require a valid API key.
2Create a Wallet
Created Wallets (click ID to copy)
3Make a Payment
4Create a Transfer
5Browse Data
6Sandbox Reset
Wipes all wallets, transactions, ledger entries, webhooks, and simulation configs. API keys are preserved.