# Cancel

`POST /api/trade/cancel`

Cancels a hotel booking order, validating order state and recording an
audit trail as the cancellation is processed.

Both full and partial cancellation are supported; which one applies is
determined by supplier policy and by the current state of the order.

**Critical Prerequisites:**
- **Order ID**: Must be provided to identify the target order
- **JWT Authentication**: Bearer token required in Authorization header
- **Valid Order State**: Order must be in a cancellable state

**Cancellation Types:**
- **Full Cancellation**: Complete order cancellation (most common)
- **Partial Cancellation**: Cancel specific nights or rooms (supplier-dependent)
- **State-Dependent**: Cancellation rules vary by order status and supplier policies

**Enterprise Reliability Features:**
- Order state machine validation and transitions
- Comprehensive audit logging and tracking
- Automatic rollback on processing failures
- CQRS event publishing for downstream processing
- Processing time monitoring and performance tracking

**State Validation:**
- Validates order exists and is accessible
- Checks current order state for cancellation eligibility
- Prevents cancellation of non-cancellable orders
- Returns appropriate validation errors for invalid states

**Processing Flow:**
1. Validate order existence and accessibility
2. Check order state for cancellation eligibility
3. Update order state to NeedCancel
4. Publish cancellation event to CQRS queue
5. Handle rollback if processing fails
6. Record comprehensive audit logs

**Error Handling:**
- Order not found errors with appropriate HTTP status
- State validation errors for non-cancellable orders
- Downstream timeout errors for supplier delays
- Automatic rollback on critical processing failures

**Common Use Cases:**
- Customer-initiated order cancellations
- Administrative order cancellations
- Policy-based cancellation processing
- Order lifecycle management

## Request headers

| Header | Required | Description |
| --- | --- | --- |
| `Client-Request-Timestamp` | No | client request time(start to send request); unix timestamp |
| `Currency` | No | Requested currency for the rates, in https://en.wikipedia.org/wiki/ISO_4217 format |
| `IP` | No | client IP address, compatible with both IPv4 and IPv6 |
| `Language` | No | https://masonreview.com/posts/ietf-bcp-47-language-tags/, eg: "en", "en-US"; default "en-US" |
| `Market` | No | Point-of-sale market for this call, as an ISO 3166-1 alpha-2 country code. Required only when your account carries a market restriction: an allow-list cannot admit a market you have not stated, so such an account refuses calls that omit it. |
| `Request-Id` | No | for identifying the current request, it can't be duplicate |
| `Session-Id` | Yes | Suggested provided in request by client. It's required in booking flow. |
| `Test` | No | Test flags. support key-value pairs, eg, "hotel=HC1&scenario=priceChange".If it's not recognized by server, the call will behave as if the "Test" header was not provided. |
| `Timeout-Milliseconds` | No | timeout specified by client, and server will try its best to return data before this timeout |
| `Trace-Id` | No | for tracing a group of requests |
| `User-Ref` | No | Your own identifier for the person on whose behalf this call is made. Required only once named users have been authorised on your account, after which every call must identify one and is authorised against that user's scopes as well as the key's. |
| `Authorization` | Yes | starts with "Bearer ". got from Ticket response. Ticket doesn't need it |

## Request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `customerReferenceNo` | string | Yes |  |
| `supplierReferenceNo` | string | Yes |  |
| `reason` | string | No |  |


### Example request

```json
{
  "customerReferenceNo": "9d1f4b2a-7c60-4f3e-9a58-1b0c2d3e4f50",
  "supplierReferenceNo": "TTD-2609-004871",
  "reason": "Guest cancelled within the free-cancellation window"
}
```

## Response

Successful calls return the standard envelope. `code` is `0` on success — check it rather than the HTTP status alone, because some business failures are delivered with HTTP 200.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `code` | integer | No |  |
| `msg` | string | No |  |
| `data` | hotel.trade.protocol.CancelResp | No |  |
|    `data.serviceFee` | Money | No | ServiceFee is the service fee charged by supplier, not refunded |
|       `data.serviceFee.currency` | string | Yes | Currency code, e.g. "USD". |
|       `data.serviceFee.amount` | number | Yes | Monetary amount, e.g. "14.50". |
|    `data.status` | OrderStatus | No | Status indicates the current status of the order after cancellation Allowed: `0`, `1`, `2`, `3`, `4`, `5`. |


## Failure responses

| HTTP | Meaning |
| --- | --- |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Order not found |
| 429 | Too Many Requests |
| 504 | Downstream supplier timeout |

Every failure uses the `{ code, msg }` envelope. See [Error handling](../guides/error-handling) for the full business-code table.
