> For the complete index of the 402pay docs, see [llms.txt](https://developer.402pay.co/llms.txt).

# Cancel a checkout

Close a checkout the customer is leaving, before any funds are on the way.

`POST https://dash.402pay.co/api/v1/checkouts/{id}/cancel`

For a customer who leaves without paying. Public, like [creating a checkout](https://developer.402pay.co/api/checkouts/create.md): the checkout's ID is all it takes. Called with your secret key, the response also has `email`, `reporting` and `fee_rate_bps`.

Works while the checkout is `open` or `awaiting_customer`. It becomes `canceled` with `canceled_by` set to `customer`. The secure payment page of a card attempt isn't closed, though: a payment the customer still finishes there reaches you in `needs_review`, and you receive `payment.needs_review`. Canceling twice returns the checkout as it is.

What happens to the payment depends on where it came from. A link's payment fails, with a `failed` event whose `reason` is `canceled`, and you receive `payment.failed`. A payment you created through the API stays `pending`, so the customer can come back and try again until it expires. On a remainder checkout, what already arrived stays with the payment.

> A customer who paid anyway can report the transfer with [a claim](https://developer.402pay.co/api/checkouts/claim.md).

### Path

- `id` (string, required): The checkout's ID, such as `chk_8zXVc2SbCBDho78Q`.

### Errors

- 404 `not_found` No checkout has that ID.
- 409 `checkout_not_cancelable` The checkout isn't `open` or `awaiting_customer`: funds may already be on the way, or it has ended.

Any request can also fail on its key or its body. See [errors](https://developer.402pay.co/api/errors.md).

Request, cURL:

```bash
curl -X POST "https://dash.402pay.co/api/v1/checkouts/chk_8zXVc2SbCBDho78Q/cancel"
```

Request, Node.js:

```js
const response = await fetch("https://dash.402pay.co/api/v1/checkouts/chk_8zXVc2SbCBDho78Q/cancel", {
  method: "POST",
});
const { data } = await response.json();
```

Request, Python:

```python
import requests

response = requests.post(
    "https://dash.402pay.co/api/v1/checkouts/chk_8zXVc2SbCBDho78Q/cancel",
)
data = response.json()["data"]
```

Response, 200 OK:

```json
{
  "data": {
    "id": "chk_8zXVc2SbCBDho78Q",
    "kind": "checkout",
    "status": "canceled",
    "rail": "crypto",
    "link_id": null,
    "payment_id": "pmt_pxYW5vHfVt1xTIT2",
    "amount": 4900,
    "currency": "USD",
    "breakdown": {
      "currency": "USD",
      "price": 4900,
      "processing_fee": null,
      "network_fee": 90,
      "total": 4990
    },
    "crypto": {
      "asset": "USDC",
      "network": "ethereum",
      "amount": "49.00",
      "address": "0xB82AFd9E40ED990A37c7eeB43e8d04528732ef39",
      "payment_uri": "ethereum:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48@1/transfer?address=0xB82AFd9E40ED990A37c7eeB43e8d04528732ef39&uint256=49000000",
      "rate": {
        "amount": 100,
        "currency": "USD"
      },
      "received_amount": "0.00",
      "remaining_amount": null,
      "remaining_payment_uri": null,
      "overpaid_amount": null,
      "detected_network": null,
      "tx_hash": null,
      "explorer_url": null
    },
    "card": null,
    "confirmations": {
      "current": 0,
      "required": 4
    },
    "remainder": false,
    "canceled_by": "customer",
    "replaced_by": null,
    "failure_code": null,
    "review_reason": null,
    "success_url": "https://example.com/thanks",
    "expires_at": "2026-09-27T18:27:57.906Z",
    "sent_at": null,
    "created_at": "2026-09-27T18:12:57.906Z",
    "updated_at": "2026-09-27T18:12:57.975Z"
  }
}
```
