# Reverse a Card Present Payment

This guide explains how to reverse an authorized payment in a **card-present** environment using the Getnet Global API. A reversal undoes the authorization before it is captured. No money moves, so the funds never leave the cardholder's account.

## Choose Between Reversal and Cancellation

Reversal and cancellation are separate operations with separate endpoints. Choose one based on whether the transaction is captured.

| | Reversal | Cancellation |
| --- | --- | --- |
| **When to use** | The transaction is authorized but not captured yet. | The transaction is captured. |
| **Money movement** | No money has moved. The reversal undoes the authorization. | The money has moved. The funds return to the customer. |
| **Amount** | Full amount only. Partial reversals are not supported. | Full, or partial from D+1. |
| **Endpoint** | `POST /dpm/payments-gwproxy/v2/payments/reversal` | `POST /dpm/payments-gwproxy/v2/payments/cancel` |

To check whether a transaction is captured, query its status with the [Get Transaction Status guide](/en/global-api/sep-card-present/payment-guides-cp/get-transaction-status-cp). An `AUTHORIZED` status means you can reverse it. A `CAPTURED` status means you must cancel it instead.

To cancel a captured transaction, see [Cancel a Card Present Payment](/en/global-api/sep-card-present/payment-guides-cp/cancel-a-payment-cp).

## Understand Manual and Automatic Reversal

Getnet already reverses some transactions automatically. The platform triggers an automatic reversal after a communication failure, a processing interruption, or a timeout. This keeps transactions consistent and prevents unintended authorizations.

The Reversal endpoint covers a different case: the reversals you decide to request. It does not replace the automatic process.

If your terminal timed out waiting for an authorization response, check the transaction status before you call the Reversal endpoint. Getnet may have already reversed it.

## Requirements

Before following the steps, you need to:

