> ## Documentation Index
> Fetch the complete documentation index at: https://docs.payzah.site/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Process Refunds with Payzah Refund API

> Return funds to your customer for a previously successful transaction, either in full or in part, using the original Track ID and Payzah Reference Code.

The Refund API lets you return funds to a customer for a transaction that has already completed successfully. You can issue a **Full Refund** for the entire original amount, or a **Partial Refund** for any portion of it. Like every other Payzah call, a refund is a single server-side `POST` request in JSON format.

## Before You Begin

A refund request will only succeed when all of the following are true:

* The original transaction completed successfully — refunds cannot be issued against failed, cancelled, or uncaptured payments
* You have the `trackid` you sent during the original payment initialization
* You have the Payzah Reference Code returned after that payment succeeded
* For a partial refund, the amount you are refunding is less than or equal to the original transaction amount

<Note>
  If you are not certain the original payment was captured, confirm it first with the [Get Payment Details API](/docs/api-reference/payment-status). A `paymentStatus` of `CAPTURED` means the transaction is eligible for a refund.
</Note>

## How Refunds Work

<Steps>
  <Step title="Set the Endpoint for Your Environment">
    Refunds use a dedicated endpoint. Use the test URL while building and switch to production only when your integration is fully validated.

    | Environment | URL                                                         |
    | ----------- | ----------------------------------------------------------- |
    | Test        | `https://development.payzah.net/ws/paymentgateway/refund`   |
    | Production  | `https://payzah.net/production770/ws/paymentgateway/refund` |

    **Headers**

    | Header          | Value                        |
    | --------------- | ---------------------------- |
    | `Content-Type`  | `application/json`           |
    | `Authorization` | `base64_encode($privateKey)` |

    <Warning>
      Your private key must never appear in client-side code, front-end JavaScript, or mobile app binaries. Refund requests must always be sent from your backend server.
    </Warning>
  </Step>

  <Step title="Choose the Refund Type">
    The `refund_type` field determines how much is returned to the customer.

    | Value | Refund type    | Amount to send                  |
    | ----- | -------------- | ------------------------------- |
    | `1`   | Full Refund    | The original transaction amount |
    | `2`   | Partial Refund | The portion you want to return  |

    For a partial refund, the `amount` must be less than or equal to the original transaction amount.
  </Step>

  <Step title="Send the Refund Request">
    Send a `POST` request containing the original transaction identifiers, the amount, the refund type, and a message explaining why the refund is being issued.

    <CodeGroup>
      ```json Request Body theme={null}
      {
        "trackid": "1000",
        "refrence_code": "2021060819283746732378",
        "amount": "70",
        "refund_type": "1",
        "message": "This is the message why to refund the amount"
      }
      ```

      ```php PHP theme={null}
      <?php

      $privateKey = 'YOUR_PRIVATE_KEY';
      $endpoint   = 'https://development.payzah.net/ws/paymentgateway/refund';

      $payload = [
          'trackid'        => '1000',
          'refrence_code'  => '2021060819283746732378',
          'amount'         => '70',
          'refund_type'    => '1',   // 1 = Full Refund, 2 = Partial Refund
          'message'        => 'This is the message why to refund the amount',
      ];

      $ch = curl_init($endpoint);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      curl_setopt($ch, CURLOPT_POST, true);
      curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
      curl_setopt($ch, CURLOPT_HTTPHEADER, [
          'Content-Type: application/json',
          'Authorization: ' . base64_encode($privateKey),
      ]);

      $response = curl_exec($ch);
      curl_close($ch);

      $result = json_decode($response, true);
      ```

      ```javascript Node.js theme={null}
      const https = require('https');

      const privateKey = 'YOUR_PRIVATE_KEY';
      const payload = JSON.stringify({
        trackid:       '1000',
        refrence_code: '2021060819283746732378',
        amount:        '70',
        refund_type:   '1',   // 1 = Full Refund, 2 = Partial Refund
        message:       'This is the message why to refund the amount',
      });

      const options = {
        hostname: 'development.payzah.net',
        path:     '/ws/paymentgateway/refund',
        method:   'POST',
        headers: {
          'Content-Type':  'application/json',
          'Authorization': Buffer.from(privateKey).toString('base64'),
        },
      };

      const req = https.request(options, (res) => {
        let data = '';
        res.on('data', (chunk) => { data += chunk; });
        res.on('end', () => {
          const result = JSON.parse(data);
          // Check result.status before confirming the refund to your customer
        });
      });

      req.write(payload);
      req.end();
      ```

      ```bash cURL theme={null}
      curl --request POST \
        --url https://development.payzah.net/ws/paymentgateway/refund \
        --header 'Content-Type: application/json' \
        --header "Authorization: $(echo -n 'YOUR_PRIVATE_KEY' | base64)" \
        --data '{
          "trackid": "1000",
          "refrence_code": "2021060819283746732378",
          "amount": "70",
          "refund_type": "1",
          "message": "This is the message why to refund the amount"
        }'
      ```
    </CodeGroup>

    <Note>
      Note the spelling of `refrence_code`. The field name is `refrence_code`, not `reference_code`.
    </Note>
  </Step>

  <Step title="Read the Response">
    A successful submission returns `status: true`. Any other value means the refund was not accepted and no funds have been returned.

    ```json Success Response theme={null}
    {
      "status": true,
      "message": "Refund request is submited successfully",
      "code": 10012
    }
    ```

    ```json Failure Response theme={null}
    {
      "status": false,
      "message": "No Record found for the provided details",
      "code": 10012
    }
    ```

    A failure most commonly means the `trackid` and `refrence_code` do not match an existing successful transaction. Verify both values against your original payment record before retrying.

    <Warning>
      Never confirm a refund to your customer based on the HTTP request completing. Check the `status` field explicitly — a `200` response with `status: false` means nothing was refunded.
    </Warning>
  </Step>

  <Step title="Confirm the Transaction State">
    The success response confirms that your refund request was *submitted*, not that it has fully settled. Call the [Get Payment Details API](/docs/api-reference/payment-status) with the same `trackid` and `payment_id` to check the transaction's current state.

    ```json Request Body theme={null}
    {
      "trackid": "29",
      "payment_id": "2026073014151522900"
    }
    ```

    Use this call for reconciliation, for customer service enquiries, and before issuing any further refund against the same transaction.
  </Step>
