# 

Both operations go to `POST /v1/transactions/{id}/cancel`. The body decides which
one you get.

|  | Void | Refund |
|  --- | --- | --- |
| Use it when | The transaction has not settled | The transaction has settled |
| Body | `{"type": "VOID"}` | `{"type": "REFUND", "amount": …}` |
| Amount | Always the full original | Full or partial |
| The cardholder sees | Usually nothing, or a hold disappearing | A credit on their statement |
| Settles | Never. The transaction leaves the batch | As a separate credit |


**Void when you can, refund when you must.** A void removes the transaction
before it ever reaches the cardholder's statement, which means no charge and no
credit to explain. A refund is two visible entries and takes days to reach them.

## Which one applies

Read `is_settled` on the transaction.

* `false` — it has not settled. Void it.
* `true` — it has settled. Refund it.


Sending a void for a settled transaction fails, and sending a refund for an
unsettled one is not the operation you want. When in doubt, read the transaction
first with `GET /v1/transactions/{id}`.

## Void

A void takes only `type`. There is no `amount` field, because a void is always
for the full original amount — you cannot void part of a transaction.

```json 200 application/json
{
  "id": "TRANSACTION-01KEW38F2RT6N4Z1AJGV5MPQ82",
  "reference_transaction_id": "TRANSACTION-01KEW32V6YNV11T33XGDR7TGWC",
  "type": "CANCEL",
  "result": "APPROVED",
  "client_id": "CLIENT-01KFDKXMQ637EKEAY410MSQSXB",
  "client_dba": "Acme Jewelry",
  "integrations": [
    "TSYS"
  ],
  "response_code": "00",
  "response_description": "Approved",
  "batch_id": null,
  "is_settled": false,
  "time_created": "2026-07-15T17:30:44Z",
  "amount": 10000,
  "tip": 0,
  "tax_amount": null,
  "currency": "USD",
  "payment_method": {
    "type": "CARD",
    "truncated_pan": "****-****-****-5439",
    "payment_token": "CARD_TOKEN-01KFDKXMQ637EKEAY410MSQSXB",
    "expiry": null,
    "first_name": "John",
    "last_name": "Doe",
    "entry_method": "keyed",
    "auth_code": "123456",
    "retrieval_reference_number": "000000603076",
    "card_type": "UNKNOWN",
    "card_brand": "Visa",
    "cvv_result_code": null
  },
  "recurring": false,
  "initiator": "CUSTOMER",
  "network_transaction_id": "000000004271001",
  "metadata": {
    "order_id": "ORD-10432",
    "sales_channel": "web",
    "customer_reference": "cust-8891"
  }
}
```

```json 400 application/json
{
  "error_code": "INVALID_REQUEST_DATA",
  "error_message": "The API request contains invalid data.",
  "details": {
    "amount": "Invalid amount",
    "payment_method.pan": "Malformed PAN"
  },
  "source": {
    "system": "TSYS",
    "code": "13",
    "message": "Invalid amount"
  }
}
```

```json 401 application/json
{
  "error_code": "NOT_AUTHENTICATED",
  "error_message": "Access credentials missing or invalid.",
  "details": null,
  "source": {
    "system": null,
    "code": null,
    "message": null
  }
}
```

```json 403 application/json
{
  "error_code": "UNAUTHORIZED_ACTION",
  "error_message": "Requested action is unavailable or forbidden.",
  "details": null,
  "source": {
    "system": null,
    "code": null,
    "message": null
  }
}
```

```json 404 application/json
{
  "error_code": "RESOURCE_NOT_FOUND",
  "error_message": "Resource not found.",
  "details": null,
  "source": {
    "system": null,
    "code": null,
    "message": null
  }
}
```

```json 409 application/json
{
  "error_code": "DUPLICATE_ACTION",
  "error_message": "Duplicate action requested.",
  "details": null,
  "source": {
    "system": "TSYS",
    "code": "12",
    "message": "Invalid transaction"
  }
}
```

```json 500 application/json
{
  "error_code": "SYSTEM_ERROR",
  "error_message": "Internal system error.",
  "details": null,
  "source": {
    "system": "TSYS",
    "code": "96",
    "message": "System malfunction"
  }
}
```

```json 502 application/json
{
  "error_code": "DOWNSTREAM_ERROR",
  "error_message": "Downstream service returned invalid or unexpected response.",
  "details": null,
  "source": {
    "system": "VERICHECK",
    "code": "502",
    "message": "Bad Gateway"
  }
}
```

```json 503 application/json
{
  "error_code": "string",
  "error_message": "string",
  "details": {
    "property1": "string",
    "property2": "string"
  },
  "source": {
    "system": "TSYS",
    "code": "51",
    "message": "Insufficient funds"
  }
}
```

The result is a new transaction with a `type` of **`CANCEL`**. Note the word: you
send `VOID` and you read `CANCEL`. Its `reference_transaction_id` points at the
transaction it voided.

