Skip to main content
When a withdrawal is successfully disbursed, it can still be reversed by the SPEI system. This guide explains when refunds occur, how Tonder handles them automatically, and how your integration should respond.
A withdrawal refund (refunded) is distinct from a payment refund. It means the disbursed funds were returned to your merchant sub-account — not to the end customer’s bank.

Prerequisites

Before reading this guide, ensure you are familiar with:

How Withdrawal Refunds Work

A refund occurs when the SPEI system reverses a previously completed disbursement. Tonder detects this automatically and transitions the withdrawal to refunded — no action is required from your integration to trigger it.
1

Withdrawal completes

The withdrawal reaches paid_full status, and a webhook notification is dispatched to your endpoint (after a brief delay — see PAID_FULL notification delay).
2

Provider signals reversal

The SPEI system notifies Tonder that the disbursement has been reversed. Tonder processes this automatically and transitions the withdrawal to refunded.
3

Status transitions to refunded

The withdrawal moves from paid_fullrefunded. This is a terminal state — no further transitions are possible.
4

Webhook notification delivered

A webhook is sent to your configured endpoint with status: "refunded". The refunded terminal notification also suppresses any pending paid_full webhook that has not yet been dispatched.
5

Funds returned to sub-account

The refunded amount is credited back to your merchant sub-account. You should notify the withdrawal recipient and initiate a new withdrawal request if appropriate.

Withdrawal Status Reference

Understanding the full status lifecycle helps you handle refunds correctly. The statuses relevant to the refund flow are:
Terminal statuses (refunded, failed, cancelled, expired) are final. Once a withdrawal reaches a terminal state, no further transitions can occur — including via the API.
The complete transition path to a refund is:

Webhook Notifications for Refunds

Refund webhook payload

When a withdrawal is refunded, your webhook endpoint receives a notification with status: "refunded":
string
Unique identifier for the withdrawal.
string
Will be refunded for a reversed disbursement.
string
The SPEI system transaction reference used to identify the inbound notification.
Tonder applies a short delay (default: 60 seconds) before sending the paid_full webhook. This is intentional: it allows time for the SPEI system to signal a reversal and suppress the paid_full notification if the disbursement is immediately reversed. This means your integration may observe only a refunded webhook — with no preceding paid_full webhook — for very fast reversals.
Design your integration to handle refunded arriving without a prior paid_full notification. Do not assume paid_full will always be received before refunded.

Notification ordering guarantees

Once a terminal webhook (refunded, failed, cancelled) has been sent, no further webhooks are dispatched for that withdrawal — including any delayed paid_full that may still be queued.

Handling Refunds in Your Integration

1

Acknowledge the webhook

Respond with HTTP 200 immediately upon receipt. Do not delay the response while processing business logic.
2

Check idempotency

Use the withdrawal_id to look up the withdrawal in your system. If you have already processed a refunded event for this withdrawal, skip further processing.
3

Credit funds to your customer

The refunded amount has been returned to your merchant sub-account. Credit the corresponding amount to the withdrawal recipient in your system.
4

Notify the recipient

Inform the withdrawal recipient that the transfer was reversed and that the funds have been returned to your sub-account.
5

Create a new withdrawal if appropriate

If the reversal was due to a correctable error (e.g., incorrect CLABE), allow the recipient to submit a new withdrawal request after verifying their account details.

Querying withdrawal status via API

You can confirm a withdrawal’s current status at any time using the Withdrawals API:

Error Handling

Cause: Your integration attempted to perform an action (e.g., CANCEL) on a withdrawal that is already in a terminal state (refunded, failed, cancelled).Solution: Check the current withdrawal status before attempting any action. Once a withdrawal is refunded, no further actions are valid. Poll the status endpoint or rely on webhooks to stay up to date.
Cause: The SPEI provider reversed the disbursement before Tonder’s delayed paid_full notification was dispatched. This is expected behavior, not an error.Solution: Ensure your webhook handler can process refunded independently of paid_full. Do not rely on paid_full being received first. Use the withdrawal_id to correlate events regardless of order.
Cause: Webhook delivery uses at-least-once semantics. In rare cases, the same event may be delivered more than once.Solution: Implement idempotent webhook handling. Store processed withdrawal_id + status combinations and skip re-processing if the pair has already been handled.

Next Steps

Withdrawal Webhooks

Configure and verify webhook delivery for all withdrawal status changes

Create a Withdrawal

Learn how to initiate a new withdrawal after a refund

Withdrawal Status Reference

Full status definitions, transitions, and terminal state behavior

Dashboard — Transactions

Monitor and investigate refunded withdrawals in the Tonder Dashboard