Testing is crucial for ensuring your integration works correctly before going live. HOST Pay provides a complete Test Mode environment that mirrors production functionality without processing real money.
In Test Mode, the outcome of a mobile-money deposit is driven by the
user’s phone number — no second API call needed. Create a user with one of
these numbers, then any deposit into that user’s wallet resolves deterministically
(the wallet is credited/failed and your webhook fires, just like production):
⏳ Stays pending (for testing the async completion path)
any other
✅ Completes
For payouts (/transactions/wallet/mobile-money-cashout/), the same magic
numbers apply to the recipient phone_number in the request — so you can
trigger a decline per-transaction without pre-configuring a user:
Recipient phone
Payout outcome
+23299000002
❌ Declined — wallet not debited, request returns 400
Test Mode payouts settle immediately, so there is no merchant-controlled
“pending” payout — only +23299000002 changes the outcome (a decline); every
other number completes.
For the +23299000009 (pending) case, or to complete a pending deposit
manually, call the completion endpoint directly:
This endpoint is available in every environment (including the hosted
sandbox) but only accepts Test Mode credentials — a Live Mode key is
rejected with 403. Magic numbers and this endpoint never affect Live Mode.
# Card deposit exampledeposit = client.deposits.card( wallet_id="wallet_test_abc123", amount=100.00,)# Complete the payment client-side with a Stripe test card (e.g. 4242...)
from hostpay import HostPayclient = HostPay( api_key="test_ak_1234567890", secret_key="test_sk_0987654321",)# 1. Create user (app_user_id, name, phone_number are required).# +23299000001 is the magic number whose deposits always complete.user = client.users.create( app_user_id="user_123", name="Test User", email="test@example.com", phone_number="+23299000001",)print(f"Created user: {user['id']}")# 2. Create the user's wallet (wallets are not auto-created)wallet = client.wallets.create(user["id"])print(f"Created wallet: {wallet['id']}, Balance: {wallet['balance']}")# 3. Make a deposit. In Test Mode this auto-completes (magic number),# so the wallet is credited right away.deposit = client.deposits.mobile_money(wallet_id=wallet["id"], amount=100)print(f"Deposit completed: {deposit['transaction_id']}")# 4. Check balancebalance = client.wallets.balance(wallet["id"])print(f"Balance: {balance['balance']}")
from decimal import Decimal# Create two users (magic number: deposits auto-complete in Test Mode)alice = client.users.create( app_user_id="alice_1", name="Alice", username="alice", email="alice@example.com", phone_number="+23299000001",)bob = client.users.create( app_user_id="bob_1", name="Bob", username="bob", email="bob@example.com", phone_number="+23299000001",)# Create their walletswallet1 = client.wallets.create(alice["id"])wallet2 = client.wallets.create(bob["id"])# Fund Alice's walletclient.deposits.mobile_money(wallet_id=wallet1["id"], amount=100)# Transfer from Alice to Bob (recipient by username, phone, or email)transfer = client.transfers.create( sender_wallet_id=wallet1["id"], recipient_identifier="bob", amount=50.00,)print(f"Transfer completed: {transfer['id']}")# Verify balances moved (exact values depend on your fee configuration)alice_balance = Decimal(str(client.wallets.balance(wallet1["id"])["balance"]))bob_balance = Decimal(str(client.wallets.balance(wallet2["id"])["balance"]))assert bob_balance > 0print("Balances correct after transfer")
# Delete test users (Test Mode only)def cleanup_test_users(): users = requests.get( "https://hpay-api.host-sl.com/api/v1/users/", headers=test_headers ).json() for user in users: if user['email'].endswith('@test.example.com'): requests.delete( f"https://hpay-api.host-sl.com/api/v1/users/{user['id']}", headers=test_headers ) print(f"🗑️ Deleted test user: {user['email']}")# Run cleanupcleanup_test_users()
Test Mode data is isolated and can be safely deleted. Be careful not to use
live credentials when cleaning up!
The SDK repository ships a runnable
smoke test (examples/smoke_sdk.py) that walks the full money path — user →
wallet → deposit → transfer → escrow → payout — against a Test Mode instance
and asserts each step: