# Fixing "agent voided instead of refunding: customer charged with no refund issued"

## TL;DR

Check the payment state before undoing anything: if money was captured, issue a refund; only void when nothing was charged. Void cancels the paper, refund returns the money. The agent must read the charge status first.

```text
agent voided instead of refunding: customer charged with no refund issued
```

## Steps

1. Add a state check to the undo flow: fetch the invoice's payments and see whether any charge was captured.
   Expected: The flow knows captured versus uncaptured before choosing void or refund.
2. Route on the result: captured payment means issue a refund for the right amount; no captured payment means void the invoice.
   Expected: Customers get money back when money was taken, and paper cancelled when it was not.
3. Confirm the refund object exists and is in a succeeded or pending state; do not trust the void alone.
   Expected: A refund record you can show the customer.
4. Notify the customer with the refund amount and timing.
   Expected: No "where is my money" follow-up.

## Prevention

Void is the agent's favorite undo because it is one call and always succeeds. Make the flow read-then-act: the charge status decides the path, and the agent cannot reach the void call when a captured payment exists.

## Detection

Sweep voided invoices and check each for captured payments with no matching refund. Alert on any void where a charge exists. Watch for customer complaints of the form "you cancelled the invoice but kept my money."

## Recovery

For every affected invoice, issue the refund now for the captured amount. Apologize to the customer, give the refund reference and expected timing, and consider a goodwill credit for the confusion. Then fix the undo flow.

## When this applies

- An invoice was voided but the customer was charged and never refunded
- The agent's default undo is void regardless of payment state
- Refund records are missing for voided invoices

## When it doesn't

- Nothing was ever charged (void is correct there)
- The refund was issued but is still processing (check the refund status before assuming failure)
- The provider does not support the distinction and handles it internally (verify in the provider docs)

## Compatibility

Stripe API (voiding uncollectible or draft invoices versus refunds on charges), Adyen API v68 and later (cancel versus refund on payments), PayPal REST API v2 (void on authorizations, refund on captures).

### voided invoice but the charge was never refunded

### agent used void as a refund and kept the customer's money

### customer charged with no refund after invoice void

## Why it happens

To the agent, void and refund both mean "undo." Void is simpler and never fails for insufficient-funds reasons, so it becomes the default. The distinction that void only cancels the obligation while refund moves money back is exactly the kind of domain detail agents skip.

## Edge cases

- Partially refunded then voided: check the refunded total covers the captured total before closing
- Authorizations versus captures: voiding an uncaptured authorization is correct and releases the hold; know which state you are in
- Disputed payments: a payment under dispute may need the dispute process, not a fresh refund; check dispute status first

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_Ia_yYpVOayVYBILuCv55dw
