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

# Create an Instant Refund

> Create an Instant Refund using Razorpay Refunds API.

<div style={{display:"flex",flexWrap:"wrap",alignItems:"center",gap:"0.35rem 0.9rem",border:"1px solid rgba(128,128,128,0.28)",borderRadius:"0.5rem",padding:"0.45rem 0.75rem",margin:"0 0 1.25rem",fontSize:"0.875rem"}}>
  <span style={{fontWeight:600}}>Available in</span>
  <span>🇮🇳 India</span>
  <span>🇸🇬 Singapore</span>
  <span>🇺🇸 United States</span>
</div>

Use this endpoint to process refunds instantaneously to your customers. The instant refund is enabled by default for your account. You should set the refund speed to `optimum` when creating a refund request to ensure refunds are processed instantly. We will consider the default speed if you do not specify the same during the refund request. Know more about [setting the default speed](/docs/sg/payments/refunds/refund-speed) from the Dashboard.

* Refunds will be processed at an optimal speed based on Razorpay's internal fund transfer logic.
* If the refund can be processed instantly, Razorpay will do so irrespective of the payment method used to make the payment.

| **`speed` attribute in Request** | **`speed_processed` attribute in Response** | **Description**                                                    |
| -------------------------------- | ------------------------------------------- | ------------------------------------------------------------------ |
| `normal`                         | `normal`                                    | Refund processed via `normal` speed.                               |
| `optimum`                        | `normal`                                    | A faster speed was not available, so processed via `normal` speed. |

Once the refund moves to the `processed` state, the refund response displays the `speed_processed` parameter, the final state of the refund.

<RequestExample>
  ```bash Curl theme={null}
  curl -u [YOUR_KEY_ID]:[YOUR_KEY_SECRET] \
  -X POST https://api.razorpay.com/v1/payments/pay_29QQoUBi66xm2f/refund \
  -H 'Content-Type: application/json' \
  -d '{
    "amount":500100,
    "speed":"optimum",
    "receipt":"Receipt No. 31",
    "notes":{
      "notes_key_1":"Tea, Earl Grey, Hot",
      "notes_key_2":"Tea, Earl Grey… decaf."
    }
  }'
  ```

  ```java Java theme={null}
  RazorpayClient razorpay = new RazorpayClient("[YOUR_KEY_ID]", "[YOUR_KEY_SECRET]");

  String paymentId = "pay_29QQoUBi66xm2f";

  JSONObject refundRequest = new JSONObject();
  refundRequest.put("amount",100);
  refundRequest.put("speed","optimum");
  refundRequest.put("receipt","Receipt No. #31");
  JSONObject notes = new JSONObject();
  notes.put("notes_key_1","Tea, Earl Grey, Hot");
  notes.put("notes_key_2","Tea, Earl Grey… decaf.");
  refundRequest.put("notes",notes);

  Payment payment = razorpay.payments.refund(paymentId,refundRequest);
  ```

  ```php PHP theme={null}
  $api = new Api($key_id, $secret);

  $api->payment->fetch($paymentId)->refund(array("amount"=> "100","speed"=>"optimum","notes"=>array("notes_key_1"=>"Beam me up Scotty.", "notes_key_2"=>"Engage"),"receipt"=>"Receipt No. 31"));
  ```

  ```python Python theme={null}
  import razorpay
  client = razorpay.Client(auth=("YOUR_ID", "YOUR_SECRET"))

  client.payment.refund(paymentId,{
    "amount": "100",
    "speed": "optimum",
    "notes": {
      "notes_key_1": "Beam me up Scotty.",
      "notes_key_2": "Engage"
    },
    "receipt": "Receipt No. 31"
  })
  ```

  ```go Go theme={null}
  import ( razorpay "github.com/razorpay/razorpay-go" )
  client := razorpay.NewClient("YOUR_KEY_ID", "YOUR_SECRET")

  data := map[string]interface{}{
  	"speed": "optimum",
    "notes": map[string]interface{}{
      "key_1": "value1",
      "key_2": "value2"
    },
  	"receipt": "Receipt No. #12",
  }
  body, err := client.Payment.Refund("<paymentId>",100, data, nil)
  ```

  ```ruby Ruby theme={null}
  require "razorpay"
  Razorpay.setup('YOUR_KEY_ID', 'YOUR_SECRET')

  paymentId = "pay_29QQoUBi66xm2f"

  para_attr = {
    "amount": "100",
    "speed": "optimum",
    "notes": {
      "notes_key_1": "Beam me up Scotty.",
      "notes_key_2": "Engage"
    },
    "receipt": "Receipt No. 31"
  }
  Razorpay::Payment.fetch(paymentId).refund(para_attr)
  ```

  ```javascript Node.js theme={null}
  var instance = new Razorpay({ key_id: 'YOUR_KEY_ID', key_secret: 'YOUR_SECRET' })

  instance.payments.refund(paymentId,{
    "amount": "100",
    "speed": "optimum",
    "notes": {
      "notes_key_1": "Beam me up Scotty.",
      "notes_key_2": "Engage"
    },
    "receipt": "Receipt No. 31"
  })
  ```

  ```csharp .NET theme={null}
  //initialize the SDK client
  RazorpayClient client = new RazorpayClient("[YOUR_KEY_ID]", "[YOUR_KEY_SECRET]");

  String paymentId = "pay_Z6t7VFTb9xHeOs";

  Dictionary<string, object> refundRequest = new Dictionary<string, object>();
  refundRequest.Add("amount",100);
  refundRequest.Add("speed","optimum");
  Dictionary<string, object> notes = new Dictionary<string, object>();
  notes.Add("notes_key_1", "Tea, Earl Grey, Hot");
  notes.Add("notes_key_2", "Tea, Earl Grey… decaf.");
  refundRequest.Add("notes", notes);
  refundRequest.Add("receipt","Receipt No. 31");

  Refund refund = client.Payment.Fetch(paymentId).Refund(refundRequest);
  ```

  ```bash CLI theme={null}
  razorpay refunds create pay_ABC123 --amount 50000 --speed optimum
  ```
