Refund Payment
Initiate a refund request on a completed payment with a received status. A payment request can be refunded multiple times; each refund is recorded separately in refund_records instead of overwriting the previous one. This endpoint processes a refund using the available balance in your account. If there is insufficient balance, you will either receive a top-up notification or need to wait for additional funds from new payments (Payins) to complete the refund.
Refunds can be partial or full, depending on the refund_amount specified. A reason for the refund is required for tracking and documentation purposes.
curl --request POST \
--url https://api.cleverhub.co/api/v1/payment_requests/refund \
--header 'Content-Type: application/json' \
--header 'app-id: <api-key>' \
--header 'secret-key: <api-key>' \
--data '
{
"payment_request_id": 1,
"reason": "Partial refund due to customer request",
"refund_amount": 100,
"external_id": "refund-req-2024-12-31-0001"
}
'import requests
url = "https://api.cleverhub.co/api/v1/payment_requests/refund"
payload = {
"payment_request_id": 1,
"reason": "Partial refund due to customer request",
"refund_amount": 100,
"external_id": "refund-req-2024-12-31-0001"
}
headers = {
"app-id": "<api-key>",
"secret-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'app-id': '<api-key>',
'secret-key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
payment_request_id: 1,
reason: 'Partial refund due to customer request',
refund_amount: 100,
external_id: 'refund-req-2024-12-31-0001'
})
};
fetch('https://api.cleverhub.co/api/v1/payment_requests/refund', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.cleverhub.co/api/v1/payment_requests/refund",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'payment_request_id' => 1,
'reason' => 'Partial refund due to customer request',
'refund_amount' => 100,
'external_id' => 'refund-req-2024-12-31-0001'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"app-id: <api-key>",
"secret-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.cleverhub.co/api/v1/payment_requests/refund"
payload := strings.NewReader("{\n \"payment_request_id\": 1,\n \"reason\": \"Partial refund due to customer request\",\n \"refund_amount\": 100,\n \"external_id\": \"refund-req-2024-12-31-0001\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("app-id", "<api-key>")
req.Header.Add("secret-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.cleverhub.co/api/v1/payment_requests/refund")
.header("app-id", "<api-key>")
.header("secret-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"payment_request_id\": 1,\n \"reason\": \"Partial refund due to customer request\",\n \"refund_amount\": 100,\n \"external_id\": \"refund-req-2024-12-31-0001\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.cleverhub.co/api/v1/payment_requests/refund")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["app-id"] = '<api-key>'
request["secret-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"payment_request_id\": 1,\n \"reason\": \"Partial refund due to customer request\",\n \"refund_amount\": 100,\n \"external_id\": \"refund-req-2024-12-31-0001\"\n}"
response = http.request(request)
puts response.read_body{
"refund_payid": "refund_payid@example.com",
"refund_amount": 100,
"reason": "Partial refund due to customer request",
"payment_request": {
"id": 123456,
"uuid": "pi_as2ks12xa2",
"balance_id": "HDCHJSS",
"name": "John Doe",
"request_payid": "payid123@example.com",
"merchant_name": "Merchant Co.",
"gst": true,
"amount": "100.0",
"total": "110.0",
"gst_amount": "10.0",
"expired_at": "2024-12-31T23:59:59Z",
"external_id": "custom-id-12345",
"cashback_amount": "5.0",
"pay_by": "2024-12-30T23:59:59Z",
"paid_at": "2024-12-25T12:34:56Z",
"status": "pending",
"description": "Payment for invoice #1234",
"nonce": "unique_nonce_string",
"stage": "overpaid",
"refund_information": {
"refund_payid": "sample@payid.com",
"refund_amount": 0.1,
"request_date": "2024-12-31T23:59:59Z",
"reason": "Broken product"
},
"refund_records": [
{
"uuid": "rf_as231sdas12",
"status": "return_pending",
"refund_amount": 0.1,
"request_date": "2024-12-31T23:59:59Z",
"reason": "Broken product"
}
],
"sender_details": {
"reference": "SenderRef123",
"description": "Payment from John Doe",
"bsb": "123456",
"account_number": "987654321",
"account_name": "John Doe"
},
"short_invoice_url": "https://short.example.com/invoice/123456",
"invoice_url": "https://example.com/invoice/123456",
"metadata": {
"custom_note": "Priority customer"
}
}
}Authorizations
A unique identifier assigned to each application.
A secure token associated with the app-id.
Body
The unique identifier for the original payment request that is to be refunded.
1
The reason for the refund, which must be at least 5 characters long. This is required for record-keeping and can help in cases of partial refunds.
"Partial refund due to customer request"
The amount to be refunded. If this is not specified, the refund will default to the total original payment amount.
100
An idempotency key provided by the client to safely retry this request multiple times without creating duplicate refunds. If a request with the same external_id is received again for the same payment request, the result of the original refund is returned instead of processing a new one.
"refund-req-2024-12-31-0001"
Response
Refund initiated successfully.
The PayID to which the refund amount should be paid to complete the refund process. Note: this field is deprecated and will be removed in a few upcoming versions.
"refund_payid@example.com"
The total amount that was refunded.
100
The reason provided for the refund.
"Partial refund due to customer request"
Show child attributes
Show child attributes
curl --request POST \
--url https://api.cleverhub.co/api/v1/payment_requests/refund \
--header 'Content-Type: application/json' \
--header 'app-id: <api-key>' \
--header 'secret-key: <api-key>' \
--data '
{
"payment_request_id": 1,
"reason": "Partial refund due to customer request",
"refund_amount": 100,
"external_id": "refund-req-2024-12-31-0001"
}
'import requests
url = "https://api.cleverhub.co/api/v1/payment_requests/refund"
payload = {
"payment_request_id": 1,
"reason": "Partial refund due to customer request",
"refund_amount": 100,
"external_id": "refund-req-2024-12-31-0001"
}
headers = {
"app-id": "<api-key>",
"secret-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'app-id': '<api-key>',
'secret-key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
payment_request_id: 1,
reason: 'Partial refund due to customer request',
refund_amount: 100,
external_id: 'refund-req-2024-12-31-0001'
})
};
fetch('https://api.cleverhub.co/api/v1/payment_requests/refund', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.cleverhub.co/api/v1/payment_requests/refund",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'payment_request_id' => 1,
'reason' => 'Partial refund due to customer request',
'refund_amount' => 100,
'external_id' => 'refund-req-2024-12-31-0001'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"app-id: <api-key>",
"secret-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.cleverhub.co/api/v1/payment_requests/refund"
payload := strings.NewReader("{\n \"payment_request_id\": 1,\n \"reason\": \"Partial refund due to customer request\",\n \"refund_amount\": 100,\n \"external_id\": \"refund-req-2024-12-31-0001\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("app-id", "<api-key>")
req.Header.Add("secret-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.cleverhub.co/api/v1/payment_requests/refund")
.header("app-id", "<api-key>")
.header("secret-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"payment_request_id\": 1,\n \"reason\": \"Partial refund due to customer request\",\n \"refund_amount\": 100,\n \"external_id\": \"refund-req-2024-12-31-0001\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.cleverhub.co/api/v1/payment_requests/refund")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["app-id"] = '<api-key>'
request["secret-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"payment_request_id\": 1,\n \"reason\": \"Partial refund due to customer request\",\n \"refund_amount\": 100,\n \"external_id\": \"refund-req-2024-12-31-0001\"\n}"
response = http.request(request)
puts response.read_body{
"refund_payid": "refund_payid@example.com",
"refund_amount": 100,
"reason": "Partial refund due to customer request",
"payment_request": {
"id": 123456,
"uuid": "pi_as2ks12xa2",
"balance_id": "HDCHJSS",
"name": "John Doe",
"request_payid": "payid123@example.com",
"merchant_name": "Merchant Co.",
"gst": true,
"amount": "100.0",
"total": "110.0",
"gst_amount": "10.0",
"expired_at": "2024-12-31T23:59:59Z",
"external_id": "custom-id-12345",
"cashback_amount": "5.0",
"pay_by": "2024-12-30T23:59:59Z",
"paid_at": "2024-12-25T12:34:56Z",
"status": "pending",
"description": "Payment for invoice #1234",
"nonce": "unique_nonce_string",
"stage": "overpaid",
"refund_information": {
"refund_payid": "sample@payid.com",
"refund_amount": 0.1,
"request_date": "2024-12-31T23:59:59Z",
"reason": "Broken product"
},
"refund_records": [
{
"uuid": "rf_as231sdas12",
"status": "return_pending",
"refund_amount": 0.1,
"request_date": "2024-12-31T23:59:59Z",
"reason": "Broken product"
}
],
"sender_details": {
"reference": "SenderRef123",
"description": "Payment from John Doe",
"bsb": "123456",
"account_number": "987654321",
"account_name": "John Doe"
},
"short_invoice_url": "https://short.example.com/invoice/123456",
"invoice_url": "https://example.com/invoice/123456",
"metadata": {
"custom_note": "Priority customer"
}
}
}