# Confirm a cancellation

> Confirm a quoted cancellation of an issued Duffel order: the order is cancelled and the refund goes to your balance. Irreversible.

Endpoint: `POST /api/v1/flights/confirm_cancel`

Source: https://fx-port.com/docs/flights/confirm-cancel

Confirm the cancellation of an issued **Duffel order** that you quoted with [`cancel_quote`](https://fx-port.com/docs/flights/cancel-quote.md). The order is cancelled at the airline and the refund is credited to your FX-Port balance.

**Permission:** Read+Write. **Rate group:** default (6,000 requests per minute per key).


> [!CAUTION]
> **This cannot be undone.** After the confirmation the order is cancelled for good and the refund of the quote is what you get. Show the amount of `cancel_quote` to your customer **before** you call this endpoint, and call it once: a second call answers `already_cancelled`.


## Request body

| Field | Type | Required | Description |
|---|---|---|---|
| `cancellation_id` | string | Yes | The `ore_...` id of `cancel_quote` (`cancellation.cancellationId`). |
| `order_id` | string | Yes | The supplier's order id of the booking (`booking_id` and `pnr` are accepted as other names). It makes FX-Port check that the booking is yours **and** update the booking (status, refund) and the balance. It is required together with `cancellation_id`: without it the call is `400 missing_field`, and nothing is cancelled. |
| `supplier_id` | string | No | Default `duffel_1`. |

Legacy names: `cancellationId`, `orderId`, `bookingId`, `supplierId`. If `order_id`, `booking_id` and `pnr` hold different values, the first one wins and an `ignored_field` warning names the others.

## Request example


**Request**

```bash
curl https://api.fx-port.com/api/v1/flights/confirm_cancel \
  -H "Authorization: Bearer fxp_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "cancellation_id": "ore_0000BC0VG9WBaFAZ83u3yy",
  "order_id": "ord_0000BC0VDONwA54LrfoCkm"
}'
```


## Response example

Real response of 2026-11-01:

~~~json
{
  "environment": "sandbox",
  "success": true,
  "requestId": "64666d3c",
  "orderId": "ord_0000BC0VDONwA54LrfoCkm",
  "processingTime": 0.245,
  "confirmation": {
    "cancellationId": "ore_0000BC0VG9WBaFAZ83u3yy",
    "orderId": "ord_0000BC0VDONwA54LrfoCkm",
    "status": "confirmed",
    "refund": {
      "originalRefundCurrency": "USD",
      "originalRefundAmount": 76.86,
      "refundCurrency": "DZD",
      "refundAmount": 19215.0,
      "refundTo": "FX-Port Balance",
      "refundToRaw": "balance",
      "convertedSupplierRefundAmount": 19215.0,
      "isFullBalanceRefund": false,
      "kioskCommissionRefund": 0.0
    },
    "confirmedAt": "2026-11-01T14:30:04.851325Z",
    "createdAt": "2026-11-01T14:28:32.488592Z",
    "airlineCredits": null,
    "liveMode": false,
    "message": "Order cancellation confirmed. Refund will be processed."
  },
  "supplier": { "id": "duffel_1", "technology": "duffel", "name": "Duffel" },
  "agency": { "currency": "DZD" },
  "exchangeRate": { "rate": 250.0, "marginPercent": 0.0, "fromCurrency": "USD", "toCurrency": "DZD" },
  "meta": {
    "cancellationConfirmedAt": "2026-11-01T14:30:04.851325Z",
    "refundProcessing": { "method": "FX-Port Balance", "estimatedDays": "Immediate", "description": "Refund credited to your FX-Port balance" }
  },
  "postProcessing": { "refundMethod": "balance", "emailSent": false }
}
~~~

| Field | Meaning |
|---|---|
| `confirmation.status` | `confirmed`. |
| `confirmation.refund` | The refund of the quote: `refundAmount` in your currency, `originalRefundAmount` in the supplier's. |
| `confirmation.message` | A sentence for your logs. |
| `meta.refundProcessing` | How the refund is paid: `FX-Port Balance`, `Immediate`. |
| `postProcessing.refundMethod` | `balance`. |

After the confirmation [`get_booking`](https://fx-port.com/docs/flights/get-booking.md) shows the status `partial_refund` with `refund_amount` (19215.0 here, of 21505.29 paid), `refund_currency` and `refund_method: "balance"`.

## Errors

The supplier's refusals are `200` answers with `success: false` (read `success`).

| Where | `error.code` | Meaning |
|---|---|---|
| `200`, `success: false` | `already_cancelled` | The order was already cancelled. |
| `200`, `success: false` | `not_found` | Duffel does not know this `cancellation_id`. |
| `400` | `bad_request` | No `cancellation_id` (`Missing required parameter: cancellation_id`), or the supplier is not Duffel. |
| `400` | `missing_field` | No `order_id` (`errors[0].field` is `order_id`): it is required with `cancellation_id`. |
| `400` | `invalid_cancellation_id`, `invalid_booking_id` | An id is not a valid token (letters, digits and `- _ . : = ~`, up to 128 characters). |
| `403` | `read_write_permission_required` | A read-only key. |
| `404` | `booking_not_found` | `order_id` is not a booking of your agency in this environment. An unknown order and the order of another agency are answered the same, and nothing is cancelled. |

## Related

- [Cancel quote](https://fx-port.com/docs/flights/cancel-quote.md) and [Post-booking operations](https://fx-port.com/docs/flights/post-booking.md).