</RequestExample>

<ResponseExample>
  ```json Success theme={null}
  {
    "id": "rfnd_FP8R8EGjGbPkVb",
    "entity": "refund",
    "amount": 500100,
    "currency": "INR",
    "payment_id": "pay_29QQoUBi66xm2f",
    "notes": {
      "notes_key_1": "Tea, Earl Grey, Hot",
      "notes_key_2": "Tea, Earl Grey… decaf."
    },
    "receipt": "Receipt No. 31",
    "acquirer_data": {
      "arn": null
    },
    "created_at": 1597078914,
    "batch_id": null,
    "status": "processed",
    "speed_processed": "normal",
    "speed_requested": "optimum"
  }
  ```

  ```json Failure theme={null}
  {
      "error": {
          "code": "BAD_REQUEST_ERROR",
          "description": "_29QQoUBi66xm2f is not a valid id",
          "source": "business",
          "step": "payment_initiation",
          "reason": "input_validation_failed",
          "metadata": {}
      }
  }
  ```
</ResponseExample>

## Path Parameters

<ParamField path="id" type="string" required>
  The unique identifier of the payment which needs to be refunded.
</ParamField>

## Request Parameters

<ParamField body="amount" type="integer">
  The amount to be refunded. Amount should be in the smallest unit of the currency in which the payment was made. **Required in case of partial refund**.

  * For a **partial refund**, enter a value lesser than the payment amount. For example, if the payment amount is ₹1200, and you want to refund only ₹200, you must pass `20000`.
  * In case of a **full refund**, enter the full payment amount. If `amount` parameter is not passed, the entire payment amount will be refunded.
</ParamField>

<Check>
  **What's New**

  Refund amounts of ₹1 or lower are now supported.
</Check>

<ParamField body="speed" type="string" required>
  Here, it must be `optimum`. Indicates that the refund will be processed at an optimal speed based on Razorpay's internal fund transfer logic.

  * If the refund can be processed instantly, Razorpay will do so, irrespective of the payment method used to make the payment.
  * If an instant refund is not possible, Razorpay will initiate a refund that is processed at the normal speed.
</ParamField>

<ParamField body="notes" type="json object">
  This is a key-value pair that can be used to store additional information about the entity. It can hold a maximum of 15 key-value pairs, 256 characters (maximum) each. For example, `"note_key": "Beam me up Scotty”`.
</ParamField>

<ParamField body="receipt" type="string">
  A unique identifier provided by you for your internal reference.
</ParamField>

## Response Parameters

<ResponseField name="id" type="string">
  The unique identifier of the refund. For example, `rfnd_FgRAHdNOM4ZVbO`.
</ResponseField>

<ResponseField name="entity" type="string">
  Indicates the type of entity. Here, it is `refund`.
</ResponseField>