</Steps>

## How Long Refunds Take

Submitting a refund is instant. Funds reaching the customer is not — the timing depends on the payment method used for the original transaction.

| Original payment method | Time for funds to reach the customer |
| ----------------------- | ------------------------------------ |
| K-Net                   | Around 1 business day                |
| Visa / Mastercard       | Up to 14 days                        |

<Note>
  These windows depend on the customer's issuing bank, so treat them as typical rather than guaranteed. Weekends and public holidays extend them.
</Note>

Tell your customers this upfront. "Your refund has been processed and will appear within 14 days" prevents far more support tickets than any amount of after-the-fact explaining — particularly for card refunds, where a customer who expects same-day money will assume something has gone wrong.

### What You Will See as a Merchant

The refund moves through two states in your Payzah dashboard:

| Status               | Meaning                                                |
| -------------------- | ------------------------------------------------------ |
| **Refund requested** | Your request was received and is queued for processing |
| **Refunded**         | The refund has been processed                          |

A status of *Refund requested* does not mean the customer has their money yet — it means Payzah has accepted the instruction. Wait for *Refunded* before treating the refund as complete in your own records.

### Why Settlement Timing Matters

Understanding where the money physically sits explains why some refunds clear faster than others.

When a customer pays, the funds are debited from them immediately and held by Payzah. They are settled into your merchant account the **next business day**.

| When you request a refund                                  | What happens                                                                                          |
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| **Before settlement** — same day as the payment            | Payzah still holds the funds and returns them to the customer directly. The simplest and fastest path |
| **After settlement** — the funds have reached your account | The refund is processed against your settled balance                                                  |

<Tip>
  If you already know an order will be refunded — a cancellation, a failed delivery, an obvious duplicate — process it the same day. Refunding before settlement keeps the money on a single path back to the customer instead of routing it out to you and back again.
</Tip>

## Request Field Reference

| Sr. No. | Field           | Type         | Mandatory | Description                                                                                                      |
| ------- | --------------- | ------------ | --------- | ---------------------------------------------------------------------------------------------------------------- |
| 1       | `trackid`       | Alphanumeric | Yes       | Merchant Track ID used during the original payment transaction                                                   |
| 2       | `refrence_code` | Alphanumeric | Yes       | Payzah Reference Code received after the successful payment transaction                                          |
| 3       | `amount`        | Numeric      | Yes       | Refund amount. For full refunds, the original transaction amount; for partial refunds, the amount to be refunded |
| 4       | `refund_type`   | Numeric      | Yes       | `1` = Full Refund, `2` = Partial Refund                                                                          |
| 5       | `message`       | Alphanumeric | Yes       | Reason or message describing why the refund is being requested                                                   |

## Best Practices

<AccordionGroup>
  <Accordion title="Verify before you refund" icon="magnifying-glass">
    Always confirm the original transaction is `CAPTURED` before submitting a refund. Requests against transactions that were voided, cancelled, or never captured will be rejected.
  </Accordion>

  <Accordion title="Guard against duplicate submissions" icon="copy">
    Protect your refund endpoint against double-clicks, retries, and repeated background jobs. Payzah does not deduplicate refund requests for you — track which transactions you have already refunded on your side.
  </Accordion>

  <Accordion title="Log every request and response" icon="file-lines">
    Store the `trackid`, `refrence_code`, `amount`, `refund_type`, and the complete API response for every refund. These records are essential for reconciliation, chargeback handling, and support enquiries.
  </Accordion>

  <Accordion title="Write meaningful refund messages" icon="message">
    The `message` field is stored against the transaction. Use a clear, specific reason — for example, an order number and cause — rather than a generic placeholder. It makes reconciliation and support investigations considerably faster.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Payment Status" icon="magnifying-glass" href="/docs/api-reference/payment-status">
    Verify a transaction's current state before and after issuing a refund.
  </Card>

  <Card title="Response Codes" icon="triangle-exclamation" href="/docs/api-reference/response-codes">
    Full reference for every Payzah error code and payment status value.
  </Card>
</CardGroup>
