# Cancel a confirmed hotel booking

> Cancels a booking of your agency and refunds it according to the cancellation schedule of the rate.

Endpoint: `POST /hotels/cancel_hotel`

Source: https://fx-port.com/docs/api/cancel-hotel

`POST /api/v1/hotels/cancel_hotel`

Requires an API key with **Read+Write** permission: a Read key is refused with `read_write_permission_required`.

Only a booking whose `status` is `confirmed` can be cancelled: right after `book_hotel` it is `pending`, so wait for `confirmed`. The booking becomes `refunded` (free cancellation), `partial_refund` (a penalty applied) or `cancelled` (nothing refunded). The call takes 1 to 4 seconds. The supplier occasionally takes 30 seconds and the call then fails with `503 supplier_timeout`: the cancellation may or may not have happened, so read the booking, and call again only if it is still `confirmed`. In the sandbox cancel every test booking: it is free until 21:00 UTC on the check-in day.

## Request

### Body

Required, JSON.

- `booking_id` (string, required): The id of the booking to cancel: the `bookingId` of `book_hotel`.
- `partner_order_id` (string, deprecated, optional): Legacy name: use `booking_id`. The booking id, in its older spelling. Use `booking_id`.
- `partnerOrderId` (string, deprecated, optional): Legacy name: use `booking_id`. The booking id, in its older spelling. Use `booking_id`.
- `bookingId` (string, deprecated, optional): Legacy name: use `booking_id`. The booking id, in its older spelling. Use `booking_id`.

### Example request

```bash
curl https://api.fx-port.com/api/v1/hotels/cancel_hotel \
  -H "Authorization: Bearer fxp_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "booking_id": "HMVXX4ZQ3"
}'
```

## Response

### 200: The booking is cancelled. `bookingStatus` and `refund` say what was given back.

- `environment` (string): The environment of the key that made the call: `sandbox` for fxp_test_ keys, `live` for fxp_live_ keys. Present in every JSON body. One of `sandbox`, `live`.
- `request_id` (string): The id of the request, also in the `X-Request-Id` header.
- `warnings` (array of object): Present only when the request used a previous spelling of a field or something the endpoint ignored.
  - `code` (string): What the warning is about. One of `deprecated_field`, `ignored_field`, `coerced_value`, `deprecated_value`, `deprecated_endpoint`.
  - `field` (string): The request field the warning is about.
  - `replacement` (string): The name to use instead, for `deprecated_*` warnings.
  - `message` (string): A sentence that says what happened and what to do.
  - `documentation_url` (string): Where the naming rules are explained.