<ResponseField name="amount" type="integer">
  The amount to be refunded (in the smallest unit of currency). <br /> For example, if the refund value is ₹30 it will be `3000`.
</ResponseField>

<ResponseField name="currency" type="string">
  The currency of payment amount for which the refund is initiated. Check the list of [supported currencies](/docs/sg/payments/international-payments#supported-currencies).
</ResponseField>

<ResponseField name="payment_id" type="string">
  The unique identifier of the payment for which a refund is initiated. For example, `pay_FgR9UMzgmKDJRi`.
</ResponseField>

<ResponseField name="created_at" type="integer">
  Unix timestamp at which the refund was created. For example, `1600856650`.
</ResponseField>

<ResponseField name="batch_id" type="string">
  This parameter is populated if the refund was created as part of a batch upload. For example, `batch_00000000000001`.
</ResponseField>

<ResponseField name="notes" type="json object">
  Key-value store for storing your reference data. A maximum of 15 key-value pairs can be included. For example, `"note_key": "Beam me up Scotty”`.
</ResponseField>

<ResponseField name="receipt" type="string">
  A unique identifier provided by you for your internal reference.
</ResponseField>

<ResponseField name="acquirer_data" type="array">
  A dynamic array consisting of a unique reference number (either RRN, ARN or UTR) that is provided by the banking partner when a refund is processed. This reference number can be used by the customer to track the status of the refund with the bank.
</ResponseField>

<ResponseField name="status" type="string">
  Indicates the state of the refund. Possible values:

  * `pending`: This state indicates that Razorpay is attempting to process the refund.
  * `processed`: This is the final state of the refund.
  * `failed`: A refund can attain the failed state in the following scenarios:<br />
    * Normal refund is not possible for a payment which is more than 6 months old.<br />
    * Instant Refund can sometimes fail because of customer's account or bank-related issues.
</ResponseField>

<ResponseField name="speed_requested" type="string">
  The processing mode of the refund seen in the refund response. <br /> This attribute is seen in the refund response only if the `speed` parameter is set in the refund request.<br />Possible values:

  * `normal`: Indicates that the refund will be processed via the normal speed. The refund will take 5-7 working days.
  * `optimum`: Indicates that the refund will be processed at an optimal speed based on Razorpay's internal fund transfer logic.
    * If the refund can be processed instantly, Razorpay will do so, irrespective of the payment method used to make the payment.
    * If an instant refund is not possible, Razorpay will initiate a refund that is processed at the normal speed.
</ResponseField>

<ResponseField name="speed_processed" type="string">
  This is a parameter in the response which describes the mode used to process a refund. <br /> This attribute is seen in the refund response only if the `speed` parameter is set in the refund request. Possible values:

  * `instant`: Indicates that the refund has been processed instantly via fund transfer.
  * `normal`: Indicates that the refund has been processed by the payment processing partner. The refund will take 5-7 working days.
</ResponseField>

## Errors

<AccordionGroup>
  <Accordion title="The API {key/secret} provided is invalid.">
    **Code:** `4xx`

    The API credentials passed in the API call differ from the ones generated on the Dashboard.

    **Solution:** The API keys must be active and entered correctly with no whitespace before or after.
  </Accordion>

  <Accordion title="{Payment_id} is not a valid id.">
    **Code:** `400`

    The `payment_id` provided is invalid.

    **Solution:** Use a valid `payment_id`.
  </Accordion>

  <Accordion title="The requested URL was not found on the server.">
    **Code:** `400`

    Possible reasons:

    * The URL is wrong or is missing something.
    * A POST API is executed by GET method.

    **Solution:**

    * Ensure that the URL is correct and complete.
    * Use the correct method, that is, POST.
  </Accordion>

  <Accordion title="{any Extra field} is/are not required and should not be sent.">
    **Code:** `400`

    An additional or unrequired parameter is passed.

    **Solution:** Ensure that you only pass the required parameters in the request body.
  </Accordion>

  <Accordion title="The refund amount provided is greater than amount captured.">
    **Code:** `400`

    The refund amount entered is more than the amount captured.

    **Solution:** Enter an amount equal to or less than the amount captured.
  </Accordion>

  <Accordion title="The payment has been fully refunded already.">
    **Code:** `400`

    The `payment_id` has already been refunded fully.

    **Solution:** Use a `payment_id` that has not been fully refunded.
  </Accordion>

  <Accordion title="Your account does not have enough balance to carry out the refund operation.">
    **Code:** `400`

    The merchant's Razorpay balance is lower than the refund amount being requested. Refunds are paid out from the merchant balance, not directly from the original payment.

    **Solution:** Add funds to your Razorpay account from the Dashboard or capture additional payments to increase your balance, then retry the refund.
  </Accordion>

  <Accordion title="The payment status should be captured for action to be taken.">
    **Code:** `400`

    The payment is not in the `captured` state. This typically happens because it failed, is still `authorized`, was `cancelled` or has already been fully refunded. Refunds can only be initiated against payments that are currently in the `captured` state.

    **Solution:** Confirm the payment status using `GET /v1/payments/:id` before refunding. Only attempt refunds on payments where `status` is `captured`.
  </Accordion>

  <Accordion title="Amount cannot be blank.">
    **Code:** `400`

    The `amount` field was passed as `0`. Razorpay treats `0` as a missing value rather than a zero-amount refund. Omitting `amount` is valid and triggers a full refund.

    **Solution:** Pass `amount` as a positive integer in currency subunits (paise for INR).
  </Accordion>

  <Accordion title="Instant refund not supported for the payment.">
    **Code:** `400`

    The payment cannot be refunded at instant speed — typically because the underlying payment method, gateway or acquirer does not support instant refunds.

    **Solution:** Retry the refund without `speed: optimum`, or omit the `speed` parameter to fall back to a normal refund.
  </Accordion>

  <Accordion title="Refund is currently not supported for this payment method.">
    **Code:** `400`

    The payment method used for this transaction (for example, Cash on Delivery, offline, BharatQR) does not support refunds via API.

    **Solution:** Reconcile the refund offline with the customer. Do not retry the API call.
  </Accordion>

  <Accordion title="Partial refund is currently not supported for this payment method.">
    **Code:** `400`

    The gateway or payment method used for this payment supports only full refunds, not partial ones.

    **Solution:** Issue a full refund by omitting the `amount` parameter, or pass the full captured amount.
  </Accordion>

  <Accordion title="Refunds cannot be created on your account.">
    **Code:** `400`

    Refunds are disabled at the account level for the merchant making the request.

    **Solution:** Contact Razorpay support to enable refunds on your account.
  </Accordion>

  <Accordion title="Refunds cannot be created on your account for {payment method} payments.">
    **Code:** `400`

    Refunds are disabled on your account for the specific payment method used (for example, `card`, `upi`, `netbanking`, `wallet`, `emi`, `pay later`). The placeholder is replaced with the actual method name in the response.

    **Solution:** Contact Razorpay support to enable refunds for that payment method, or use a different payment method.
  </Accordion>

  <Accordion title="Refund has already been processed.">
    **Code:** `400`

    A refund for this payment has already moved to a final state and cannot be re-initiated using the same request.

    **Solution:** Use the Fetch Refunds API to check the existing refund status before retrying.
  </Accordion>

  <Accordion title="The refund on this payment is blocked due to ongoing dispute investigation.">
    **Code:** `400`

    The payment is under an active dispute (chargeback) and cannot be refunded until the dispute is resolved.

    **Solution:** Wait for the dispute to be resolved before initiating a refund. Track the dispute status from the Razorpay Dashboard.
  </Accordion>

  <Accordion title="Duplicate receipt found for this refund request.">
    **Code:** `400`

    The value passed in the `receipt` parameter has already been used for an earlier refund on the same payment. `receipt` is treated as an idempotency key.

    **Solution:** Pass a unique value in `receipt`, or check the existing refund created with the same receipt before retrying.
  </Accordion>

  <Accordion title="Notes validation failed.">
    **Code:** `400`

    The `notes` object failed validation. Possible reasons: more than 15 keys, a key longer than 255 characters, or a value longer than 512 characters.

    **Solution:** Limit `notes` to a maximum of 15 key-value pairs, keep each key under 256 characters, and each value under 512 characters.
  </Accordion>

  <Accordion title="Request failed because another payment operation is in progress.">
    **Code:** `400`

    A concurrent operation (such as another refund attempt or a capture) is already running for the same payment.

    **Solution:** Wait a few seconds and retry. If the issue persists, fetch the payment and its existing refunds to confirm the current state before retrying.
  </Accordion>

  <Accordion title="Void is not supported for partial refunds.">
    **Code:** `400`

    A partial-amount refund was requested on a payment that is still in the `authorized` state. A void can only be performed for the full authorised amount.

    **Solution:** Either capture the payment first and then issue a partial refund, or void the full authorised amount by omitting the `amount` parameter.
  </Accordion>
</AccordionGroup>
