Refunds
Refunds return all or part of a paid order to the customer's original payment method. Use this API to create a refund, follow its progress, cancel it before processing begins, or browse previous refunds.
For an explanation of refund eligibility, lifecycle, and effects on balances and payouts, read the Refunds product guide. This page is the endpoint reference.
Create new refunds through POST /refunds/create. The older POST /orders/refund route remains available for compatibility and is documented with the Orders API.
The refund object
A refund records the amounts requested against an order's line items, why they were returned, and the refund's current status. New refunds begin as pending and then become processing, succeeded, or failed. A refund canceled before processing begins has a canceled status.
Order responses may include the same objects in order.refunds, with the newest refund first. Optional properties and lifecycle timestamps appear when they have a value.
Properties
Create a refund
Return all or part of one or more paid order line items. Inttegro sends each amount back through the payment method used for the order. Processing happens asynchronously, so every new refund begins in pending status.
Before creating the refund:
- Read the order to obtain its line-item IDs and current refundable amounts.
- Include each line item once, using the same currency and no more than its remaining refundable amount.
- Reuse the same idempotency key and request body if the result of a request is uncertain.
Request attributes
Response
Returns the new refund in pending status. Save its id and use Lookup a refund when you need its latest status.
Request
- cURL
- TypeScript
- Go
- Python
- PHP
- Ruby
- Java
- C#
curl --fail-with-body https://api.inttegro.com/refunds/create \
-H "Authorization: Bearer $INTTEGRO_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: refund-return-1042" \
-d '{
"custom_data": {
"warehouse": "accra"
},
"line_items": [
{
"order_line_item_id": "oli_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN",
"reason": "item_damaged",
"reason_details": "Packaging was crushed.",
"refund_amount": {
"currency": "ghs",
"value": 2500
}
},
{
"order_line_item_id": "oli_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn",
"refund_amount": {
"currency": "ghs",
"value": 1000
}
}
],
"order_id": "or_0123456789abcdefghijklmnopqrstuvwxyzABCD",
"reason": "requested_by_customer",
"reason_details": "Customer returned part of the order.",
"reference": "return_1042"
}'
import * as Inttegro from '@inttegro/inttegro-sdk'
const inttegro = new Inttegro.InttegroClient({
apiKey: process.env.INTTEGRO_API_KEY!,
})
const result = await inttegro.refunds.create({
customData: {
warehouse: "accra",
},
lineItems: [
{
orderLineItemId: "oli_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN",
reason: Inttegro.RefundReasons.ItemDamaged,
reasonDetails: "Packaging was crushed.",
refundAmount: {
currency: "ghs",
value: 2500,
},
},
{
orderLineItemId: "oli_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn",
refundAmount: {
currency: "ghs",
value: 1000,
},
},
],
orderId: "or_0123456789abcdefghijklmnopqrstuvwxyzABCD",
reason: Inttegro.RefundReasons.RequestedByCustomer,
reasonDetails: "Customer returned part of the order.",
reference: "return_1042",
}, {
idempotencyKey: "refund-return-1042",
})
package main
import (
"context"
"log"
"os"
inttegro "github.com/zebodotdev/inttegro-sdk-go/v4"
"github.com/zebodotdev/inttegro-sdk-go/v4/money"
)
func main() {
ctx := context.Background()
client := inttegro.NewClient(os.Getenv("INTTEGRO_API_KEY"))
params := inttegro.CreateRefundRequest{
CustomData: map[string]string{
"warehouse": "accra",
},
LineItems: []inttegro.CreateRefundLineItem{
{
OrderLineItemID: "oli_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN",
Reason: func() *inttegro.RefundReason { value := inttegro.RefundReasonItemDamaged; return &value }(),
ReasonDetails: "Packaging was crushed.",
RefundAmount: money.AmountParams{
Currency: money.GHS,
Value: 2500,
},
},
{
OrderLineItemID: "oli_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn",
RefundAmount: money.AmountParams{
Currency: money.GHS,
Value: 1000,
},
},
},
OrderID: "or_0123456789abcdefghijklmnopqrstuvwxyzABCD",
Reason: inttegro.RefundReasonRequestedByCustomer,
ReasonDetails: "Customer returned part of the order.",
Reference: "return_1042",
}
result, err := client.Refunds.Create(ctx, params)
if err != nil {
log.Fatal(err)
}
_ = result
}
import os
import inttegro
client = inttegro.InttegroClient(api_key=os.environ["INTTEGRO_API_KEY"])
result = client.refunds.create(inttegro.refunds.CreateRequest(
custom_data={
"warehouse": "accra",
},
line_items=[
inttegro.refunds.LineItem(
order_line_item_id="oli_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN",
reason=inttegro.RefundReason.ITEM_DAMAGED,
reason_details="Packaging was crushed.",
refund_amount=inttegro.refunds.AmountParams(
currency=inttegro.Currency.GHS,
value=2500,
),
),
inttegro.refunds.LineItem(
order_line_item_id="oli_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn",
refund_amount=inttegro.refunds.AmountParams(
currency=inttegro.Currency.GHS,
value=1000,
),
),
],
order_id="or_0123456789abcdefghijklmnopqrstuvwxyzABCD",
reason=inttegro.RefundReason.REQUESTED_BY_CUSTOMER,
reason_details="Customer returned part of the order.",
reference="return_1042",
),
idempotency_key="refund-return-1042")
<?php
use Inttegro\Client;
$client = new Client($_ENV['INTTEGRO_API_KEY']);
$result = $client->refunds->create([
'custom_data' => [
'warehouse' => 'accra',
],
'line_items' => [
[
'order_line_item_id' => 'oli_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN',
'reason' => \Inttegro\RefundReason::ItemDamaged,
'reason_details' => 'Packaging was crushed.',
'refund_amount' => [
'currency' => 'ghs',
'value' => 2500,
],
],
[
'order_line_item_id' => 'oli_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn',
'refund_amount' => [
'currency' => 'ghs',
'value' => 1000,
],
],
],
'order_id' => 'or_0123456789abcdefghijklmnopqrstuvwxyzABCD',
'reason' => \Inttegro\RefundReason::RequestedByCustomer,
'reason_details' => 'Customer returned part of the order.',
'reference' => 'return_1042',
], "refund-return-1042");
require "inttegro"
client = Inttegro::Client.new(api_key: ENV.fetch("INTTEGRO_API_KEY"))
result = client.refunds.create(
custom_data: {
warehouse: "accra",
},
line_items: [
{
order_line_item_id: "oli_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN",
reason: Inttegro::RefundReason::ITEM_DAMAGED,
reason_details: "Packaging was crushed.",
refund_amount: {
currency: "ghs",
value: 2500,
},
},
{
order_line_item_id: "oli_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn",
refund_amount: {
currency: "ghs",
value: 1000,
},
},
],
order_id: "or_0123456789abcdefghijklmnopqrstuvwxyzABCD",
reason: Inttegro::RefundReason::REQUESTED_BY_CUSTOMER,
reason_details: "Customer returned part of the order.",
reference: "return_1042",
idempotency_key: "refund-return-1042"
)
import com.inttegro.Client;
import com.inttegro.refunds.CreateRefundParams;
import java.util.Map;
import com.inttegro.refunds.CreateRefundLineItem;
import com.inttegro.refunds.RefundReason;
import com.inttegro.money.AmountParams;
import com.inttegro.money.Currency;
import com.inttegro.RequestOptions;
public class Example {
public static void main(String[] args) throws Exception {
var client = new Client(System.getenv("INTTEGRO_API_KEY"));
var params = CreateRefundParams.builder()
.customData(Map.<String, String>ofEntries(
Map.entry("warehouse", "accra")
))
.lineItem(CreateRefundLineItem.builder()
.orderLineItemId("oli_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN")
.reason(RefundReason.ITEM_DAMAGED)
.reasonDetails("Packaging was crushed.")
.refundAmount(AmountParams.of(Currency.GHS, 2500))
.build())
.lineItem(CreateRefundLineItem.builder()
.orderLineItemId("oli_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn")
.refundAmount(AmountParams.of(Currency.GHS, 1000))
.build())
.orderId("or_0123456789abcdefghijklmnopqrstuvwxyzABCD")
.reason(RefundReason.REQUESTED_BY_CUSTOMER)
.reasonDetails("Customer returned part of the order.")
.reference("return_1042")
.build();
var result = client.refunds().create(params, RequestOptions.withIdempotencyKey("refund-return-1042"));
}
}
using Inttegro;
using var inttegro = new InttegroClient(
Environment.GetEnvironmentVariable("INTTEGRO_API_KEY")!
);
var result = await inttegro.Refunds.CreateAsync(new Inttegro.CreateRefundRequest {
CustomData = new Dictionary<string, string> {
["warehouse"] = "accra",
},
LineItems = new List<Inttegro.CreateRefundLineItem> {
new Inttegro.CreateRefundLineItem {
OrderLineItemId = "oli_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN",
Reason = Inttegro.RefundReason.ItemDamaged,
ReasonDetails = "Packaging was crushed.",
RefundAmount = new Inttegro.Money.AmountParams {
Currency = Inttegro.Money.Currency.GHS,
Value = 2500,
},
},
new Inttegro.CreateRefundLineItem {
OrderLineItemId = "oli_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn",
RefundAmount = new Inttegro.Money.AmountParams {
Currency = Inttegro.Money.Currency.GHS,
Value = 1000,
},
},
},
OrderId = "or_0123456789abcdefghijklmnopqrstuvwxyzABCD",
Reason = Inttegro.RefundReason.RequestedByCustomer,
ReasonDetails = "Customer returned part of the order.",
Reference = "return_1042",
}, "refund-return-1042");
Response
- Object
- JSON
RefundResponse {
refund: { … },
}
{
"refund": {
"created_at": "2026-08-30T12:00:00Z",
"custom_data": { … },
"id": "rf_1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcd",
"line_items": [ … ],
"order_id": "or_0123456789abcdefghijklmnopqrstuvwxyzABCD",
"reason": "requested_by_customer",
"reason_details": "Customer returned part of the order.",
"reference": "return_1042",
"total": { … },
"status": "pending"
}
}
Cancel a refund
Stop a pending refund before Inttegro begins processing it. Cancellation releases the balance reserved for the refund and restores the affected order lines' refundable amounts.
A refund cannot be canceled once it is processing, succeeded, or failed. Repeating this operation for an already canceled refund returns the same refund, making retries safe when you reuse the same idempotency key and request body.
Request attributes
Response
Returns the refund in canceled status.
Request
- cURL
- TypeScript
- Go
- Python
- PHP
- Ruby
- Java
- C#
curl --fail-with-body https://api.inttegro.com/refunds/cancel \
-H "Authorization: Bearer $INTTEGRO_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: cancel-refund-return-1042" \
-d '{"refund_id":"rf_1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcd"}'
import * as Inttegro from '@inttegro/inttegro-sdk'
const inttegro = new Inttegro.InttegroClient({
apiKey: process.env.INTTEGRO_API_KEY!,
})
const result = await inttegro.refunds.cancel({
refundId: "rf_1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcd",
}, {
idempotencyKey: "cancel-refund-return-1042",
})
package main
import (
"context"
"log"
"os"
inttegro "github.com/zebodotdev/inttegro-sdk-go/v4"
)
func main() {
ctx := context.Background()
client := inttegro.NewClient(os.Getenv("INTTEGRO_API_KEY"))
params := inttegro.CancelRefundRequest{
RefundID: "rf_1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcd",
}
result, err := client.Refunds.Cancel(ctx, params)
if err != nil {
log.Fatal(err)
}
_ = result
}
import os
import inttegro
client = inttegro.InttegroClient(api_key=os.environ["INTTEGRO_API_KEY"])
result = client.refunds.cancel("rf_1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcd")
<?php
use Inttegro\Client;
$client = new Client($_ENV['INTTEGRO_API_KEY']);
$result = $client->refunds->cancel("rf_1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcd");
require "inttegro"
client = Inttegro::Client.new(api_key: ENV.fetch("INTTEGRO_API_KEY"))
result = client.refunds.cancel(refund_id: "rf_1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcd")
import com.inttegro.Client;
public class Example {
public static void main(String[] args) throws Exception {
var client = new Client(System.getenv("INTTEGRO_API_KEY"));
var result = client.refunds().cancel("rf_1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcd");
}
}
using Inttegro;
using var inttegro = new InttegroClient(
Environment.GetEnvironmentVariable("INTTEGRO_API_KEY")!
);
var result = await inttegro.Refunds.CancelAsync("rf_1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcd");
Lookup a refund
Retrieve a refund's current status and line-item amounts. Use this after creating or canceling a refund, or when helping a customer with a return.
Request attributes
Response
Returns the requested refund.
Request
- cURL
- TypeScript
- Go
- Python
- PHP
- Ruby
- Java
- C#
: "${INTTEGRO_API_KEY:?INTTEGRO_API_KEY is required}"
: "${INTTEGRO_REFUND_ID:?INTTEGRO_REFUND_ID is required}"
curl --fail-with-body https://api.inttegro.com/refunds/lookup \
-H "Authorization: Bearer $INTTEGRO_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"refund_id\":\"$INTTEGRO_REFUND_ID\"}"
import * as Inttegro from '@inttegro/inttegro-sdk'
const inttegro = new Inttegro.InttegroClient({
apiKey: process.env.INTTEGRO_API_KEY!,
})
const result = await inttegro.refunds.lookup({
refundId: "$INTTEGRO_REFUND_ID",
})
package main
import (
"context"
"log"
"os"
inttegro "github.com/zebodotdev/inttegro-sdk-go/v4"
)
func main() {
ctx := context.Background()
client := inttegro.NewClient(os.Getenv("INTTEGRO_API_KEY"))
params := inttegro.LookupRefundRequest{
RefundID: "$INTTEGRO_REFUND_ID",
}
result, err := client.Refunds.Lookup(ctx, params)
if err != nil {
log.Fatal(err)
}
_ = result
}
import os
import inttegro
client = inttegro.InttegroClient(api_key=os.environ["INTTEGRO_API_KEY"])
result = client.refunds.lookup("$INTTEGRO_REFUND_ID")
<?php
use Inttegro\Client;
$client = new Client($_ENV['INTTEGRO_API_KEY']);
$result = $client->refunds->lookup("$INTTEGRO_REFUND_ID");
require "inttegro"
client = Inttegro::Client.new(api_key: ENV.fetch("INTTEGRO_API_KEY"))
result = client.refunds.lookup(refund_id: "$INTTEGRO_REFUND_ID")
import com.inttegro.Client;
public class Example {
public static void main(String[] args) throws Exception {
var client = new Client(System.getenv("INTTEGRO_API_KEY"));
var result = client.refunds().lookup("$INTTEGRO_REFUND_ID");
}
}
using Inttegro;
using var inttegro = new InttegroClient(
Environment.GetEnvironmentVariable("INTTEGRO_API_KEY")!
);
var result = await inttegro.Refunds.LookupAsync("$INTTEGRO_REFUND_ID");
List refunds
Browse refunds from newest to oldest. Use this endpoint to build refund history, customer-service, and reconciliation views.
Pages are one-based. page_size defaults to 256, and the response's page.size is the number of refunds actually returned. An empty page is successful and contains size: 0 and refunds: [].
Request attributes
Response
Returns the page number, number of results, and a refunds array. An empty page returns refunds: [] and size: 0.
Request
- cURL
- TypeScript
- Go
- Python
- PHP
- Ruby
- Java
- C#
: "${INTTEGRO_API_KEY:?INTTEGRO_API_KEY is required}"
curl --fail-with-body https://api.inttegro.com/refunds/page \
-H "Authorization: Bearer $INTTEGRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"page_number":1,"page_size":20}'
import * as Inttegro from '@inttegro/inttegro-sdk'
const inttegro = new Inttegro.InttegroClient({
apiKey: process.env.INTTEGRO_API_KEY!,
})
const result = await inttegro.refunds.page({
pageNumber: 1,
pageSize: 20,
})
package main
import (
"context"
"log"
"os"
inttegro "github.com/zebodotdev/inttegro-sdk-go/v4"
)
func main() {
ctx := context.Background()
client := inttegro.NewClient(os.Getenv("INTTEGRO_API_KEY"))
params := inttegro.PageRefundsRequest{
PageNumber: 1,
PageSize: 20,
}
result, err := client.Refunds.Page(ctx, params)
if err != nil {
log.Fatal(err)
}
_ = result
}
import os
import inttegro
client = inttegro.InttegroClient(api_key=os.environ["INTTEGRO_API_KEY"])
result = client.refunds.page(inttegro.refunds.PageRequest(
page_number=1,
page_size=20,
))
<?php
use Inttegro\Client;
$client = new Client($_ENV['INTTEGRO_API_KEY']);
$result = $client->refunds->page([
'page_number' => 1,
'page_size' => 20,
]);
require "inttegro"
client = Inttegro::Client.new(api_key: ENV.fetch("INTTEGRO_API_KEY"))
result = client.refunds.page(
page_number: 1,
page_size: 20
)
import com.inttegro.Client;
import com.inttegro.refunds.RefundPageParams;
public class Example {
public static void main(String[] args) throws Exception {
var client = new Client(System.getenv("INTTEGRO_API_KEY"));
var params = RefundPageParams.builder()
.pageNumber(1)
.pageSize(20)
.build();
var result = client.refunds().page(params);
}
}
using Inttegro;
using var inttegro = new InttegroClient(
Environment.GetEnvironmentVariable("INTTEGRO_API_KEY")!
);
var result = await inttegro.Refunds.PageAsync(new Inttegro.PageRefundsRequest {
PageNumber = 1,
PageSize = 20,
});
Handling refund failures
Read error.code, fix_code, and detail to decide what to do next.
- If an amount, currency, or line item is no longer valid, retrieve the order again and rebuild the refund from its current refundable amounts.
- If the merchant balance cannot cover the refund or the original payment method is unavailable, resolve that condition before creating another refund.
- If refundable capacity changed concurrently, retrieve the order and refund state before retrying.
- Retry a transient failure only when
fix_coderecommends it. Keep the same endpoint, idempotency key, and request body.
Related resources
- Refunds product guide — Understand eligibility, lifecycle, balances, and payouts.
- Lookup an order — Read the paid order and its line-item IDs before creating a refund.
- Errors — Handle Inttegro API errors consistently.