# 

## Prerequisites

* A valid API key — see [Obtain API credentials](/docs/how-tos/setup/obtain-credentials)
* A transaction in `authorized` or `captured` state (before batch closure)


## Step 1: Confirm the transaction state

Retrieve the transaction to verify it has not already settled.

```shell
curl -X GET \
  https://api.dev.paradisegateway.net/v1/transactions/TRANSACTION-01JMRSPCK7XVNP3KS8F2W4T6Y \
  -H "APIKEY: YOUR-API-KEY"
```

Check the `transaction_state` field. If it is `authorized` or `captured`, you can cancel. If it is `settled`, you must [refund instead](/docs/how-tos/manage-transactions/refund-settled-auth).

## Step 2: Cancel the transaction

Send `POST /v1/transactions/{id}/cancel` with the cancel type and amount.

### Card cancel

curl
```shell
curl -X POST \
  https://api.dev.paradisegateway.net/v1/transactions/TRANSACTION-01JMRSPCK7XVNP3KS8F2W4T6Y/cancel \
  -H "Content-Type: application/json" \
  -H "APIKEY: YOUR-API-KEY" \
  -d '{
    "type": "cancel",
    "amount": 15000
  }'
```

Python
```python
import requests

transaction_id = "TRANSACTION-01JMRSPCK7XVNP3KS8F2W4T6Y"
resp = requests.post(
    f"https://api.dev.paradisegateway.net/v1/transactions/{transaction_id}/cancel",
    headers={"Content-Type": "application/json", "APIKEY": "YOUR-API-KEY"},
    json={"type": "cancel", "amount": 15000},
)
print(resp.json())
```

JavaScript
```javascript
const transactionId = "TRANSACTION-01JMRSPCK7XVNP3KS8F2W4T6Y";
const resp = await fetch(
  `https://api.dev.paradisegateway.net/v1/transactions/${transactionId}/cancel`,
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "APIKEY": "YOUR-API-KEY",
    },
    body: JSON.stringify({ type: "cancel", amount: 15000 }),
  }
);
console.log(await resp.json());
```

C#
```csharp
var transactionId = "TRANSACTION-01JMRSPCK7XVNP3KS8F2W4T6Y";
var payload = new { type = "cancel", amount = 15000 };
var resp = await client.PostAsJsonAsync(
    $"https://api.dev.paradisegateway.net/v1/transactions/{transactionId}/cancel",
    payload);
Console.WriteLine(await resp.Content.ReadAsStringAsync());
```

Java
```java
String transactionId = "TRANSACTION-01JMRSPCK7XVNP3KS8F2W4T6Y";
String body = """
    {"type": "cancel", "amount": 15000}
    """;
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create(
        "https://api.dev.paradisegateway.net/v1/transactions/"
        + transactionId + "/cancel"))
    .header("Content-Type", "application/json")
    .header("APIKEY", "YOUR-API-KEY")
    .POST(HttpRequest.BodyPublishers.ofString(body)).build();
HttpResponse<String> resp = client.send(request,
    HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());
```

Go
```go
transactionID := "TRANSACTION-01JMRSPCK7XVNP3KS8F2W4T6Y"
payload := strings.NewReader(`{"type": "cancel", "amount": 15000}`)
req, _ := http.NewRequest("POST",
    "https://api.dev.paradisegateway.net/v1/transactions/"+transactionID+"/cancel",
    payload)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("APIKEY", "YOUR-API-KEY")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
```

PHP
```php
$id = "TRANSACTION-01JMRSPCK7XVNP3KS8F2W4T6Y";
$ch = curl_init("https://api.dev.paradisegateway.net/v1/transactions/$id/cancel");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ["Content-Type: application/json", "APIKEY: YOUR-API-KEY"],
    CURLOPT_POSTFIELDS => json_encode(["type" => "cancel", "amount" => 15000]),
]);
echo curl_exec($ch); curl_close($ch);
```

Ruby
```ruby
require "net/http"; require "json"
id = "TRANSACTION-01JMRSPCK7XVNP3KS8F2W4T6Y"
uri = URI("https://api.dev.paradisegateway.net/v1/transactions/#{id}/cancel")
req = Net::HTTP::Post.new(uri, {
  "Content-Type" => "application/json", "APIKEY" => "YOUR-API-KEY",
})
req.body = { type: "cancel", amount: 15000 }.to_json
resp = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts resp.body
```

### ACH cancel

Use the appropriate cancel type for ACH transactions.

| Original transaction type | Cancel type |
|  --- | --- |
| `payment` | `cancel` |
| `payout` | `cancel` |


```json
{
  "type": "cancel",
  "amount": 50000
}
```

## Step 3: Verify the response

A successful cancel returns `transaction_state: canceled`.

```json
{
  "id": "TRANSACTION-01JMRSPCK7XVNP3KS8F2W4T6Y",
  "object": "CancelTransactionResponse",
  "type": "cancel",
  "transaction_state": "canceled",
  "response_status": "Approved",
  "response_code": "00",
  "response_message": "The API request is approved.",
  "amount": 15000,
  "correlation_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
```

The hold on the person's funds is released immediately.

Cancel vs. refund
If the `transaction_state` is `settled`, a cancel will fail. Use a [refund](/docs/how-tos/manage-transactions/refund-settled-auth) instead.

## Next steps

* [Refund a settled transaction](/docs/how-tos/manage-transactions/refund-settled-auth) — return funds after settlement
* [About cancels and refunds](/docs/concepts/transactions/cancels-and-refunds)