Create Refund
curl --request POST \
--url https://api.fyatu.com/api/v3/collections/{collectionId}/refund \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"mode": "FULL",
"reason": "CUSTOMER_REQUEST"
}
'import requests
url = "https://api.fyatu.com/api/v3/collections/{collectionId}/refund"
payload = {
"mode": "FULL",
"reason": "CUSTOMER_REQUEST"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({mode: 'FULL', reason: 'CUSTOMER_REQUEST'})
};
fetch('https://api.fyatu.com/api/v3/collections/{collectionId}/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.fyatu.com/api/v3/collections/{collectionId}/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([
'mode' => 'FULL',
'reason' => 'CUSTOMER_REQUEST'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.fyatu.com/api/v3/collections/{collectionId}/refund"
payload := strings.NewReader("{\n \"mode\": \"FULL\",\n \"reason\": \"CUSTOMER_REQUEST\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.fyatu.com/api/v3/collections/{collectionId}/refund")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"mode\": \"FULL\",\n \"reason\": \"CUSTOMER_REQUEST\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.fyatu.com/api/v3/collections/{collectionId}/refund")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"mode\": \"FULL\",\n \"reason\": \"CUSTOMER_REQUEST\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"status": 201,
"message": "<string>",
"data": {
"refundId": "<string>",
"collectionId": "<string>",
"amount": 123,
"currency": "<string>",
"reason": "<string>",
"reasonDescription": "<string>",
"recipient": {
"clientId": "<string>",
"name": "<string>"
},
"createdAt": "2023-11-07T05:31:56Z"
},
"meta": {
"requestId": "req_abc123def456",
"timestamp": "2023-11-07T05:31:56Z"
}
}{
"success": false,
"status": 400,
"message": "Validation failed",
"error": {
"code": "VALIDATION_ERROR",
"details": [
{
"field": "currency",
"message": "Currency is required"
}
]
},
"meta": {
"requestId": "req_abc123",
"timestamp": "2026-01-05T10:30:00+00:00"
}
}{
"success": false,
"status": 401,
"message": "Unable to identify business",
"error": {
"code": "AUTH_TOKEN_INVALID"
},
"meta": {
"requestId": "req_abc123",
"timestamp": "2026-01-05T10:30:00+00:00"
}
}{
"success": false,
"status": 401,
"message": "Invalid credentials",
"error": {
"code": "AUTH_INVALID_CREDENTIALS",
"details": [
{
"field": "appId",
"message": "AppId is required"
}
]
},
"meta": {
"requestId": "req_abc123def456",
"timestamp": "2023-11-07T05:31:56Z"
}
}{
"success": false,
"status": 404,
"message": "Wallet not found",
"error": {
"code": "RESOURCE_NOT_FOUND"
},
"meta": {
"requestId": "req_abc123",
"timestamp": "2026-01-05T10:30:00+00:00"
}
}Create Refund
Create a full or partial refund for a completed collection. Specify amount, reason, and recipient. POST /refunds.
POST
/
collections
/
{collectionId}
/
refund
Create Refund
curl --request POST \
--url https://api.fyatu.com/api/v3/collections/{collectionId}/refund \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"mode": "FULL",
"reason": "CUSTOMER_REQUEST"
}
'import requests
url = "https://api.fyatu.com/api/v3/collections/{collectionId}/refund"
payload = {
"mode": "FULL",
"reason": "CUSTOMER_REQUEST"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({mode: 'FULL', reason: 'CUSTOMER_REQUEST'})
};
fetch('https://api.fyatu.com/api/v3/collections/{collectionId}/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.fyatu.com/api/v3/collections/{collectionId}/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([
'mode' => 'FULL',
'reason' => 'CUSTOMER_REQUEST'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.fyatu.com/api/v3/collections/{collectionId}/refund"
payload := strings.NewReader("{\n \"mode\": \"FULL\",\n \"reason\": \"CUSTOMER_REQUEST\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.fyatu.com/api/v3/collections/{collectionId}/refund")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"mode\": \"FULL\",\n \"reason\": \"CUSTOMER_REQUEST\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.fyatu.com/api/v3/collections/{collectionId}/refund")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"mode\": \"FULL\",\n \"reason\": \"CUSTOMER_REQUEST\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"status": 201,
"message": "<string>",
"data": {
"refundId": "<string>",
"collectionId": "<string>",
"amount": 123,
"currency": "<string>",
"reason": "<string>",
"reasonDescription": "<string>",
"recipient": {
"clientId": "<string>",
"name": "<string>"
},
"createdAt": "2023-11-07T05:31:56Z"
},
"meta": {
"requestId": "req_abc123def456",
"timestamp": "2023-11-07T05:31:56Z"
}
}{
"success": false,
"status": 400,
"message": "Validation failed",
"error": {
"code": "VALIDATION_ERROR",
"details": [
{
"field": "currency",
"message": "Currency is required"
}
]
},
"meta": {
"requestId": "req_abc123",
"timestamp": "2026-01-05T10:30:00+00:00"
}
}{
"success": false,
"status": 401,
"message": "Unable to identify business",
"error": {
"code": "AUTH_TOKEN_INVALID"
},
"meta": {
"requestId": "req_abc123",
"timestamp": "2026-01-05T10:30:00+00:00"
}
}{
"success": false,
"status": 401,
"message": "Invalid credentials",
"error": {
"code": "AUTH_INVALID_CREDENTIALS",
"details": [
{
"field": "appId",
"message": "AppId is required"
}
]
},
"meta": {
"requestId": "req_abc123def456",
"timestamp": "2023-11-07T05:31:56Z"
}
}{
"success": false,
"status": 404,
"message": "Wallet not found",
"error": {
"code": "RESOURCE_NOT_FOUND"
},
"meta": {
"requestId": "req_abc123",
"timestamp": "2026-01-05T10:30:00+00:00"
}
}Overview
Issue a full or partial refund for a completed collection. The refund amount is debited from your business wallet and credited to the payer’s Fyatu account. Important: Each collection can only be refunded once. Choose between a full refund or a partial refund at the time of processing.Path Parameters
| Parameter | Type | Description |
|---|---|---|
collectionId | string | The collection ID to refund |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
mode | string | No | Refund mode: FULL (default) or PARTIAL |
amount | number | Conditional | Required for PARTIAL mode. Refund amount in USD |
reason | string | No | Reason code (default: CUSTOMER_REQUEST). See available reasons |
Refund Modes
| Mode | Description | Amount Required |
|---|---|---|
FULL | Refunds the entire net amount automatically | No |
PARTIAL | Refunds a specific amount you specify | Yes |
Use
FULL mode to avoid calculation errors. The system automatically determines the maximum refundable amount (net amount after fees).Refund Reason Codes
Use one of these predefined reason codes in thereason field:
| Code | Description |
|---|---|
DUPLICATE_PAYMENT | Duplicate payment |
FRAUDULENT | Fraudulent transaction |
CUSTOMER_REQUEST | Customer requested refund (default) |
ORDER_CANCELLED | Order was cancelled |
PRODUCT_NOT_DELIVERED | Product/service not delivered |
PRODUCT_NOT_AS_DESCRIBED | Product/service not as described |
PRICING_ERROR | Pricing or billing error |
OTHER | Other reason |
GET /api/v3/refunds/reasons.
Response
| Field | Type | Description |
|---|---|---|
refundId | string | Unique refund identifier |
collectionId | string | Original collection ID |
amount | number | Refunded amount |
currency | string | Currency code |
reason | string | Reason code |
reasonDescription | string | Human-readable reason description |
status | string | COMPLETED |
recipient | object | Payer who received the refund |
recipient.clientId | string | Payer’s Fyatu client ID |
recipient.name | string | Payer’s name |
createdAt | string | Refund timestamp |
Refund Rules
- Only Completed Collections: Cannot refund pending, expired, or failed payments
- One Refund Per Collection: Each collection can only be refunded once
- Maximum Refundable: Net amount (original amount minus fees)
- Fees Non-Refundable: Processing fees are retained
- Wallet Balance Required: Your business wallet must have sufficient balance
Example Usage
<?php
$collectionId = 'col_a1b2c3d4e5f6';
// Full refund (recommended - automatically calculates amount)
$response = file_get_contents(
"https://api.fyatu.com/api/v3/collections/{$collectionId}/refund",
false,
stream_context_create([
'http' => [
'method' => 'POST',
'header' => [
'Content-Type: application/json',
'Authorization: Bearer ' . $accessToken
],
'content' => json_encode([
'mode' => 'FULL',
'reason' => 'CUSTOMER_REQUEST'
])
]
])
);
$result = json_decode($response, true);
if ($result['success']) {
echo "Refund successful: {$result['data']['refundId']}\n";
echo "Amount refunded: \${$result['data']['amount']}\n";
echo "Credited to: {$result['data']['recipient']['name']}\n";
}
// Partial refund example
$partialResponse = file_get_contents(
"https://api.fyatu.com/api/v3/collections/{$collectionId}/refund",
false,
stream_context_create([
'http' => [
'method' => 'POST',
'header' => [
'Content-Type: application/json',
'Authorization: Bearer ' . $accessToken
],
'content' => json_encode([
'mode' => 'PARTIAL',
'amount' => 10.00,
'reason' => 'PRODUCT_NOT_AS_DESCRIBED'
])
]
])
);
const collectionId = 'col_a1b2c3d4e5f6';
// Full refund (recommended - automatically calculates amount)
const response = await fetch(
`https://api.fyatu.com/api/v3/collections/${collectionId}/refund`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`
},
body: JSON.stringify({
mode: 'FULL',
reason: 'CUSTOMER_REQUEST'
})
}
);
const result = await response.json();
if (result.success) {
console.log(`Refund successful: ${result.data.refundId}`);
console.log(`Amount refunded: $${result.data.amount}`);
console.log(`Credited to: ${result.data.recipient.name}`);
}
// Partial refund example
const partialResponse = await fetch(
`https://api.fyatu.com/api/v3/collections/${collectionId}/refund`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`
},
body: JSON.stringify({
mode: 'PARTIAL',
amount: 10.00,
reason: 'PRODUCT_NOT_AS_DESCRIBED'
})
}
);
Example Response (Full Refund)
{
"success": true,
"status": 201,
"message": "Refund processed successfully",
"data": {
"refundId": "ref_a1b2c3d4e5f6",
"collectionId": "col_a1b2c3d4e5f6",
"amount": 25.00,
"currency": "USD",
"reason": "CUSTOMER_REQUEST",
"reasonDescription": "Customer requested refund",
"status": "COMPLETED",
"recipient": {
"clientId": "clt_a1b2c3d4e5f6",
"name": "Alice Example"
},
"createdAt": "2026-01-08T14:00:00+00:00"
},
"meta": {
"requestId": "req_refund123",
"timestamp": "2026-01-08T14:00:00+00:00"
}
}
Example Response (Partial Refund)
{
"success": true,
"status": 201,
"message": "Refund processed successfully",
"data": {
"refundId": "ref_b1c2d3e4f5a6",
"collectionId": "col_a1b2c3d4e5f6",
"amount": 10.00,
"currency": "USD",
"reason": "PRODUCT_NOT_AS_DESCRIBED",
"reasonDescription": "Product/service not as described",
"status": "COMPLETED",
"recipient": {
"clientId": "clt_a1b2c3d4e5f6",
"name": "Alice Example"
},
"createdAt": "2026-01-08T14:00:00+00:00"
},
"meta": {
"requestId": "req_refund124",
"timestamp": "2026-01-08T14:00:00+00:00"
}
}
Amount Exceeds Maximum
If you request a partial refund amount that exceeds the maximum refundable, the API will return an error with the maximum amount:{
"success": false,
"status": 400,
"message": "Requested amount (50.00) exceeds maximum refundable amount",
"error": {
"code": "AMOUNT_EXCEEDS_REFUNDABLE",
"maxRefundable": 24.25
}
}
Refund Amount Calculation
| Original Payment | $25.00 |
|---|---|
| Processing Fee | -$0.75 |
| Net Amount (Max Refundable) | $24.25 |
Processing fees are non-refundable. The maximum refund amount is the net amount you received, not the original payment amount.
Error Responses
| Error Code | HTTP | Description |
|---|---|---|
RESOURCE_NOT_FOUND | 404 | Collection not found |
INVALID_STATUS | 400 | Collection not in COMPLETED status |
AMOUNT_EXCEEDS_REFUNDABLE | 400 | Requested amount exceeds maximum (includes maxRefundable value) |
ALREADY_REFUNDED | 400 | Collection has already been refunded |
INSUFFICIENT_BALANCE | 402 | Business wallet balance too low |
PAYER_NOT_FOUND | 400 | Payer account no longer exists |
Collection Status After Refund
- Full Refund: Collection status changes to
REFUNDED - Partial Refund: Collection status changes to
PARTIALLY_REFUNDED - Customer Notification: Payer receives notification of the refund
Keep track of refund IDs to handle customer inquiries and for accounting purposes.
Authorizations
JWT access token obtained from /auth/token
Path Parameters
Collection ID or batch ID
Body
application/json
Refund mode: FULL (auto-calculate) or PARTIAL (specify amount)
Available options:
FULL, PARTIAL Refund amount (required for PARTIAL mode)
Reason code for refund
Available options:
DUPLICATE_PAYMENT, FRAUDULENT, CUSTOMER_REQUEST, ORDER_CANCELLED, PRODUCT_NOT_DELIVERED, PRODUCT_NOT_AS_DESCRIBED, PRICING_ERROR, OTHER ⌘I

