Skip to content

mtn-momo: add Disbursement helpers (transfer, status, balance, account validation) #1813

Open

Description

@jackohilts

Summary

Extend @openfn/language-mtn-momo (currently v1.2.3) with helper functions for the MTN MoMo Disbursement product. Today the adaptor exposes only a generic request(), and its examples target the Collection product.

Follow-up to #1106, which built the Collections side and planned Disbursements as a later iteration.

Use case

A workflow sends approved incentive payments to mobile-money wallets in Ghana, then a second workflow polls pending payments and reconciles them. Because this moves real money, idempotency and clear status handling are the priority.

Proposed functions

  • Auth for the Disbursement product: POST /disbursement/token/ using API user/key and the disbursement subscription key (subscription keys are per product). Cache the token per run; re-auth on 401.
  • validateAccountHolder(msisdn): GET /disbursement/v1_0/accountholder/msisdn/{msisdn}/active
  • getBasicUserInfo(msisdn): name check before the first payment to a new payee
  • getBalance(): GET /disbursement/v1_0/account/balance (pre-payout funds check)
  • transfer(data, { referenceId, callbackUrl }): POST /disbursement/v1_0/transfer with amount, currency, payee { partyIdType, partyId }, externalId, payerMessage, payeeNote. The caller supplies the UUID X-Reference-Id so a retry can never create a second payment. Expect 202 Accepted.
  • getTransferStatus(referenceId): GET /disbursement/v1_0/transfer/{referenceId}. Returns PENDING / SUCCESSFUL / FAILED plus reason. A 404 means the original transfer was never accepted.
  • Optional: deposit (v1_0 / v2_0) if the market provisions deposit rather than transfer.

Credential schema changes

  • Add product (collection | disbursement) or a separate disbursement_subscription_key
  • Add targetEnvironment (sandbox or the production value issued by MTN for the market), sent as X-Target-Environment
  • Document that sandbox only accepts EUR; production in Ghana uses GHS

Acceptance criteria

  • Token caching per run; re-auth on 401
  • transfer throws if no caller-supplied referenceId
  • Status values and common reason codes documented
  • Full cycle tested in the MoMo sandbox: validate, balance, transfer, status
  • Existing Collection usage via request() unaffected
  • JSDoc examples, mocked unit tests, changeset, docs

Go-live notes (implementer side, not adaptor work)

  • Pre-funded MTN MoMo Disbursement account in the target market
  • Production API user/key and subscription key issued by MTN
  • IP whitelisting of the OpenFn worker egress IP(s) is required for Disbursement
  • HTTPS callback URL if callbacks are used; otherwise poll status

Notes

  • If the implementation ends up using Hubtel instead, the equivalent work is adding sendMoney() and getTransactionStatus() to the existing hubtel adaptor (Hubtel docs cite a 5 requests/minute rate limit).

References: MoMo Disbursement Transfer, MoMo Developer portal

Target: end of December 2026.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions