> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.etera.dev/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.etera.dev/_mcp/server.

# Cancel Booking

POST https://api.etera.dev/account/bookings/{bookingId}/cancel
Content-Type: application/json

Cancel a booking by ID for any vertical (Restaurant, Experience, Hotel).

## Supported Booking Types

* **RESTAURANT**: Restaurant reservations
* **EXPERIENCE**: Experience bookings (tours, activities)
* **HOTEL**: Hotel reservations

## Process Flow

1. Validates authorization token
2. Routes to appropriate external API based on dataType
3. Transforms response to standardized format
4. Returns cancellation details including refund information

**Note for Experience Bookings**: Cancellation is processed asynchronously by Headout. The API response indicates the cancellation request was submitted, not that it's completed. The actual cancellation status is updated via webhook or polling when Headout completes processing.

## External API Endpoints

* Restaurant: `POST {RESTAURANT_API_URL}/{bookingId}/cancel`
* Experience: `POST {EXPERIENCE_API_URL}/{bookingId}/cancel?reason=<reason>&other_reason=<optional>`
  * Uses query parameters instead of request body
  * Reason can be enum (TICKETS\_NOT\_RECEIVED, CHANGE\_OF\_TRAVEL\_PLANS, etc.) or free text
  * Cancellation is processed asynchronously by Headout
* Hotel: `POST {HOTEL_API_URL}/{bookingId}/cancel`

## Timeout

* Request timeout: 10 seconds per external API call

## Error Handling

* 400: Validation errors, missing parameters
* 401: Missing or invalid authorization token
* 404: Booking not found
* 502: External API errors, timeouts
* 500: Internal server errors

Reference: https://docs.etera.dev/platform/account/account-api/bookings/cancel-booking

## Authentication

- `Authorization` header (bearer token, required) — Bearer authentication of the form `Bearer <token>`, where token is your auth token.

## Servers

- `https://api.etera.dev/account` (Production, default)
- `https://api-stage.etera.dev/account` (Staging)
- `https://api-dev.etera.dev/account` (Development)

## Request

### Path parameters

- `bookingId` (string, required) — Unique identifier of the booking to cancel

### Body (application/json)

This endpoint expects an object.

- `dataType` (BookingsBookingIdCancelPostRequestBodyContentApplicationJsonSchemaDataType, required)
- `reason` (string, optional)
- `other_reason` (string, optional) — Additional details when reason is OTHER (for Experience bookings)

## Response

### 200

Booking cancelled successfully

- `success` (boolean, optional)
- `message` (string, optional)
- `bookingId` (string, optional)
- `dataType` (enum, optional)
  - Allowed values: `RESTAURANT`, `EXPERIENCE`, `HOTEL`
- `cancellationId` (string, optional) — Unique cancellation identifier
- `refundAmount` (double, optional) — Refund amount in currency units
- `refundStatus` (enum, optional) — Status of the refund process
  - Allowed values: `pending`, `processed`, `failed`, `not_applicable`
- `cancelledAt` (datetime, optional) — ISO timestamp of cancellation
- `data` (map from string to any, optional) — Additional cancellation details from external API

## Errors

### 400 Bad Request Error

Bad Request - Validation error or service error

- `success` (boolean, optional)
- `error` (string, optional)
- `code` (string, optional)
- `bookingId` (string, optional)
- `details` (list of BookingsBookingIdCancelPostResponsesContentApplicationJsonSchemaDetailsItems, optional) — Validation error details

### 401 Unauthorized Error

Unauthorized - Missing or invalid authorization token

- `success` (boolean, optional)
- `error` (string, optional)
- `code` (string, optional)
- `bookingId` (string, optional)

### 404 Not Found Error

Not Found - Booking not found

- `success` (boolean, optional)
- `error` (string, optional)
- `code` (string, optional)
- `bookingId` (string, optional)

### 500 Internal Server Error

Internal Server Error

- `success` (boolean, optional)
- `error` (string, optional)
- `code` (string, optional)
- `bookingId` (string, optional)

### 502 Bad Gateway Error

Bad Gateway - External API error or timeout

- `success` (boolean, optional)
- `error` (string, optional)
- `code` (string, optional)
- `bookingId` (string, optional)

## Types

### BookingsBookingIdCancelPostRequestBodyContentApplicationJsonSchemaDataType

- "RESTAURANT"
- "EXPERIENCE"
- "HOTEL"

### BookingsBookingIdCancelPostResponsesContentApplicationJsonSchemaDetailsItems

- `field` (string, optional)
- `message` (string, optional)

## Examples

### Restaurant Cancellation Response

**Request**

```json
{
  "dataType": "RESTAURANT"
}
```

**Response**

```json
{
  "success": true,
  "message": "Restaurant booking cancelled successfully",
  "bookingId": "rest_booking_123456",
  "dataType": "RESTAURANT",
  "cancellationId": "cancel_789012",
  "refundAmount": 150,
  "refundStatus": "pending",
  "cancelledAt": "2025-01-15T14:30:00.000Z",
  "data": {
    "originalBooking": {
      "id": "rest_booking_123456",
      "amount": 150,
      "status": "confirmed",
      "createdAt": "2025-01-01T10:00:00Z"
    },
    "cancellationDetails": {
      "reason": "Customer request",
      "processedBy": "system",
      "refundMethod": "original_payment"
    }
  }
}
```

**SDK Code**