## Refund

`amount` is required, and it may be less than the original — that example refunds
25.00 of a 100.00 sale. It may not be more.

```json 200 application/json
{
  "id": "TRANSACTION-01KEW3B7XKC9P5W2DMHY6NRS13",
  "reference_transaction_id": "TRANSACTION-01KEW32V6YNV11T33XGDR7TGWC",
  "type": "REFUND",
  "result": "APPROVED",
  "client_id": "CLIENT-01KFDKXMQ637EKEAY410MSQSXB",
  "client_dba": "Acme Jewelry",
  "integrations": [
    "TSYS"
  ],
  "response_code": "00",
  "response_description": "Approved",
  "batch_id": null,
  "is_settled": false,
  "time_created": "2026-07-16T10:12:58Z",
  "amount": 2500,
  "tip": 0,
  "tax_amount": null,
  "currency": "USD",
  "payment_method": {
    "type": "CARD",
    "truncated_pan": "****-****-****-5439",
    "payment_token": "CARD_TOKEN-01KFDKXMQ637EKEAY410MSQSXB",
    "expiry": null,
    "first_name": "John",
    "last_name": "Doe",
    "entry_method": "keyed",
    "auth_code": "123456",
    "retrieval_reference_number": "000000603076",
    "card_type": "UNKNOWN",
    "card_brand": "Visa",
    "cvv_result_code": null
  },
  "recurring": false,
  "initiator": "CUSTOMER",
  "network_transaction_id": "000000004271001",
  "metadata": {
    "order_id": "ORD-10432",
    "sales_channel": "web",
    "customer_reference": "cust-8891"
  }
}
```

```json 400 application/json
{
  "error_code": "INVALID_REQUEST_DATA",
  "error_message": "The API request contains invalid data.",
  "details": {
    "amount": "Invalid amount",
    "payment_method.pan": "Malformed PAN"
  },
  "source": {
    "system": "TSYS",
    "code": "13",
    "message": "Invalid amount"
  }
}
```

```json 401 application/json
{
  "error_code": "NOT_AUTHENTICATED",
  "error_message": "Access credentials missing or invalid.",
  "details": null,
  "source": {
    "system": null,
    "code": null,
    "message": null
  }
}
```

```json 403 application/json
{
  "error_code": "UNAUTHORIZED_ACTION",
  "error_message": "Requested action is unavailable or forbidden.",
  "details": null,
  "source": {
    "system": null,
    "code": null,
    "message": null
  }
}
```

```json 404 application/json
{
  "error_code": "RESOURCE_NOT_FOUND",
  "error_message": "Resource not found.",
  "details": null,
  "source": {
    "system": null,
    "code": null,
    "message": null
  }
}
```

```json 409 application/json
{
  "error_code": "DUPLICATE_ACTION",
  "error_message": "Duplicate action requested.",
  "details": null,
  "source": {
    "system": "TSYS",
    "code": "12",
    "message": "Invalid transaction"
  }
}
```

```json 500 application/json
{
  "error_code": "SYSTEM_ERROR",
  "error_message": "Internal system error.",
  "details": null,
  "source": {
    "system": "TSYS",
    "code": "96",
    "message": "System malfunction"
  }
}
```

```json 502 application/json
{
  "error_code": "DOWNSTREAM_ERROR",
  "error_message": "Downstream service returned invalid or unexpected response.",
  "details": null,
  "source": {
    "system": "VERICHECK",
    "code": "502",
    "message": "Bad Gateway"
  }
}
```

```json 503 application/json
{
  "error_code": "string",
  "error_message": "string",
  "details": {
    "property1": "string",
    "property2": "string"
  },
  "source": {
    "system": "TSYS",
    "code": "51",
    "message": "Insufficient funds"
  }
}
```

A refund is its own transaction with a `type` of `REFUND`, and it settles in a
batch like any other. The money reaches the cardholder when that batch settles,
not when you make the call.

## Partial refunds

Send the amount you are returning. To refund in several parts, call the endpoint
again with the next amount; each call is a separate `REFUND` transaction against
the same original.

The gateway does not stop you from refunding more in total than the original
transaction, so **track the running total yourself** if you issue partial
refunds. Reading the original back and summing the refunds that reference it is
the reliable way to do that.

## Releasing an authorization

An authorization you never capture is a hold on someone's funds. Void it rather
than leaving it to expire — the issuer decides when that happens, and it is
usually days.

[Authorize and capture](/docs/payments/authorize-and-capture) covers the flow
that leads here.

## Next steps

* [Transaction lifecycle](/docs/after-the-payment/transaction-lifecycle)
* [Batches and settlement](/docs/after-the-payment/batches-and-settlement)
* [Find and report on transactions](/docs/after-the-payment/find-and-report-on-transactions)