- **API Credentials**: Get your `client_id` and `client_secret` from the Integration Support team.
- **Authentication**: Generate a Bearer token with the [Authentication endpoint](https://docs.globalgetnet.com/en/products/online-payments/regional-api/swagger#tag/authentication).
- **Seller ID**: Your seller identifier, sent in the `x-seller-id` header. Get it from the Integration Support team with your API credentials. The reversal uses it to find the original transaction.
- **Payment ID**: The `payment_id` returned by the original authorization.
- **Card Data** (optional): The card number (PAN) or the Track 2 data of the original transaction. You do not need to keep card data to reverse a payment. Without it, send an empty `card` object.
- **Terminal Identifiers** (Brazil): The `terminal_code`, `logical_code`, and `serial_number` of the terminal that processed the transaction.

## Step 1: Reverse the Payment

To reverse a card-present payment, call the [Reversal endpoint](https://docs.globalgetnet.com/en/products/online-payments/regional-api/swagger#tag/payments/post/dpm/payments-gwproxy/v2/payments/reversal) with the original transaction's `payment_id`. Always include the `additional_data.card` object, even when it is empty. The endpoint is available in all countries integrated with SEP Card Present.

### Headers

Send these headers on every reversal request.

| Header | Description | Required |
| --- | --- | --- |
| `Authorization` | `Bearer` followed by your access token. | **Yes** |
| `Content-Type` | `application/json` | **Yes** |
| `x-seller-id` | Your seller identifier. | **Yes** |
| `country` | Country identifier. Defaults to `BR`. Send your country if you operate outside Brazil. | No |
| `tenant` | Tenant identifier. Defaults to `santander`. | No |

### Request Attributes

The request body identifies the original transaction and the terminal that processed it.

| Attribute | Description | Required |
| --- | --- | --- |
| `idempotency_key` | Unique key for this request (1-64 characters). If you repeat a key, the API returns the same data. | **Yes** |
| `payment_id` | The `payment_id` of the original authorization. | **Yes** |
| `payment_method` | The payment method of the original transaction. We recommend that you omit it: Getnet uses the payment method of the original transaction. If you send it, it must match the original authorization. | No |
| `amount` | Amount in cents. Omit it: a reversal always covers the full amount. | No |
| `custom_key` | Your own key to identify the reversal (3-32 characters). | No |
| `additional_data.terminal` | Identifiers of the terminal that processed the original transaction. | **Yes** |
| `additional_data.terminal.terminal_code` | Terminal code. | **Yes (Brazil)** |
| `additional_data.terminal.logical_code` | Logical code of the terminal. | **Yes (Brazil)** |
| `additional_data.terminal.serial_number` | Serial number of the terminal. | **Yes (Brazil)** |
| `additional_data.card` | Card data of the original transaction. Send the object even without card data: `"card": {}`. | **Yes** |
| `additional_data.card.number` | Card number (PAN), up to 32 characters. | No |
| `additional_data.card.track_2` | Track 2 data, up to 150 characters. Accepted with or without `number`. | No |
| `additional_data.card.expiration_month` | Two-digit expiration month, as a string (for example, `"12"`). | No |
| `additional_data.card.expiration_year` | Two-digit expiration year, as a string (for example, `"26"`). | No |
| `additional_data.currency` | ISO 4217 currency code of the original transaction (for example, `BRL`). | No |

### Example 1: Reversal with Card Number

Used when you have the card number (PAN) of the original transaction.

```bash
curl --request POST \
  --url https://api.pre.globalgetnet.com/dpm/payments-gwproxy/v2/payments/reversal \
  --header 'Authorization: Bearer <YOUR_TOKEN>' \
  --header 'Content-Type: application/json' \
  --header 'x-seller-id: 19ffd677-3691-4c4d-88c9-79cc91b95c0d' \
  --data '{
  "idempotency_key": "b10be7a7-d76e-4cd6-8ebe-4f68b9271d9c",
  "payment_id": "b0b7851a-e558-4d94-b34e-86d69138de77",
  "custom_key": "2bc94fa13c8d4df28e52a996912bbab5",
  "additional_data": {
    "terminal": {
      "terminal_code": "TF123456",
      "logical_code": "654321",
      "serial_number": "ABC123"
    },
    "card": {
      "number": "4111111111111111",
      "expiration_month": "12",
      "expiration_year": "26"
    },
    "currency": "BRL"
  }
}'
```

### Example 2: Reversal with Track 2

Used when you send the Track 2 data instead of the `number` field. Track 2 already contains the card number.

```bash
curl --request POST \
  --url https://api.pre.globalgetnet.com/dpm/payments-gwproxy/v2/payments/reversal \
  --header 'Authorization: Bearer <YOUR_TOKEN>' \
  --header 'Content-Type: application/json' \
  --header 'x-seller-id: 19ffd677-3691-4c4d-88c9-79cc91b95c0d' \
  --data '{
  "idempotency_key": "3f6c2d8e-91a4-4b7e-8c05-d2e7a19b4f60",
  "payment_id": "b0b7851a-e558-4d94-b34e-86d69138de77",
  "additional_data": {
    "terminal": {
      "terminal_code": "TF123456",
      "logical_code": "654321",
      "serial_number": "ABC123"
    },
    "card": {
      "track_2": "4111111111111111=26122010000000000000"
    },
    "currency": "BRL"
  }
}'
```

### Example 3: Reversal without Card Data

Used when you do not have the card data of the original transaction. Send the `card` object empty.

```bash
curl --request POST \
  --url https://api.pre.globalgetnet.com/dpm/payments-gwproxy/v2/payments/reversal \
  --header 'Authorization: Bearer <YOUR_TOKEN>' \
  --header 'Content-Type: application/json' \
  --header 'x-seller-id: 19ffd677-3691-4c4d-88c9-79cc91b95c0d' \
  --data '{
  "idempotency_key": "7a2e9c41-5b3d-4f8a-9e16-c0d4b8f2a735",
  "payment_id": "b0b7851a-e558-4d94-b34e-86d69138de77",
  "additional_data": {
    "terminal": {
      "terminal_code": "TF123456",
      "logical_code": "654321",
      "serial_number": "ABC123"
    },
    "card": {},
    "currency": "BRL"
  }
}'
```

## Step 2: Verify the Response

On success, the API returns `HTTP 200` with `status` set to `REVERSED` and `reason_code` set to `00`.

```json
{
  "idempotency_key": "b10be7a7-d76e-4cd6-8ebe-4f68b9271d9c",
  "seller_id": "19ffd677-3691-4c4d-88c9-79cc91b95c0d",
  "request_id": "51d212f6-ad05-499c-90a1-e05c3b6ea0db",
  "payment_id": "b0b7851a-e558-4d94-b34e-86d69138de77",
  "order_id": "471994a7-ba22-453e-8afc-f0137d1710c2",
  "amount": 4000,
  "status": "REVERSED",
  "reason_code": "00",
  "reason_message": "Payment successful reversal.",
  "authorization_code": "601878",
  "trace_number": 0,
  "canceled_at": "2026-09-04T18:14:54.057Z",
  "custom_key": "2bc94fa13c8d4df28e52a996912bbab5"
}
```

The `amount` field always contains the full amount of the original authorization. The `canceled_at` field records the date and time of the reversal.

### Handle Errors

If the request fails, the response body carries the error in `details[]`. Each entry has these fields:

- `status`: The result of the request, such as `DENIED`.
- `error_code`: The error code.
- `description`: The HTTP status text, such as `Bad Request`.
- `description_detail`: The explanation of the error.

For example:

```json
{
  "message": "Bad Request",
  "name": "RequestCancelApi",
  "status_code": 400,
  "details": [
    {
      "status": "DENIED",
      "error_code": "CANCEL-400",
      "description": "Bad Request",
      "description_detail": "Denied. Payment already reversed"
    }
  ]
}
```

Use the HTTP status to decide your next action:

| HTTP status | What to do |
| --- | --- |
| `400` | Fix the request before you send it again. `CANCEL-400` with `Denied. Payment already reversed` means the payment is already reversed. Do not retry. |
| `401` | Check your credentials and your Bearer token. Do not retry with the same token. |
| `429`, `5xx`, or a timeout | Retry with the same `idempotency_key`. If the first request went through, the API returns the same result instead of processing a second reversal. |

A `200` response can also carry `status` set to `DENIED` or `ERROR`. In that case the reversal was not processed. Check `reason_code` and `reason_message` for the cause.

For the full list of error codes, see [Errors](/en/global-api/reference-global/errors).

## Step 3: Receive the Reversal Webhook (Optional)

Subscribe to the `REVERSED_TRANSACTIONS` event to get notified when a reversal is processed. To subscribe, call the [Subscribe to a webhook event endpoint](https://docs.globalgetnet.com/en/products/online-payments/regional-api/swagger#tag/webhooks/post/dpm/webhooks/v1/subscriptions) (`POST /dpm/webhooks/v1/subscriptions`) with `event` set to `REVERSED_TRANSACTIONS`.

The payload includes `complete_cancel`, which is always `true` for this event. For the full payload, see the [Webhooks Reference](/en/global-api/webhooks-global/webhooks-reference).

## Next Steps

Now that you know how to reverse payments, explore these related card-present features:

- **[Cancel a Card Present Payment](/en/global-api/sep-card-present/payment-guides-cp/cancel-a-payment-cp)**: Return the funds of a captured transaction.
- **[Pre-authorized Payments](/en/global-api/sep-card-present/payment-guides-cp/pre-auth-payment-cp)**: Manage two-step flows for reservations and delayed captures.
- **[Single-Step Payments](/en/global-api/sep-card-present/payment-guides-cp/single-step-payment-cp)**: Process standard chip and magnetic stripe sales.