# Let the transaction tell you

[Cancel or refund a payment](https://devportal.qa.winkpg.io/docs/decide/cancel-or-refund-a-payment.md): Whether undoing a payment is a void, a reversal, or a refund, and what each one does to the money and to your records.

Every transaction publishes the operations it accepts right now, so your code reads the answer instead of working it out.

**Your answers so far**

- How did the customer pay? By card.
- Has the payment settled? I don't know, and my code shouldn't have to.

**What to build**

Read the transaction and keep the entries in its allowedActions list that are Void, Reversal, or Refund. Send the one that's left. That list already accounts for settlement, the processor's capabilities, its reversal window, and the merchant's refund setting, and it's the same evaluation the merchant's own screens use, so the API and the screen agree.

**Worth knowing**

- An empty result is an answer, not a failure: nothing about this transaction can be undone. A decline, an already voided payment, and a zero-dollar verification all land there.
- The create response doesn't carry the list. Read the transaction back when you need to know what a payment you just created accepts.
- A batch can close between your read and your request. The refusal is a 409 with OPERATION_NOT_ALLOWED_IN_STATE, and it carries the current allowed actions, so read them off the error and send one of those.

**Where to go next**

- [Read a transaction](https://devportal.qa.winkpg.io/docs/api/transactionsGet.md)
- [Refunds, voids, and reversals](https://devportal.qa.winkpg.io/docs/guides/refunds-voids-and-reversals.md)
- [Refund or void a payment](https://devportal.qa.winkpg.io/docs/blueprints/refund-or-void-a-payment.md)

- [Start over](https://devportal.qa.winkpg.io/docs/decide/cancel-or-refund-a-payment.md): go back to the first question.

## See also

- [All documentation](https://devportal.qa.winkpg.io/llms.txt): the machine-readable index of every public page on this site.
