Skip to content
Test money only. BitMomo currently runs on test networks. Payments use testnet coins and no real money moves. Live keys are not available yet.

Payments

POST /api/v1/gateway/payments (scope payments:write) creates a payment priced in Ghana cedis.

Field Required Notes
amount Yes GHS amount as a decimal string, for example "100.00". At most 8 decimal places.
crypto_type Yes The coin the customer pays with, for example USDT_TRC20. See supported coins.
fiat_currency No Only GHS is accepted.
order_id No Your order reference, up to 128 characters. Returned on the payment and in webhooks.
description No Shown to the customer, up to 500 characters.
idempotency_key No, but strongly recommended See Idempotency.
callback_url No Restricts this payment’s webhooks to one registered endpoint. See Webhooks.
redirect_url No Stored with the order terms. BitMomo does not redirect the customer to it automatically.
metadata No Your own key/value data, up to 4 KB and 3 levels deep. Keys starting with _, bitmomo_, cryptopos_ or server_ are reserved.

The response contains everything needed to collect the payment: the locked crypto amount and rate, the deposit address and network, a qr_code_data payment URI, and expires_at. Send the customer to the hosted checkout at https://customer.dev.bitmomo.app/pay/{id}, or build your own page from those fields.

Always take the price from your own server-side order record, never from the browser.

Network calls can time out after BitMomo has already created the payment. To make retries safe:

  1. Generate an idempotency_key for the order (the SDK’s newIdempotencyKey() returns a UUID).
  2. Save it with the order before calling BitMomo.
  3. Send the same key on every retry for that order.

Repeating a request with the same key returns the original payment instead of creating a second one. Reusing a key with different details (for example another amount) is rejected with 409.

A payment moves through these statuses:

Stage Statuses
Waiting for the customer created, locked, pending
Payment seen on chain detected, confirming, confirmed, settling
Final completed, expired, failed, cancelled
Held for review flagged, needs_review, orphaned
  • completed: the funds are confirmed and credited to your account.
  • expired: the quote window passed without an accepted payment. Create a new payment if the customer still wants to pay.
  • cancelled: the payment was cancelled before completion.
  • needs_review: BitMomo is holding the payment for a manual check. Do not fulfil until it reaches completed.

Statuses are lowercase with underscores. Treat any status you do not recognise as “not paid yet”.

GET /api/v1/gateway/payments/{id} (scope payments:read) returns the full private view of one of your payments. Fields to check before fulfilling an order:

Field Meaning
status Must be completed.
environment test today; must match the environment of your order.
order_terms.order_id Must be the order you are fulfilling.
economics.invoice_ghs The amount you asked for.
economics.recognized_gross_ghs The amount BitMomo recognised from what the customer actually paid.
economics.merchant_net_ghs What you receive after fees.
economics.surplus_ghs Any overpayment held separately.
payout Payout state for this payment. It is separate from whether the customer paid.

economics is null until the payment completes. completed alone does not prove the customer paid the full price: compare recognized_gross_ghs with your order amount. If you accept underpayment (for example a discount), make that an explicit rule in your own system.

All money values are decimal strings. Compare them exactly; never convert them to floating-point numbers.

GET /api/v1/gateway/payments (scope payments:read) returns your payments, newest first. Use page and limit (up to 100) to paginate and status_filter to filter by status. Each row includes environment and recognized_amount_fiat.

GET /api/v1/gateway/balances (scope payments:read) returns exact balances as decimal strings, for example ghs_available_exact, together with per-currency and per-asset balances. Older numeric fields in the same response are for display only.

Use webhooks to learn about changes, and GET /gateway/payments/{id} to confirm them. If your webhook endpoint was down, list recent payments to catch up; do not rely on webhooks alone.