Initiate a transfer
/v1/transfers/initiateAtomically debits your wallet and queues the disbursement. Pass an Idempotency-Key header to make retries safe. In live mode, a transfer above your OTP threshold returns status: "awaiting_otp" — finalize it with the emailed code (see *Finalize a transfer*). Sandbox transfers are never OTP-gated.
Body parameters
amountintegerrequiredAmount in kobo. Must exceed the configured minimum (see Get transfer config).
recipientstringrequiredAn RCP_ recipient code or a settlement-account id.
narrationstringoptionalStatement narration, max 100 chars.
referencestringoptionalYour unique reference. Auto-generated if omitted. 1–100 chars of [A-Za-z0-9_-.].
currencystringoptionalNGN only at this time.
metadataobjectoptionalArbitrary key/value pairs echoed back and in webhooks.
Response
200transfer_idstringTagPay-assigned transfer id (UUID).
referencestringTransfer reference (trf_…). Use this to finalize/verify.
statusenum<'queued' | 'processing' | 'success' | 'failed' | 'reversed' | 'awaiting_otp'>Lifecycle status.
amountintegerAmount in kobo.
feeintegerTransfer fee in kobo.
currencystringAlways NGN.
narrationstringStatement narration.
recipientobjectResolved destination.
idstringInternal settlement-account id.
account_namestringResolved account name.
account_numberstring10-digit NUBAN.
bank_codestringNIP bank code.
provider_referencestringDownstream NIP reference (null until processed).
created_atstringISO-8601 timestamp.
Errors
INSUFFICIENT_FUNDS400Wallet balance is below amount + fee.AMOUNT_BELOW_MINIMUM400Amount is under the configured withdrawal minimum.RECIPIENT_NOT_FOUND404No recipient/settlement account for that identifier.