Skip to main content

How to Reverse or Refund a Transaction

Once you've charged a payment method, you might want to cancel the transaction or refund the customer their money later. This guide provides instructions for the various ways you can "undo" a charge.

To attempt to completely reverse a transaction, regardless of its present settlement status, you may use the reverseTransaction mutation. When using this mutation, we will either void the transaction or issue a refund for the full amount of the transaction.

Voiding the transaction cancels it, preventing funds from being debited from the customer's account. A refund occurs when you have received or are in the process of receiving funds from a transaction already, and you would like to debit the full or partial amount of money from your own account to send back to the customer.

Reversing a Transaction

To reverse a transaction, you only need the ID of the Transaction. Depending on the settlement status at the time of the attempted reversal, the result of the reverseTransaction mutation will either be a Transaction updated to the VOIDED status, or a new Refund linked to the original transaction. If you are interested in only partially refunding a transaction or wish to provide an orderId, use the refundTransaction mutation directly instead.

mutation

mutation ExampleReverse($input: ReverseTransactionInput!) {
reverseTransaction(input: $input) {
reversal {
... on Transaction {
id
status
statusHistory {
status
terminal
}
}
... on Refund {
id
amount {
value
}
orderId
status
refundedTransaction {
id
amount {
value
}
orderId
status
}
}
}
}
}

variables

{
"input": {
"transactionId": "TRANSACTION_ID"
}
}

response

"data": {
"reverseTransaction": {
"reversal": {
"id": "TRANSACTION_ID",
"status": "VOIDED",
"statusHistory": [
{
"status": "VOIDED",
"terminal": true,
},
{
"status": "SUBMITTED_FOR_SETTLEMENT",
"terminal": false,
},
{
"status": "AUTHORIZED",
"terminal": false,
}
]
}
}
}

or

response

"data": {
"reverseTransaction": {
"reversal": {
"id": "REFUND_ID",
"amount": {
"value": "10.00"
},
"orderId": "original-charge-order-id-123",
"status": "SUBMITTED_FOR_SETTLEMENT",
"refundedTransaction": {
"id": "TRANSACTION_ID",
"amount": {
"value": "10.00"
},
"orderId": "original-charge-order-id-123",
"status": "SETTLED"
}
}
}
}

Refunding a Transaction

If you already know the transaction has been SETTLED, or you want to partially refund it, or you need to provide a refund order ID, you can use the refundTransaction mutation.

You'll need the ID for the Transaction that needs to be refunded. It must meet the following criteria to be refundable:

  • in either the SETTLING or SETTLED status
  • has not already been fully refunded

By default, refundTransaction will fully refund a transaction. You can pass in an amount less than the original amount in order to partially refund it. You can also optionally specify an orderId to give the refund its own unique order ID, instead of the default behavior, which is inheriting the order ID from the original transaction.

mutation

mutation ExampleRefund($input: RefundTransactionInput!) {
refundTransaction(input: $input) {
refund {
id
amount {
value
}
orderId
status
refundedTransaction {
id
amount {
value
}
orderId
status
}
}
}
}

variables

{
"input": {
"transactionId": "SETTLED_TRANSACTION_ID",
"refund": {
"amount": "7.00",
"orderId": "refund-order-id-456"
}
}
}

A successful refund results in a new Refund object:

response

{
"data": {
"refundTransction": {
"refund": {
"id": "REFUND_ID",
"amount": {
"value": "7.00"
},
"orderId": "refund-order-id-456",
"status": "SUBMITTED_FOR_SETTLEMENT",
"refundedTransaction": {
"id": "TRANSACTION_ID",
"amount": {
"value": "10.00"
},
"orderId": "original-charge-order-id-123",
"status": "SETTLED"
}
}
}
}
}

Or, a refund can fail because the original transaction wasn't ready to refund or had already been refunded. For example:

errors

{
"data": null,
"errors": [
{
"message": "Transaction has already been completely refunded.",
"locations": [{"line": 2, "column": 3}],
"path": ["refundTransaction"],
"extensions": {
"errorType": "user_error",
"errorClass": "VALIDATION",
"legacyCode": "91512",
"inputPath": ["input", "transactionId"]
}
}
]
}