# Pending transfer reversals Queue transfer reversals when connected accounts have insufficient balance, and release them automatically when funds become available. When a connected account has insufficient balance to cover a transfer reversal, Stripe can hold the reversal in a `pending` state and release it automatically after the account’s balance recovers instead of returning an error. The `status` field on transfer reversals tracks this lifecycle. > The `status` field and pending state behavior are active in the API only after Stripe enables the platform for the private preview. Contact your Stripe account manager to request access. ## Transfer reversal lifecycle The `status` field on transfer reversals can have these values: | Status | Description | | ----------- | ------------------------------------------------------------------------------------- | | `pending` | The reversal is waiting for the connected account to have sufficient balance. | | `succeeded` | The reversal completed successfully, and funds are available in the platform balance. | | `failed` | The reversal expired after more than 45 days. Funds return to the connected account. | | `canceled` | You canceled the reversal before Stripe released it. | Transfer reversal state transitions (See full diagram at https://docs.stripe.com/connect/pending-transfer-reversals) If the connected account has sufficient balance, the reversal transitions directly to `succeeded`. Otherwise, it enters the `pending` state. Stripe debits and reserves the funds from the connected account’s balance so they can’t be used for other purposes. Because the balance recovery check runs periodically, expect a delay of up to one hour between balance recovery and the transition to `succeeded`. If the connected account doesn’t accumulate sufficient funds within 45 days of the reversal’s creation, Stripe marks the reversal as `failed` and returns the held funds to the connected account’s available balance. ## Webhooks Subscribe to these events to track state changes: | Event | Trigger | | ---------------------------- | ------------------------------------------------------------------------- | | `transfer.reversal.pending` | A transfer reversal entered the `pending` state. | | `transfer.reversal.failed` | A transfer reversal failed (for example, after it expired after 45 days). | | `transfer.reversal.canceled` | You canceled a pending transfer reversal. | The existing `transfer.reversed` event occurs when a reversal transitions to `succeeded`. ## Limitations This feature has the following limitations: - **Unlinked transfer reversals only**: Reversals on transfers that aren’t associated with a destination charge and don’t include an application fee. Reversals that don’t meet these criteria return an error if the connected account has insufficient balance. - **Stripe must be loss liable**: This feature is supported only when Stripe is responsible for [negative balance liability](https://docs.stripe.com/connect/risk-management.md#negative-balance-responsibility), not your platform. ## Create a transfer reversal Create a transfer reversal as usual. If the connected account has insufficient balance, the reversal enters `pending` instead of returning an error. The response includes `pending_reason: "insufficient_balance"`. ```curl curl https://api.stripe.com/v1/transfers/{{TRANSFER_ID}}/reversals \ -u "<>:" \ -d amount=1000 ``` ```json { "id": "trr_001", "object": "transfer_reversal", "amount": 1000, "transfer": "tr_001", "status": "pending", "pending_reason": "insufficient_balance", "balance_transaction": null } ``` From the connected account’s perspective, Stripe creates a pending payment refund on the Stripe Account Payment associated with the transfer to hold the funds. The connected account receives a `refund.created` event. When the connected account’s available balance plus held funds is sufficient to cover the reversal amount, Stripe automatically releases it. Your platform receives a `transfer.reversed` event, the connected account receives a `refund.updated` event, and Stripe populates the `balance_transaction` field on the reversal. ## Cancel a pending reversal If you need to cancel a pending reversal (for example, due to an error), use the cancel endpoint: ```curl curl -X POST https://api.stripe.com/v1/transfers/{{TRANSFER_ID}}/reversals/{{TRANSFERREVERSAL_ID}}/cancel \ -u "<>:" ``` ```json { "id": "trr_001", "object": "transfer_reversal", "amount": 1000, "transfer": "tr_001", "status": "canceled", "balance_transaction": null, "failure_reason": null } ``` You can only cancel a reversal with `status: pending`. Canceling a reversal returns the held funds to the connected account’s available balance. The associated payment refund on the connected account transitions to `canceled`. ## Handle failed reversals A pending reversal can fail if Stripe doesn’t release it within 45 days or if either account is closed or has frozen funds: - **Platform**: Receives a `transfer.reversal.failed` event and an email reminder 10 days before the deadline. - **Connected account**: Receives a `refund.failed` event, and the held funds return to the available balance. ```json { "id": "trr_001", "object": "transfer_reversal", "amount": 1000, "transfer": "tr_001", "status": "failed", "failure_reason": "insufficient_balance", "balance_transaction": null } ``` After a reversal fails, you can create a new transfer reversal for the same transfer.