# Cancel Invoice

> Cancel an open invoice before the customer locks an asset, understand the allowed state transition, and handle the cancellation response.

`POST /v1/invoices/:invoice_id/cancel`

:::endpoint
POST /v1/invoices/:invoice_id/cancel
:::

**API key:** `Payment`

Cancel an invoice that is still in `awaiting_client` status. Once the customer selects a token/network and the invoice moves to `awaiting_payment`, cancellation is no longer possible — and a paid or expired invoice can never be cancelled. Cancelling an already-cancelled invoice is a no-op: it returns `200` with the same invoice, not an error.

## Request body

`reason` is required (max 500 characters). It is recorded in the audit log and carried on the `invoice.cancelled` webhook.

```json
{
  "reason": "Customer requested cancellation"
}
```

## Response (200 OK)

```json
{
  "invoice_id": "inv_5CcyDYmMUGtzYL10q0Iimr",
  "project_id": "prj_xFukZuAJZR06pLVBh3uwzv",
  "status": "cancelled",
  "is_final": true,
  "is_test": true,
  "payment_url": "https://checkout.paymos.io/invoice/inv_5CcyDYmMUGtzYL10q0Iimr",
  "order": {
    "external_id": "order-12345",
    "client_id": "customer-67890",
    "amount": "100.00",
    "currency": "USD"
  },
  "created_at": 1739280600,
  "updated_at": 1739280660,
  "expires_at": 1739284200
}
```

## Errors

See [Error Codes](/docs/errors/codes.md) for the full catalogue. The `type` URI in every error response deep-links to the matching row.
