Skip to main content
A refund returns funds to the originator when a transaction cannot be completed after funds have already moved. This can happen for several reasons β€” the receiving bank returns the payment, a compliance review reverses it, the transaction expires or fails after funds left the source, or an explicit refund is requested. When a refund completes, the original transaction reaches the Refunded status.
If you’re just getting started, please check out our quick start guide.
Like every operation on Borderless, refunds are asynchronous. You can track a refund either via webhooks or by polling the transaction. For background on the transaction lifecycle and the Refunded status, see Transactions.

How refunds work

When a transaction is created, Borderless builds a refund plan for it. The plan records how a refund would be handled if it becomes necessary β€” where the funds should be returned (the refund destination) and whether the refund should be triggered automatically. If the transaction later fails or is reversed:
  • When the plan has auto-refund enabled (the default), Borderless dispatches the refund automatically.
  • When auto-refund is disabled, the plan stays eligible but waits until the refund is dispatched manually through the refund endpoint.
Whether a refund is supported, and which return paths are available, depends on the partner financial institution (PFI) handling the transaction.

Refund destinations

A refund destination describes where returned funds should go. It is configured with the following fields:
type
string enum
required
How the refund should be handled. One of:
  • Address β€” return funds to a specific crypto address.
  • Source β€” return funds to the original on-chain sender.
  • ProviderBalance β€” leave the funds in your account balance at the PFI.
address
string
The crypto address that should receive the refund. Required when type is Address.
autoRefund
boolean
Whether Borderless should automatically trigger the refund on failure. Defaults to true. Setting it to false records the plan as eligible but keeps it waiting until the refund is dispatched manually.
You can attach a refundDestination when creating a withdrawal. The examples below show each destination type:
{
  "paymentInstructionId": "cm2c4x3cc000019stwv7um4zl",
  "paymentPurpose": "delivery fees",
  "refundDestination": {
    "type": "Address",
    "address": "0x1234567890abcdef1234567890abcdef12345678",
    "autoRefund": true
  }
}

Where the destination comes from

The refund destination is resolved from three layers. Each layer overrides the one before it, so the most specific configuration always wins:
  1. Organization default β€” an org-wide fallback applied to every transaction. Resolves to destinationSource: OrganizationDefault.
  2. Withdrawal β€” the refundDestination you set on the create request. Overrides the organization default and resolves to destinationSource: PerTransaction.
  3. Execute Plan β€” a refundDestination override passed to the refund endpoint, applied just before the refund is dispatched. Takes precedence over everything and resolves to destinationSource: Manual.

Refund capabilities

Before creating a transaction, you can check which refund behavior is supported for an off-ramp corridor. The capabilities endpoint reports, per partner financial institution (PFI), the refund paths, accepted destination types, supported chains, and estimated timing for a given country and fiat currency. The response is an array with one entry per PFI that currently serves the corridor. Each entry contains:
pfiName
string enum
The partner financial institution the capabilities apply to.
supportedPaths
array of strings
The refund paths the PFI supports for this corridor, such as SourceReturn, ProviderBalance, or ManualRequired.
acceptedRequestTypes
array of strings
The refund destination type values you may specify on a transaction. Either ["Address"] or empty.
destinationModes
array of strings
How the refund destination is determined: none, address_optional, address_required, or provider_locked.
dispatchModes
array of strings
How the refund is dispatched and tracked, such as SubmitAndPoll, PollOnly, or Manual.
chainsSupported
array of strings
The assets/chains available for refunds on this corridor, such as USDC_POLYGON.
estimatedTimingRange
object
The expected refund time as minSeconds, maxSeconds, and a businessDays flag indicating whether the range is measured in business days.
autoRefundOverrideSupported
boolean
Whether the auto-refund preference can be overridden for this corridor. Currently always false.
prerequisites
array of strings
Any prerequisites that must be met before a refund can be processed.
curl --request GET \
  --url https://api.borderless.xyz/v1/corridors/{country}/{fiat}/off-ramp/refund-capabilities \
  --header 'Authorization: Bearer <token>'
Capabilities are scoped to the PFIs currently enabled for your organization. An empty array means no enabled PFI serves that corridor.

Executing a refund plan

When auto-refund is disabled, or when you need to override the stored destination, you can dispatch the refund manually:
curl --request POST \
  --url https://api.borderless.xyz/v1/transactions/{id}/refund \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "refundDestination": {
      "type": "Address",
      "address": "0x1234567890abcdef1234567890abcdef12345678"
    }
  }'
The request body is optional β€” call the endpoint with an empty body to dispatch using the destination already stored on the plan. The endpoint responds with 202 Accepted and returns the current refund resolution.
Dispatching a refund through this endpoint bypasses the autoRefund: false preference, so it is the way to trigger refunds for transactions created with auto-refund disabled. Only plans in Created or Eligible status can be dispatched manually, and any refundDestination override is re-validated against the PFI’s refund capability before it is applied.
If you have any questions, please don’t hesitate to reach out to us via email or slack.