> For the complete documentation index, see [llms.txt](https://docs.fuspay.us/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.fuspay.us/payment-and-utilities/services-backend/utility-purchases.md).

# Utility Purchases

**SOURCE APP SIDE: The source app is purchasing utility (Airtime)**

1. <mark style="color:blue;">**Initiate a Utility Purchase**</mark>

\
![](/files/1p71S21Gnh3qQeCRUmis)

![](/files/H81W1r7NUxk5RXjo5VKn)

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

<figure><img src="/files/jBT8EMyrPAR3ZKRoeGob" alt=""><figcaption></figcaption></figure>

PAYLOAD sent to merchant's end to initiate purchase of utility&#x20;

{% code lineNumbers="true" fullWidth="false" %}

```javascript
{
	"event": "TRANSACTION_INITIATE",
	"data": {
		"user_reference": "poormeggriffin",
		"amount": "200.0",
		"currency": "ngn",
		"txn_reference": "UTL-hZ4KKPAvGR43kYLL1687247368",
		"transfer_type": "UTILITY",
		"recipient": {
			"product_id": "4611",
			"product_type": "Mobile Pin / Voucher",
			"product_category": "Mobile PIN",
			"operator": "Nigeria Airtel",
			"value_recipient": "+2347081332677"
		},
		"mode": "TEST"
	}
}
```

{% endcode %}

| Key               | Type   | Description                                                                                                                  |
| ----------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------- |
| Event             | String | the name of the even being broadcasted to the merchant. Initiate informs the merchant                                        |
| Data              | Object | The object containg the info of the utility purchase                                                                         |
| user\_reference   | String | the identifier for the user making the purchase                                                                              |
| amount            | Number | the amount to be debited from the user                                                                                       |
| currency          | String | the currency code of the buyer                                                                                               |
| txn\_reference    | String | The identifier for the transaction                                                                                           |
| transfer\_type    | String | The type of transaction. On finswich transactions can be of diffrent types. e.g. interwallet, bank transfers, utility e.t.c. |
| Recipient         | Object | The object containing                                                                                                        |
| product\_id       | String | the identifier for the utility product.                                                                                      |
| product\_type     | String | The type of utility being purchased                                                                                          |
| product\_category | String | the category of the utility being purchased eg Mobile Pin                                                                    |
| operator          | String | the service provider                                                                                                         |
| value\_recipient  | String | the phone number where the data or airtime would be loaded on.                                                               |
| mode              | String | The transaction can either be in the test mode or live mode. In test actual money is not transferred.                        |

200 RESPONSE <br>

```javascript
{
"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&#x20;

2. <mark style="color:blue;">**Trigger OTP**</mark>

<div align="left"><figure><img src="/files/jUnapzRAfr0Ay2Aln3hi" alt=""><figcaption></figcaption></figure></div>

Payload sent to merchant to trigger the sending of OTP to their end user\
endpoint = source app outgoing transaction webhook<br>

{% code overflow="wrap" lineNumbers="true" %}

```javascript
{
	"event": "SEND_OTP",
	"data": {
		"user_reference": "poormeggriffin",
		"txn_reference": "UTL-hZ4KKPAvGR43kYLL1687247368",
		"debit_platform": "Kuda",
		"credit_platform": "Utility",
		"amount": "200.0",
		"currency": "ngn",
		"recipient_user": "None",
		"mode": "TEST"
	}
}

```

{% endcode %}

200 response structure<br>

```javascript
{
"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.

3. <mark style="color:blue;">**Complete Utility Purchase**</mark> (for merchant to verify OTP received by their user and start the real process of purchasing the utility )

**Payload sent to source app to complete transfer**\
**endpoint = Merchant's outgoing settlement webhook**<br>

```javascript
{
	"event": "COMPLETE_TRANSACTION",
	"data": {
		"otp": "23341",
		"txn_reference": "UTL-hZ4KKPAvGR43kYLL1687247368",
		"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.&#x20;

200 response structure<br>

<pre class="language-javascript"><code class="lang-javascript"><strong>{
</strong>"status":"success"
}
</code></pre>

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

**3b. Calling the Finswich Transfer API**

\
On the originator app’s end, when they receive this request, they would call Finswich’s transfer API to actually make the transfer. This is what the endpoint and the payload looks like:

\
endpoint (prod) = [`https://finswich-api.fuspay.finance/api/v1/app-transfer/wallet`](https://finswich-api.fuspay.finance/api/v1/app-transfer/wallet)\
endpoint (sandbox/test) = [`https://finswichstaging.instance.exchange/api/v1/app-transfer/wallet`](https://finswichstaging.instance.exchange/api/v1/app-transfer/wallet)\
method = POST

\
**Sample Request**&#x20;

```javascript
headers = {
"Accept": "application/json",
"x-finswich-signature": hashed_payload,
"x-public-key": public_key,
"x-origin": your whitelisted URL 
}


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

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

**Sample Response**<br>

**200 OK**

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

**400** response structure<br>

```javascript
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.&#x20;

3c. **Giving value to the user**

In certain utility events like the purchase of power there is need to provide some sort of token to,  as the token is what is used by the user to get the utility purchased.&#x20;

So there is a need to broadcast another event to the Finswich Merchant. This event enables merchant to efficiently dispatch mails and notifications to their end users.&#x20;

```javascript
{
	"event": "UTILITY_TRANSACTION_VALUE_READY",
	"data": {
		"txn_reference": "UTL-hZ4KKPAvGR43kYLL1687247368",
		"user_reference": "poormeggriffin",
		"utility_details": {
			"operator": "Nigeria Airtel",
			"product_id": "4611",
			"product_type": "Mobile Pin / Voucher",
			"value_recipient": "+2347081332677",
			"product_category": "Mobile PIN"
		},
		"utility_value": {
			"pin": { "number": "1234567890", "serial": "ZZZ123456", "instructions": "This is a test pin" },
			"instructions": "None"
		},
		"mode": "TEST"
	}
}
```

3d. **Failure at the Utility Providers end. Merchant and end user refund**&#x20;

For cases where the transaction fails at the utility providers end we also broadcast an event to the Finswich Merchant. This event signifies to the merchant that their Finswich wallet has been credited back with what was charged for their user's utility purchase and therefore the merchant can also refund their end user.&#x20;

<pre class="language-javascript" data-overflow="wrap" data-line-numbers><code class="lang-javascript"><strong> {"event": "UTILITY_TRANSACTION_REVERSAL",
</strong>            "data": {
                "txn_reference": UTL-p3kIL9sKruTBv3kL1686731317,
                "user_reference": poormeggriffin,
                "amount": 3000,
                "currency": NGN,
                "utility_details": {
	                                "operator": "Nigeria Airtel",
	                                "product_id": "4611",
	                                "product_type": "Mobile Pin / Voucher",
	                                "value_recipient": "+2347081332677",
	                                "product_category": "Mobile PIN"
			            }
                    }
}
</code></pre>

{% code overflow="wrap" %}

```javascript
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.
```

{% endcode %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.fuspay.us/payment-and-utilities/services-backend/utility-purchases.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
