Bank Transfer

How Interwallet Transfer works (step by step flow)

SOURCE APP SIDE: The source app is the app trying to do the wallet transfer

Communication is sent to the merchants endpoint(Outgoing transaction webhook)

Below is a screen showing where the Finswich merchant sets their transaction or settlement webhook for a registered app

PAYLOAD sent to the merchant's backend to initiate a bank transfer and debit their end user

{
	"event": "TRANSACTION_INITIATE",
	"data": {
		"user_reference": "poormeggriffin",
		"amount": 771.4,
		"currency": "ngn",
		"txn_reference": "FIN-OZeyO8sv9ZMMra781684308945",
		"transfer_type": "BANK",
		"recipient": {
			"account_number": "6172555949",
			"bank_name": "Fidelity Bank Plc",
			"account_name": "Abuchi Kingsley Ndinigwe",
			"bank_code": "50"
		},
		"mode": "TEST"
	}
}

200 RESPONSE structure expected

{
"status":"success",
"data": {
"user_category":str (optional)
}
}

If the response returned is not in the 200 range or response.status != “success”, the transaction process is terminated immediately and that transaction reference becomes invalid.

If user_category is returned then we automatically run an internal policy check using the category sent. If the policy check fails, we call their policy notification API or Email and notify the merchant and then the transaction process is terminated.

Its advisable to store this transaction (txn_reference) as it will be used to complete the remaining steps

  1. Trigger OTP

Payload sent to source app to trigger sending OTP to the user endpoint = source app transaction webhook

{
	"event": "SEND_OTP",
	"data": {
		"user_reference": "poormeggriffin",
		"txn_reference": "FIN-OZeyO8sv9ZMMra781684308945",
		"debit_platform": "Kuda",
		"credit_platform": "Zenith Bank Plc",
		"amount": 771.4,
		"currency": "ngn",
		"recipient_user": "None",
		"mode": "TEST"
	}
}

200 response structure

{
"status":"success"
}

If the response returned is not 200 or the response.status != “success”, we do not terminate the txn. If the call to this endpoint is successful, we respond back to the client informing them that an OTP has been sent to their phone number This is the same endpoint and payload called when the user clicks the OTP resend button This transaction ref is valid for only 60minutes.

  1. Complete Transfer (for merchant to verify OTP received by their user and start the real process of transferring funds from the originator app to the destination bank account )

Payload sent to source app to complete transfer endpoint = source app transaction webhook

{
	"event": "COMPLETE_TRANSACTION",
	"data": {
		"otp": "745058",
		"txn_reference": "FIN-OZeyO8sv9ZMMra781684308945",
		"user_reference": "poormeggriffin",
		"mode": "TEST"
	}
}

Here the merchant verifies the OTP. If verification is succesful merchant proceeds to truly complete the transaction by communicating with the Finswich Transfer endpoint.

200 response structure

{
"status":"success"
}

//This response is received after the event mentioned in 3b below

If the response is 200 Ok, this means the txn was successful

3b. Calling the Finswich Transfer API for Payment Termination

On the originator app’s end, when they receive the complete transaction event and has verified the OTP, they would call Finswich’s transfer API to actually make the transfer. The Finswich transfer API handles the movement of money from the source merchant's app to the recipient bank account.

This is what the endpoint and the payload will look like:

endpoint (prod) = https://finswich-api.fuspay.finance/api/v1/app-transfer/wallet endpoint (staging) = https://finswichstaging.instance.exchange/api/v1/app-transfer/wallet method = POST

Sample Request

headers = {
"Accept": "application/json",
"x-finswich-signature": hashed_payload,
"x-public-key": public_key,
}


payload = {"auth_code": otp, "txn_reference": txn_reference}

//the OTP code is not for verification but logging on Finswich end

Sample Response

200 OK

response = {
"status":"success",
"data":{},
"message":"Transaction completed successfully"
}

400 response structure

response = {
"status":"error",
"data":{},
"message":"Transaction failed"
}

If a 200 response is returned and response.status == “success” this means the source app’s wallet been debited.

  1. SETTLEMENT/BENEFICIARY'S END If the above transaction was successful FInswich sends the money to the recipient bank account using the payment termination API

200 response expected

{
"status":"success"
}

If any request to the beneficiary fails, it is retried 4 times

MINUTES_MAP = {1: 5, 2: 60, 3: 1440, 4: 4320} 
//The first retry is 5 mins after the first attempt to credit. The second retry is 60 mins after the first retry...the 3rd retry is 1440 mins after the second retry and so on.

Last updated