```python Restaurant Cancellation Response
import requests

url = "https://api.etera.dev/account/bookings/booking_123456/cancel"

payload = { "dataType": "RESTAURANT" }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript Restaurant Cancellation Response
const url = 'https://api.etera.dev/account/bookings/booking_123456/cancel';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"dataType":"RESTAURANT"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Restaurant Cancellation Response
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.etera.dev/account/bookings/booking_123456/cancel"

	payload := strings.NewReader("{\n  \"dataType\": \"RESTAURANT\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Restaurant Cancellation Response
require 'uri'
require 'net/http'

url = URI("https://api.etera.dev/account/bookings/booking_123456/cancel")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"dataType\": \"RESTAURANT\"\n}"

response = http.request(request)
puts response.read_body
```

```java Restaurant Cancellation Response
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.etera.dev/account/bookings/booking_123456/cancel")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"dataType\": \"RESTAURANT\"\n}")
  .asString();
```

```php Restaurant Cancellation Response
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.etera.dev/account/bookings/booking_123456/cancel', [
  'body' => '{
  "dataType": "RESTAURANT"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Restaurant Cancellation Response
using RestSharp;

var client = new RestClient("https://api.etera.dev/account/bookings/booking_123456/cancel");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"dataType\": \"RESTAURANT\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Restaurant Cancellation Response
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["dataType": "RESTAURANT"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.etera.dev/account/bookings/booking_123456/cancel")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Experience Cancellation Response

**Request**

```json
{
  "dataType": "RESTAURANT"
}
```

**Response**

```json
{
  "success": true,
  "message": "Experience booking cancelled successfully",
  "bookingId": "exp_booking_789012",
  "dataType": "EXPERIENCE",
  "cancellationId": "cancel_345678",
  "refundAmount": 200,
  "refundStatus": "processed",
  "cancelledAt": "2025-01-15T14:30:00.000Z",
  "data": {
    "experienceName": "Desert Safari",
    "participants": 2,
    "originalAmount": 200
  }
}
```

**SDK Code**

```python Experience Cancellation Response
import requests

url = "https://api.etera.dev/account/bookings/booking_123456/cancel"

payload = { "dataType": "RESTAURANT" }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript Experience Cancellation Response
const url = 'https://api.etera.dev/account/bookings/booking_123456/cancel';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"dataType":"RESTAURANT"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Experience Cancellation Response
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.etera.dev/account/bookings/booking_123456/cancel"

	payload := strings.NewReader("{\n  \"dataType\": \"RESTAURANT\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Experience Cancellation Response
require 'uri'
require 'net/http'

url = URI("https://api.etera.dev/account/bookings/booking_123456/cancel")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"dataType\": \"RESTAURANT\"\n}"

response = http.request(request)
puts response.read_body
```

```java Experience Cancellation Response
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.etera.dev/account/bookings/booking_123456/cancel")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"dataType\": \"RESTAURANT\"\n}")
  .asString();
```

```php Experience Cancellation Response
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.etera.dev/account/bookings/booking_123456/cancel', [
  'body' => '{
  "dataType": "RESTAURANT"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Experience Cancellation Response
using RestSharp;

var client = new RestClient("https://api.etera.dev/account/bookings/booking_123456/cancel");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"dataType\": \"RESTAURANT\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Experience Cancellation Response
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["dataType": "RESTAURANT"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.etera.dev/account/bookings/booking_123456/cancel")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Hotel Cancellation Response

**Request**

```json
{
  "dataType": "RESTAURANT"
}
```

**Response**

```json
{
  "success": true,
  "message": "Hotel booking cancelled successfully",
  "bookingId": "hotel_booking_456789",
  "dataType": "HOTEL",
  "cancellationId": "cancel_901234",
  "refundAmount": 500,
  "refundStatus": "pending",
  "cancelledAt": "2025-01-15T14:30:00.000Z",
  "data": {
    "hotelName": "Burj Al Arab",
    "checkIn": "2025-01-25",
    "checkOut": "2025-01-27",
    "rooms": 1,
    "guests": 2
  }
}
```

**SDK Code**

```python Hotel Cancellation Response
import requests

url = "https://api.etera.dev/account/bookings/booking_123456/cancel"

payload = { "dataType": "RESTAURANT" }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript Hotel Cancellation Response
const url = 'https://api.etera.dev/account/bookings/booking_123456/cancel';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"dataType":"RESTAURANT"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Hotel Cancellation Response
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.etera.dev/account/bookings/booking_123456/cancel"

	payload := strings.NewReader("{\n  \"dataType\": \"RESTAURANT\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Hotel Cancellation Response
require 'uri'
require 'net/http'

url = URI("https://api.etera.dev/account/bookings/booking_123456/cancel")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"dataType\": \"RESTAURANT\"\n}"

response = http.request(request)
puts response.read_body
```

```java Hotel Cancellation Response
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.etera.dev/account/bookings/booking_123456/cancel")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"dataType\": \"RESTAURANT\"\n}")
  .asString();
```

```php Hotel Cancellation Response
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.etera.dev/account/bookings/booking_123456/cancel', [
  'body' => '{
  "dataType": "RESTAURANT"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Hotel Cancellation Response
using RestSharp;

var client = new RestClient("https://api.etera.dev/account/bookings/booking_123456/cancel");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"dataType\": \"RESTAURANT\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Hotel Cancellation Response
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["dataType": "RESTAURANT"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.etera.dev/account/bookings/booking_123456/cancel")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```