> For the complete documentation index, see [llms.txt](https://developer.ellypayapp.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.ellypayapp.com/service-payments/payment-confirmation.md).

# Payment Confirmation

{% hint style="info" %}
We recommend checking out the [Getting Started](/service-payments/getting-started.md) section to understand the basics of service payments first and the general workflow. This guide assumes that you have read that
{% endhint %}

## Step 1: Setup the payment confirmation request

The table below describes the request parameters that are used for the payment confirmation request.&#x20;

<table><thead><tr><th width="197">Parameter</th><th width="93">Type</th><th width="98">Required</th><th>Description</th></tr></thead><tbody><tr><td>internal_reference</td><td>String</td><td>true</td><td>The internal reference returned as part of the validation response</td></tr><tr><td>secret_code</td><td>String</td><td>false</td><td>This one is a special parameter that applies to Airtel Money Withdraw transactions. <em><strong>The customer secret code should be Base64 encoded before sending the API request</strong></em>.</td></tr></tbody></table>

Prepare your request payload as demonstrated below.

```json
{
    "internal_reference": "ELPREFQ9ULSYC7KAASWJ"
}
```

<mark style="color:green;">`POST`</mark> `https://gwapisdbx.ellypayapp.com/service-payments/process-payment`

The request is sent as a JSON body as demonstrated by the sample request below. Sample responses (acknowledgement and failure) are also shared.

```powershell
curl -X POST "https://gwapisdbx.ellypayapp.com/service-payments/process-payment" \
   -H 'Content-Type: application/json' \
   -H "x-api-version: 1" \
   -H "public-key: your-public-key" \
   -d '{
        "internal_reference": "ELPREFQ9ULSYC7KAASWJ"
    }'
```

{% tabs %}
{% tab title="200: OK - Request processed successfully" %}

```json
{
    "code": 202,
    "status": "accepted",
    "message": "Request Accepted",
    "data": {
        "internal_reference": "ELPREFA65BGTFR7NGUXM",
        "merchant_reference": "MCTREFT2WMNWZ23SBN6Y"
    }
}
```

{% endtab %}

{% tab title="400: Bad Request - Request is not formed as expected" %}

```json
{
    "code": 400,
    "status": "error",
    "message": "Unknown internal reference",
    "data": {}
}
```

{% endtab %}
{% endtabs %}

## Step 2: Handle final status notification

Every merchant account is expected to have configured a callback/webhook URL for service payments. For all transactions that transition to the final state (COMPLETED or FAILED), a JSON POST request will be made to the callback URL. Sample callback payloads (request bodies) are shared below. Be sure to check out [Handling Notifications](/utility-functions/handling-notifications-callbacks.md) to see how you should verify the signature(s) in the request headers and how to respond.

{% tabs %}
{% tab title="Successful Service Payment" %}

```json
{
    "event": "payment.completed",
    "payload": {
        "merchant_reference": "MCTPAY7JAKLM2CGHUAUK",
        "internal_reference": "ELPREFAJJXPPALHUWKFY",
        "transaction_type": "SERVICE_PAYMENT",
        "request_currency": "UGX",
        "request_amount": 1000,
        "transaction_status": "COMPLETED",
        "account_number": "256772007180",
        "transaction_charge": 0,
        "transaction_amount": 1000,
        "customer_name": "SANDBOX CUSTOMER",
        "service_name": "MTN Airtime",
        "status_message": "Transaction Completed Successfully",
        "additional_details": {}
    }
}
```

In some situations, the `payload.additional_details` parameter will hold extra details about the payment e.g. the YAKA token etc. The table below decribes some of the expected parameters in the additional\_details object.

<table><thead><tr><th width="171">Parameter</th><th width="101">Type</th><th>Description</th></tr></thead><tbody><tr><td>token</td><td>String</td><td>The YAKA token. Only returned on YAKA payments</td></tr><tr><td>units</td><td>Number</td><td>The total units purchased. Usually returned on YAKA payments</td></tr><tr><td>receipt_number</td><td>String</td><td>The payment receipt. Usually returned on utility or tax payments</td></tr><tr><td>description</td><td>String</td><td>Description of the payment. This usually applies to all service payments</td></tr><tr><td>debt_recovery</td><td>String</td><td>Usually returns on YAKA payments</td></tr><tr><td>fuel</td><td>String</td><td>Usually returns on YAKA payments</td></tr><tr><td>inflation</td><td>String</td><td>Usually returns on YAKA payments</td></tr><tr><td>tax</td><td>String</td><td>Usually returns on YAKA payments</td></tr><tr><td>customer_phone</td><td>String</td><td>Usually returns on utility, tax and digital TV payments</td></tr></tbody></table>
{% endtab %}

{% tab title="Failed Service Payment" %}

```json
{
    "event": "payment.failed",
    "payload": {
        "merchant_reference": "MCTPAYWQXZML3EQR7TKT",
        "internal_reference": "ELPREFNWSN5RFEBWHHWK",
        "transaction_type": "SERVICE_PAYMENT",
        "request_currency": "UGX",
        "request_amount": 1000,
        "transaction_status": "FAILED",
        "account_number": "256772000004",
        "transaction_charge": 0,
        "transaction_amount": 0,
        "customer_name": "SANDBOX CUSTOMER",
        "service_name": "MTN Airtime",
        "status_message": "Insufficient funds to complete transaction",
        "additional_details": {}
    }
}
```

{% endtab %}
{% endtabs %}
