HubdexPay helps businesses accept and disburse money across mobile money, banks, wallets, and local payment rails through a single secure API. Built for the Horn of Africa, designed for global merchants.
Mobile wallets dominate the Horn of Africa. We've built first-class connectors for the major ones, with bank transfer, card, and manual settlement as fallbacks. New providers are added in days through our connector framework.
Push-payment STK flow with real-time webhooks. Most popular wallet in southern Somalia.
Direct wallet-to-merchant collections plus B2C disbursements. Dollar-denominated.
Wallet collections via Golis Telecom. Coverage across the Bari and Nugal regions.
Collections and disbursements across Somtel's network. Cross-region wallet support.
Daraja STK Push integration. KES collections, B2C payouts, paybill and till support.
Operator-confirmed bank deposits and outgoing wires. Multi-currency settlement.
3-D Secure card acceptance through approved acquirers. Tokenized PAN handling.
Have a regional rail not listed here? Our connector interface integrates a new provider in days, not months.
The full lifecycle of a deposit — request, route, process, confirm, settle — is observable in your dashboard the moment it happens. No black boxes.
Your backend posts a signed deposit or payout request to /v1/deposits.
Routing engine picks the healthy provider for your channel and risk-checks the transaction.
The connector talks to the upstream rail and tracks the provider transaction ID.
When the customer pays, the provider notifies us; we verify the signature.
Ledger entries written, your balance bumps, and we POST a signed event to your URL.
Predictable JSON, signed requests, idempotency on every mutation, and webhook callbacks that retry until your endpoint acknowledges them. No SDK lock-in — works with curl.
Every request signed with HMAC-SHA256 over timestamp + method + path + body_hash. Constant-time comparison, 5-minute replay window.
Send the same Idempotency-Key twice and you get the cached response — never a duplicate charge. 24-hour retention.
Every response wraps in { data: {...} } on success or { error: { code, message } } on failure. No surprises.
Signed events delivered to your URL with 9-step exponential backoff: 30s → 24h. Dead-letter queue for review.
Lost a webhook? Pull current state any time via GET /v1/transactions/{id} or by your own merchant reference.
// Charge a customer via mobile wallet (PHP) $timestamp = time(); $path = '/v1/deposits'; $body = json_encode([ 'amount' => '25.00', 'currency' => 'USD', 'channel' => 'evc', 'customer' => ['phone' => '252611234567'], 'merchant_reference' => 'order_8421', ]); $toSign = "$timestamp\nPOST\n$path\n" . hash('sha256', $body); $signature = base64_encode(hash_hmac('sha256', $toSign, $apiSecret, true)); $response = httpPost('https://api.hubdexpay.com' . $path, $body, [ 'X-API-Key: ' . $apiKey, 'X-Timestamp: ' . $timestamp, 'X-Signature: ' . $signature, 'Idempotency-Key: ' . $orderId, ]); // Response: 201 Created // { "data": { "id": "hdx_dep_01HKL...", "status": "pending", ... } }
# Same call as a one-liner curl -X POST https://api.hubdexpay.com/v1/deposits \ -H "X-API-Key: pk_live_xxx" \ -H "X-Timestamp: $(date +%s)" \ -H "X-Signature: $SIG" \ -H "Idempotency-Key: order_8421" \ -d '{ "amount": "25.00", "currency": "USD", "channel": "evc", "customer": { "phone": "252611234567" }, "merchant_reference": "order_8421" }' # 201 Created { "data": { "id": "hdx_dep_01HKL...", "reference": "HDX-D-7K2A1B", "status": "pending", "amount": "25.0000", "net_amount": "24.6250" } }
// Node.js / TypeScript import crypto from 'node:crypto'; import { fetch } from 'undici'; const ts = Math.floor(Date.now() / 1000); const body = JSON.stringify({ amount: '25.00', currency: 'USD', channel: 'evc', customer: { phone: '252611234567' }, }); const bodyHash = crypto.createHash('sha256').update(body).digest('hex'); const sig = crypto.createHmac('sha256', apiSecret) .update(`${ts}\nPOST\n/v1/deposits\n${bodyHash}`).digest('base64'); const res = await fetch('https://api.hubdexpay.com/v1/deposits', { method: 'POST', headers: { 'X-API-Key': apiKey, 'X-Timestamp': `${ts}`, 'X-Signature': sig }, body, });
One pane of glass for your operations team. Filter, search, export, retry, and reconcile — without filing a support ticket.
See available, pending, and reserved balances per currency. Initiate manual payouts straight from the dashboard.
Generate test and live keys, scope by capability, restrict to IP ranges, and revoke instantly when needed.
Configure your endpoint URL, rotate signing secrets, replay failed deliveries, and inspect every event payload.
Daily reconciliation reports with line-by-line breakdown of fees, net settled amount, and payout batches.
HubdexPay ships with a back-office console designed for real fintech teams. Every action is audited, every state change is reversible, every webhook is inspectable.
Create, suspend, or close merchant accounts. Adjust risk tier, reserve %, and rate limits per merchant.
Manual review for risky payouts and bank transfers. One click writes ledger entries and notifies the merchant.
Real-time health dashboard for every connector. Set health to "down" to instantly reroute traffic.
Every delivery attempt with HTTP status, response body, and retry timestamp. Replay deliveries from the UI.
Append-only log of every dashboard state change with actor, IP, user-agent, and before/after metadata.
Every monetary movement creates immutable ledger entries. Every state transition is audited. Every secret is encrypted at rest. We don't get to be wrong about money.
Every API call signed with HMAC-SHA256 over timestamp + method + path + body hash. Constant-time verification, 5-minute replay window.
Provider API credentials and merchant webhook secrets stored AES-256-GCM encrypted. Plaintext never touches disk.
Owner, admin, finance, support, viewer roles. Each user scoped to their merchant, with full audit on every action.
Verify HubdexPay events with three lines of code. Reject anything older than 5 minutes to prevent replay.
// Verify a webhook (PHP) $expected = base64_encode(hash_hmac('sha256', $timestamp . '.' . $rawBody, $webhookSecret, true)); if (!hash_equals($expected, $received)) return http_response_code(401);
Every state-changing action — login, payout approval, settings change — logged with actor, IP, user-agent, and metadata.
Per-merchant rate limits, IP allow-lists on API keys, login throttle (5 fails/10min/IP), and DDoS-friendly upstream caching.
Configurable thresholds and velocity rules. Anything flagged sits in admin's queue until a human signs off.
HubdexPay is in production with merchants across betting, e-commerce, agent networks, remittance, and utility payments. Real workflows, real volume, real reconciliation.
Accept wallet deposits in seconds, disburse winnings the same day. Velocity controls and per-customer limits configurable per merchant.
Move fiat in and out of crypto exchanges through mobile wallets and bank transfers. Manual review queue for large amounts.
White-label checkout where customers pick a payment method by name — without exposing which provider is on the other side. Drop-in JS or full API control.
Wallet platforms get one ledger across providers — no separate reconciliation per rail. Same-day settlement to your operating bank.
Distribute float to thousands of agents and reconcile commissions automatically. Sub-merchant accounts let you give each agent their own dashboard.
Receive remittances via correspondent banks and disburse to wallets. Or move money the other direction — wallet to international bank account.
Power, water, and telco bills routed through the right rail per region. Bulk-import customer accounts and let them pay any way they prefer.
No setup fees, no monthly minimums. Volume discounts kick in automatically as you scale. Provider-specific fees are passed through transparently.
For new businesses testing the waters. Get fully integrated, then start paying when you go live.
For merchants moving real volume across multiple rails. Production-ready from day one.
For high-volume aggregators and PSPs that need custom routing, dedicated infrastructure, and tight SLAs.
Concrete examples in PHP, Node, Python, and curl. No "TODO: write tutorial" pages. No marketing fluff between you and the code.
Every endpoint documented with request shape, response shape, error cases, and concrete examples. Hosted alongside an interactive sandbox.
POST /v1/deposits — charge a customer via any railPOST /v1/payouts — disburse to a wallet or bankGET /v1/transactions — paginated historyGET /v1/balance — per-currency available, pending, reservedGET /v1/providers — your enabled rails with health status# GET /v1/transactions?type=deposit&status=completed&limit=10 { "data": [ { "id": "hdx_dep_01HKL3...", "reference": "HDX-D-7K2A1B", "type": "deposit", "status": "completed", "amount": "25.0000", "net_amount": "24.6250", "currency": "USD", "created_at": "2026-05-06T03:14:29Z" } ], "next_cursor": "2026-05-06T02:48:11Z" }
We POST signed JSON events to your URL whenever a transaction state changes. Verify the signature in three lines and you're done.
transaction.createdtransaction.completedtransaction.failedtransaction.expiredtransaction.updated// Verify (PHP) $secret = 'whsec_…'; $raw = file_get_contents('php://input'); $header = $_SERVER['HTTP_HUBDEXPAY_SIGNATURE']; preg_match('/t=(\d+),v1=([^,]+)/', $header, $m); $expected = base64_encode(hash_hmac( 'sha256', $m[1] . '.' . $raw, $secret, true )); if (!hash_equals($expected, $m[2])) { http_response_code(401); exit; }
Every API call carries three headers: X-API-Key, X-Timestamp, and X-Signature. The signature is HMAC-SHA256 over a canonical string.
ts + "\n" + METHOD + "\n" + path + "\n" + sha256_hex(body)base64(hmac_sha256(secret, stringToSign))hash_equals# Compute signature in shell TS=$(date +%s) PATH_=/v1/deposits BODY='{"amount":"25.00","currency":"USD","channel":"evc"}' HASH=$(printf "%s" "$BODY" | sha256sum | awk '{print $1}') TO_SIGN=$(printf "%s\nPOST\n%s\n%s" "$TS" "$PATH_" "$HASH") SIG=$(printf "%s" "$TO_SIGN" | openssl dgst -sha256 -hmac "$SECRET" -binary | base64) curl -X POST "https://api.hubdexpay.com$PATH_" \ -H "X-API-Key: $KEY" \ -H "X-Timestamp: $TS" \ -H "X-Signature: $SIG" \ -d "$BODY"
Errors return uniform JSON: { error: { code, message, details } }. The HTTP status reflects the kind of error. No surprise codes — every value is documented.
400 invalid_amount — amount missing or malformed401 signature_invalid — HMAC mismatch or stale timestamp402 insufficient_balance — payout exceeds available403 blocked_by_risk — risk engine rejected409 idempotency_conflict — key reused with different body429 rate_limited — slow down; check Retry-After# 402 Payment Required { "error": { "code": "insufficient_balance", "message": "Merchant balance is below the requested payout amount.", "details": { "requested": "100.00", "available": "42.50", "currency": "USD" } } }
Sandbox is a full mirror of production using the mock provider. Every API behavior — pending, completed, failed — can be triggered deterministically without spending a cent.
success, pending, fail, random# Trigger a deterministic FAILED deposit (sandbox) curl -X POST https://sandbox.hubdexpay.com/v1/deposits \ -H "X-API-Key: pk_test_…" \ -H "X-Test-Outcome: fail" \ -d '{"amount":"10.00","currency":"USD","channel":"mock"}' # 201 Created — status will transition to "failed" within 2 seconds # and a transaction.failed webhook will be queued
The path from sandbox keys to production. We've shipped this with dozens of merchants — these are the steps that matter, in order.
/v1/deposits# Recommended test matrix before going live [✓] Signed request with valid signature → 201 [✓] Signed request with stale timestamp → 401 [✓] Same idempotency key, same body → cached [✓] Same idempotency key, diff body → 409 [✓] Webhook with valid signature → 200 [✓] Webhook with bad signature → 401 [✓] Payout exceeding available balance → 402 [✓] Recover state via /v1/transactions/id → 200
One business day to first reply. If you're already running on a payment stack and considering a switch, mention it — those usually get a same-day call.
Sandbox in minutes. Live keys in days, not months. Most merchants are processing real volume within a week.
Your brand on the dashboard, your channel names in the API, your customer-facing receipts. We're invisible infrastructure.
Double-entry bookkeeping enforced at write-time. Reconcile to the cent every day with zero spreadsheets.
Built by people who've run a payment back-office. Manual review queues, audit logs, and webhook replay aren't bolt-ons.