For Developers
Build in an afternoon. Go live in weeks.
Onboard users, move funds, top up cards and upload KYC over one REST API. Once your sandbox credentials arrive, most teams have money moving in the sandbox the same afternoon. Going live follows due diligence, UAT and contracting.
Get your keys
Get in touch and we'll run KYB, then send your sandbox credentials. There's no bank onboarding and no separate integration for each payment method.
Get in touch →Call the API
Create accounts, move money, top up cards and read balances from documented endpoints with full error schemas.
Jump to the reference ↓Go live
Once you've passed UAT and signed the commercial agreement, we issue production credentials. The same API you built against then moves real money.
API reference
Spendl Public API
Every partner endpoint, grouped by what it does. Request and response schemas, error codes and worked examples live in the guide.
- Production
- https://ingest.spendl.money
- Sandbox (staging)
- https://ingest.staging.spendl.money
- Auth
Authorization: Bearer <accessToken>on every/api/*route. Get the token from/auth/token.
Public
No authentication required.
- GET
/healthHealth check - POST
/auth/tokenExchange API credentials for a JWT
User ingestion & validation
- POST
/api/ingestCreate a single user or a batch of users - PATCH
/api/ingest/:id/detailsUpdate mutable account details - PATCH
/api/ingest/:id/kycReplace canonical KYC data and restart validation - POST
/api/validateValidate a payload without inserting records - GET
/api/ingest/status/:idCheck ingestion and sync status
KYC documents
- POST
/api/kyc/:userId/:documentType/:category/:filenameUpload an identity or residence document
Lending
- POST
/api/debt/ingestSubmit a debt obligation record - POST
/api/debt/eligibilityRecord a debt-offer eligibility notification - GET
/api/debt/status/:guidCheck obligation processing status - GET
/api/debt/audit-logsList the audit trail for debt records
Wallet
- GET
/api/wallet/balance/:userIdRetrieve an account balance - GET
/api/wallet/history/:userIdRetrieve transaction history, paginated - GET
/api/wallet/:userId/depositRefGet a treasury deposit reference - POST
/api/wallet/depositDeposit funds into a wallet - POST
/api/wallet/transferTransfer between two user wallets - POST
/api/wallet/disbursePay one recipient or hundreds from a business walletadmin scope - POST
/api/wallet/load-cardTop up a debit card from a wallet - POST
/api/wallet/send-to-bankEFT to a registered external bank account - POST
/api/wallet/purchase-voucherPurchase a voucher, airtime and the rest - POST
/api/wallet/repay-debtRepay a debt obligation from a wallet
Beneficiaries
- POST
/api/wallet/beneficiaryRegister a bank beneficiary for EFT - GET
/api/wallet/beneficiaries/:userIdList registered beneficiaries - DELETE
/api/wallet/beneficiary/:userId/:beneficiaryIdRemove a beneficiary
Vouchers & payouts
- GET
/api/vouchers/providersList enabled voucher and payout products - GET
/api/vouchers/providers/:providerCode/limitsLive amount limits and recipient fields - POST
/api/vouchers/quoteQuote a voucher payout fee and total debit - POST
/api/vouchers/performIssue a voucher, airtime, cash or bank payout - GET
/api/vouchers/statusCheck a voucher payout status
Remittance
- GET
/api/remittance/corridorsList available corridors and payout types - POST
/api/remittance/quoteGet a live quote with a locked rate - POST
/api/remittance/name-checkValidate recipient identity before send - POST
/api/remittance/validateValidate recipient details for the selected payout rail - GET
/api/remittance/banksList destination banks for a country - GET
/api/remittance/user-limitsCheck a user’s remaining remittance limits - POST
/api/remittance/sendExecute a cross-border transfer - GET
/api/remittance/transactionsList remittance transaction history - GET
/api/remittance/transactions/:transactionIdGet one remittance transaction - GET
/api/remittance/transactions/:transactionId/statusPoll a remittance transaction status - POST
/api/remittance/transactions/:transactionId/cancelCancel an eligible remittance transaction - GET
/api/remittance/statsGet a user’s remittance statistics
Cards
- GET
/api/cards/:userIdList a user’s cards - GET
/api/cards/:userId/readinessCheck whether a user can be issued or top up a card - GET
/api/cards/:userId/limitsMonthly card funding limit and usage - GET
/api/cards/:userId/funding-accountGet the card funding account - GET
/api/cards/:userId/card/:cardIdGet masked card details - GET
/api/cards/:userId/card/:cardId/balanceGet a card balance - GET
/api/cards/:userId/card/:cardId/transactionsList card transactions
Crypto
- GET
/api/crypto/balancesList a user’s crypto balances - GET
/api/crypto/market-dataList crypto market data - GET
/api/crypto/market-data/:pairGet market data for one pair - GET
/api/crypto/deposit-addressesGet crypto deposit addresses - GET
/api/crypto/depositsList crypto deposits - POST
/api/crypto/estimate-tradeEstimate a market sell to rand - POST
/api/crypto/place-orderPlace a market sell to rand - GET
/api/crypto/order-status/:orderIdGet a sell order status - GET
/api/crypto/service-providersList withdrawal service providers - GET
/api/crypto/withdrawals-config/:currencyGet withdrawal fees and limits for an asset - GET
/api/crypto/withdrawal-addressesList saved withdrawal addresses - POST
/api/crypto/withdrawalsCreate an on-chain withdrawal - GET
/api/crypto/withdrawalsList crypto withdrawals - GET
/api/crypto/withdrawals/:withdrawalIdGet one crypto withdrawal - GET
/api/crypto/transactionsList crypto transactions
Pay@
- POST
/api/wallet/deposit/payatStart a Pay@ top-up: card and EFT links, a QR code and a till account number - GET
/api/payat/account/:userIdGet Pay@ account details for a user - GET
/api/payat/transactionsList a user’s Pay@ deposits, paginated - GET
/api/payat/transactions/:idGet one Pay@ deposit - POST
/api/wallet/withdrawal/payatIssue a single-use PIN for cash at the till - GET
/api/payat/withdrawal/status/:withdrawalRequestIdPoll a Pay@ withdrawal status - GET
/api/payat/withdrawal/list/:userIdList a user’s Pay@ withdrawals
Zapper
- POST
/api/wallet/deposit/zapperInitiate a Zapper QR deposit - GET
/api/zapper/deposit/status/:sessionIdPoll a Zapper deposit by session - GET
/api/zapper/deposit/status-by-order/:merchantOrderIdPoll a Zapper deposit by merchant order reference - POST
/api/wallet/withdrawal/zapper/decodeDecode a Zapper scan-to-pay QR code - POST
/api/wallet/withdrawal/zapperPay a Zapper merchant from the wallet (scan to pay) - GET
/api/zapper/withdrawal/status/:paymentReferencePoll a Zapper payment status
Reference data
Cached, five-minute TTL.
- GET
/api/wallet/bank-optionsList available banks - GET
/api/wallet/account-typesList bank account types - GET
/api/wallet/supplier-typesList supplier types - GET
/api/wallet/participating-banksList banks supporting PayShap / RTC
Webhooks
40 events, pushed as they happen
Subscribe to the lifecycle events you care about and your system hears about money the moment it moves, without polling.
- Signing
- Every delivery carries an X-Signature header over the exact request body. Ask for a signing secret and it becomes HMAC-SHA256, so you can prove the call came from us. We recommend it for production.
- Retries
- Network errors and 5xx responses are retried from a durable queue, up to five times. X-Idempotency-Key stays the same across retries, so you can safely de-duplicate.
- Formats
- JSON over REST or RPC, or form-encoded. Optional Basic or Bearer authentication on your endpoint.
- Setup
- You choose which events you want and where each one goes. We configure the endpoints and secrets for your business, kept separate from every other business.
Account & lending
- user.created
- account.updated
- account.status_changed
- bank_account_created
- debt_obligation_created
- debt_repayment_complete
KYC
- kyc.document_uploaded
- kyc.documents_completed
- kyc.not_ready
- kyc.submission_pending
- kyc.submitting
- kyc.submitted
- kyc.submission_failed
- kyc.validation_pending
- kyc.validation_started
- kyc.validation_failed
- kyc.review_required
- kyc.approved
- kyc.rejected
- kyc.superseded
Wallet
- wallet.incoming_credit
- wallet.deposit_completed
- wallet.transfer_completed
- wallet.disbursement_completed
- wallet.load_card_completed
- wallet.purchase_voucher_completed
- wallet.repay_debt_completed
- wallet.send_to_bank_completed
- wallet.beneficiary_added
- wallet.beneficiary_removed
- wallet.suspended
- wallet.closed
Compliance
- compliance.hold_set
- compliance.hold_cleared
Remittance
- remittance.submitted
- remittance.completed
- remittance.failed
- remittance.cancelled
- remittance.cashPickupReady
- remittance.refunded
Get started
Keep the next rand you move.
See a branded wallet, cross-border and the Public API running on your own numbers. Onboarding is hands-on, whatever the size of your team.
or email support@spendl.money