Tupane Sandbox
Tupane

A payment simulation platform for mobile money APIs. Test your integrations without moving real money.

Quick Start

Get up and running in 3 steps:

1

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.

2

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}'
3

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.

POST /sandbox/v1/api-keys Create a new API key

No auth required. The raw_key is returned only once.

FieldTypeRequiredDescription
owner_idstringYesYour app identifier (1-64 chars)
environmentstringNosandbox (default)
labelstringNoHuman-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..."
  }
}
GET /sandbox/v1/api-keys/me Get current key info

Returns details about the currently authenticated API key.

GET /sandbox/v1/api-keys List all keys for owner

Returns all API keys belonging to the authenticated owner.

DEL /sandbox/v1/api-keys/{key_id} Revoke key

Permanently deactivates the key. Must belong to authenticated owner.

Wallets

Virtual mobile money wallets. Balance is computed from an append-only ledger.

POST /sandbox/v1/wallets Create a wallet
FieldTypeRequiredDescription
owner_idstringYesYour app identifier
wallet_typestringNouser, merchant, or system
currencystringNo3-letter code, default UGX
initial_balanceintegerNoStarting balance in minor units
GET /sandbox/v1/wallets List wallets (paginated)

Query params: limit (1-100, default 50), offset (default 0).

GET /sandbox/v1/wallets/{wallet_id} Get wallet + balance

Returns wallet details. Balance is recomputed from ledger on every call.

Payments

Simulate mobile money request-to-pay (collection) flows.

POST /sandbox/v1/payments/request-to-pay Initiate a payment
FieldTypeRequiredDescription
payer_wallet_idstringYesWallet to debit
payee_wallet_idstringYesWallet to credit
amountintegerYesAmount in minor units (> 0)
currencystringNoDefault UGX
descriptionstringNoPayment description (max 256)
idempotency_keystringNoPrevents duplicate processing
// Response 201
{
  "status": "success",
  "data": {
    "id": "01KP6B...",
    "type": "payment",
    "status": "success",
    "amount": 10000,
    "fee": 150,
    "net_amount": 9850,
    "currency": "UGX"
  }
}
GET /sandbox/v1/payments List payments (paginated)

Query params: limit, offset.

GET /sandbox/v1/payments/{payment_id} Get payment details

Returns transaction. Owner-scoped.

Transfers

Wallet-to-wallet money movement.

POST /sandbox/v1/transfers Create a transfer
FieldTypeRequiredDescription
source_wallet_idstringYesWallet to debit
destination_wallet_idstringYesWallet to credit
amountintegerYesAmount in minor units
currencystringNoDefault UGX
descriptionstringNoTransfer description
GET /sandbox/v1/transfers List transfers

Query: limit, offset.

GET /sandbox/v1/transfers/{transfer_id} Get transfer details

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.

POST /sandbox/v1/webhooks/register Register a webhook

Events: payment.success, payment.failed, payment.pending, transfer.completed, transfer.failed

{ "url": "https://myapp.com/webhooks", "events": ["payment.success"] }
GET /sandbox/v1/webhooks/endpoints List endpoints

Returns all active webhook endpoints for your owner.

DEL /sandbox/v1/webhooks/endpoints/{id} Deactivate endpoint

Deactivates the endpoint. No further events will be sent.

GET /sandbox/v1/webhooks/events List webhook events

Query: limit (1-100), offset. Shows delivery status per event.

Simulations

Control sandbox behaviour — inject failures, set fees, add delays.

GET /sandbox/v1/simulations/config Get simulation config

Returns current simulation settings (fees, success rate, delays).

POST /sandbox/v1/simulations/config Update simulation config
{ "mode": "random", "fee_percentage": 2.5, "success_rate": 0.85, "processing_delay_ms": 2000 }
POST /sandbox/v1/simulations/failure-inject Force-fail transaction types
{ "transaction_types": ["payment"] }          // force payments to fail
{ "transaction_types": ["payment","transfer"] } // force all to fail
{ "transaction_types": [] }                     // clear forced failures
POST /sandbox/v1/simulations/delay-config Set processing delay
{ "processing_delay_ms": 3000 }

Sandbox Management

POST /sandbox/v1/reset Reset all sandbox data

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)

No wallets yet

3Make a Payment

4Create a Transfer

5Browse Data

6Sandbox Reset

Wipes all wallets, transactions, ledger entries, webhooks, and simulation configs. API keys are preserved.