> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cleo-pay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Cancel and retry payments

> Cancel a held or scheduled payment and learn where the money goes, or retry a bill whose payment failed on the rail it failed on.

You can cancel what the Cleo web app lets a payer cancel, and retry what it lets a payer retry. Both need `payments:initiate` and an `Idempotency-Key`, and both are money writes.

## Cancel

`POST /v1/payments/{paymentId}/cancel` cancels a `held` or `scheduled` payment. You can send an optional `reason` (up to 500 characters), which is shown on the bill.

```bash theme={null}
curl -X POST https://api.stg.cleo-pay.com/v1/payments/e4f5a6b7-c8d9-4e0f-9a1b-2c3d4e5f6a7b/cancel \
  --header "Authorization: Bearer $CLEO_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: 4c5d6e7f-8a9b-4c0d-9e1f-2a3b4c5d6e7f" \
  --data '{ "reason": "Vendor will be paid by check" }'
```

The answer is the payment after the cancel and a `message` that says where the money went:

| What you cancelled | Result |
| - | - |
| A Dwolla hold | The money goes back to the bank in 1 to 3 business days. The payment becomes `refund_pending`, then `refunded`. |
| A Cleo Pay hold | The bank debit is stopped, or the money is in (or on its way to) the Cleo Pay balance. The payment becomes `refunded`. |
| A scheduled payment | Nothing moved. The payment becomes `cancelled`. |

Any other status answers `409 payment_not_cancellable` with `details.status`. A payment that changed while it was being cancelled answers the same way.

## Retry

`POST /v1/payables/{payableId}/retry-payment` retries a bill whose payment failed. It takes no body: the retry runs on the failed payment's rail, never on the business's current default.

```bash theme={null}
curl -X POST https://api.stg.cleo-pay.com/v1/payables/b1e2c3d4-5f6a-4b8c-9d0e-1f2a3b4c5d6e/retry-payment \
  --header "Authorization: Bearer $CLEO_API_KEY" \
  --header "Idempotency-Key: 8e9f0a1b-2c3d-4e4f-8a5b-6c7d8e9f0a1b"
```

The answer has the same shape as `POST /v1/payments`.

| Case | Answer |
| - | - |
| The bill's payment did not fail | `409 payment_not_retryable` with `details.status` |
| The retry would pull from the Cleo Pay linked bank again | `409 payment_not_retryable`. That pull needs your user's ACH debit authorization, so pay it with `POST /v1/payments` (`paymentRail: "CLEO_PAY"`, `fundingSource: "BANK"`, `achAuthorizationAccepted: true`). |
| The bill reached its retry limit | `validation_error`. Contact Cleo support. |

You can also retry by paying the failed bill with `POST /v1/payments`. Then name the failed payment's rail, and on Dwolla the same bank. Anything else answers `validation_error` with the fields to send.

## If the answer is lost

Cancel and retry never run twice under one key. If a cancel or retry fails in a way that may have moved money, every retry with that key answers `409 payment_unconfirmed`. Check `GET /v1/payments/{paymentId}` or `GET /v1/payments?payableId=...` before you use a new key. See [Idempotency](/reference/idempotency).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.