- `success` (boolean): `true` when the supplier cancelled the booking.
- `status` (string): Always `ok`: the call worked. The state of the booking is `bookingStatus`. Always `ok`.
- `bookingId` (string, deprecated): Legacy name: use `booking_id`. The id of the booking that was cancelled.
- `booking_id` (string): The id of the booking that was cancelled. The snake_case twin of `bookingId`, with the same value: use this name.
- `bookingStatus` (string, deprecated): Legacy name: use `booking_status`. The new status of the booking: `refunded` (free cancellation), `partial_refund` (a penalty applied) or `cancelled` (no refund). One of `refunded`, `partial_refund`, `cancelled`.
- `booking_status` (string): The new status of the booking: `refunded` (free cancellation), `partial_refund` (a penalty applied) or `cancelled` (no refund). The snake_case twin of `bookingStatus`, with the same value: use this name. One of `refunded`, `partial_refund`, `cancelled`.
- `adminCancel` (boolean): `true` when FX-Port staff cancelled the booking. Always `false` for a call of yours.
- `refund` (object): What the cancellation gave back.
  - `cancellationType` (string, deprecated): Legacy name: use `cancellation_type`. `free`: the supplier refunded everything; `partial`: a penalty applied; `none`: no refund. One of `free`, `partial`, `none`.
  - `cancellation_type` (string): `free`: the supplier refunded everything; `partial`: a penalty applied; `none`: no refund. The snake_case twin of `cancellationType`, with the same value: use this name. One of `free`, `partial`, `none`.
  - `type` (string): The same as a label for people. One of `Free cancellation`, `Partial cancellation`, `No refund`.
  - `agencyAmount` (number, deprecated): Legacy name: use `agency_refund_amount`. What is credited back to your agency, in `currency`. `0` for `none`.
  - `agency_refund_amount` (number): What is credited back to your agency, in `currency`. `0` for `none`. The snake_case twin of `agencyAmount`, with the same value: use this name.
  - `travelerAmount` (number, deprecated): Legacy name: use `traveler_refund_amount`. What the traveler gets back, in `currency`.
  - `traveler_refund_amount` (number): What the traveler gets back, in `currency`. The snake_case twin of `travelerAmount`, with the same value: use this name.
  - `currency` (string, deprecated): Legacy name: use `agency_currency`. The currency of your agency.
  - `agency_currency` (string): The currency of your agency. The snake_case twin of `currency`, with the same value: use this name.
  - `providerAmount` (number, deprecated): Legacy name: use `supplier_refund_amount`. What the supplier refunded, in `providerCurrency`.
  - `supplier_refund_amount` (number): What the supplier refunded, in `providerCurrency`. The snake_case twin of `providerAmount`, with the same value: use this name.
  - `providerCurrency` (string, deprecated): Legacy name: use `supplier_currency`. The supplier's currency: `EUR`.
  - `supplier_currency` (string): The supplier's currency: `EUR`. The snake_case twin of `providerCurrency`, with the same value: use this name.
- `refundProcessed` (boolean, deprecated): Legacy name: use `refund_processed`. `true` when the refund was handled. In the sandbox nothing moves, and the flag is still `true`.
- `refund_processed` (boolean): `true` when the refund was handled. In the sandbox nothing moves, and the flag is still `true`. The snake_case twin of `refundProcessed`, with the same value: use this name.
- `webhookSent` (boolean): Describes an internal step of FX-Port, not a message to you: FX-Port sends no webhooks to customers.
- `processingTime` (number, deprecated): Legacy name: use `processing_time`. Seconds the call took.
- `processing_time` (number): Seconds the call took. The snake_case twin of `processingTime`, with the same value: use this name.

```json
{
  "environment": "sandbox",
  "success": true,
  "status": "ok",
  "bookingId": "HMVXX4ZQ3",
  "bookingStatus": "refunded",
  "adminCancel": false,
  "refund": {
    "cancellationType": "free",
    "type": "Free cancellation",
    "agencyAmount": 1482,
    "travelerAmount": 1484.97,
    "currency": "DZD",
    "providerAmount": 3,
    "providerCurrency": "EUR"
  },
  "refundProcessed": true,
  "webhookSent": true,
  "processingTime": 3.488
}
```

## Errors

| Status | Code | Example message |
| --- | --- | --- |
| 400 | `invalid_status` | Booking is 'pending', can only cancel 'confirmed' bookings |
| 400 | `missing_field` | Missing required field: booking_id |
| 400 | `invalid_booking_id` | 'booking_id' must be 1 to 256 characters: letters, digits and '_ . : -' (got 'abc def'). |
| 403 | `read_write_permission_required` | This endpoint requires an API key with read_write permission. |
| 403 | `forbidden` | This booking does not belong to your agency. Only the agency that made the booking can cancel it. |
| 404 | `booking_not_found` | Booking HZZZZZZZZ not found |
| 502 | `supplier_invalid_response` | The hotel supplier returned an answer that could not be used. Retry in a few minutes. |
| 503 | `supplier_timeout` | The hotel supplier did not answer in time, so the request may or may not have been processed: read the booking's status before you retry. |

See [Errors](https://fx-port.com/docs/errors.md) for every code and how to react.

## Related guides

- [Cancel a hotel booking](https://fx-port.com/docs/hotels/cancel.md)
