---
uuid: 407a0e57-cb83-4bcc-8779-f530d33d705f
date_created: 2026-02-26T16:41:35.779Z
date_updated: 2026-04-03T17:59:10.630Z
seo_url: booking-upsell
category: Booking upsell
tags: 
  - Bookings
routes: 
  - GET /v1/customers/{customer_id}/bookings/{booking_id}/cart
  - POST /v1/customers/{customer_id}/bookings/{booking_id}/cart/services
  - POST /v0/customers/{customer_id}/bookings/{booking_id}/services_no_payment_validation
  - GET /v3/customers/{customer_id}/bookings/{booking_id}/services
---

# Add services to an existing booking

This scenario explains how to add services to an existing booking by reading the current cart, adding a service, validating the change when no payment is required, and then listing the subscribed services. It fits post-booking service sales and service-management journeys.

The flow starts from a known `customer_id` and `booking_id`, then moves through cart enrichment and service confirmation before reading the services attached to the booking.

## Flow

```mermaid
flowchart LR
    step0["Inspect the booking cart"]
    step1["Add a service to the cart"]
    step2["Validate services without payment when possible"]
    step3["List subscribed services"]
    step0 --> step1
    step1 --> step2
    step2 --> step3
```

## Overview

This scenario is designed for applications that need to upsell additional services on top of an existing booking.

## Prerequisites

* A known `customer_id` and `booking_id`.
* A valid bearer token, `accept-language` and `x-api-key`.
* Some upsell and validation steps rely on request bodies whose full schemas are not exposed in the available route excerpts.
* The cart service addition route explicitly mentions a limitation for multi-stay bookings.

## Expected result

The application can inspect the current cart, add a service, validate the change when no payment is required and read back the services subscribed on the booking.

## 1 - Inspect the booking cart

Use this route to inspect the current booking cart before adding a new upsell service.

#### Prerequisites

* A valid `customer_id` and `booking_id`.
* Send `accept-language`, `authorization` and `x-api-key`.
* Call this step first to understand the current cart price and service compatibility constraints.

#### Calling CURL

```bash
curl -X 'GET' \
  'https://api.clubmed.com/v1/customers/123456789/bookings/0123456789/cart' \
  -H 'accept: application/json' \
  -H 'accept-language: en-US' \
  -H 'authorization: Bearer YOUR_TOKEN' \
  -H 'x-api-key: YOUR_API_KEY'
```

#### Example answer

```json
{
  "price": {
    "total": 250,
    "currency": "EUR",
    "detail": [
      {
        "amount": 500,
        "type": "CHILDCARE"
      }
    ]
  },
  "services": [
    {
      "id": "APCA2Y",
      "type": "CHILDCARE",
      "stay_index": 1,
      "sold_only_with": [
        "ATIG3A"
      ],
      "not_compatible_with": [
        "ATIG3A"
      ]
    }
  ]
}
```

> **info:** Review `sold_only_with` and `not_compatible_with` before adding a service to avoid upsell conflicts.

***

**Response codes**

* **OK Response (200):** returns the current cart price and the services already staged on the booking.
* **Error (400):** one input value is invalid.
* **Error (401):** authentication is missing, invalid or expired.
* **Error (403):** access is forbidden because of a customer, issuer or locale mismatch.
* **Error (404):** non documented in Swagger.

**Related route**: [GET https://api.clubmed.com//v1/customers/{customer\_id}/bookings/{booking\_id}/cart](https://api.clubmed.com/doc?search=GET%20%2Fv1%2Fcustomers%2F%7Bcustomer_id%7D%2Fbookings%2F%7Bbooking_id%7D%2Fcart)

## 2 - Add a service to the cart

This route adds a service to a cart. Swagger explicitly states that removing a service from the cart uses `DELETE /v0/customers/{customer_id}/bookings/{booking_id}/cart/{serviceId}`.

#### Prerequisites

* Reuse the `customer_id` and `booking_id` of the targeted booking cart.
* Send `accept-language`, `authorization`, and `x-api-key`.
* Prepare a request body that identifies the service, the schedule, and the attendees to attach to the cart.

#### Calling CURL

```bash
curl -X 'POST' \
  'https://api.clubmed.com/v1/customers/123456789/bookings/0123456789/cart/services' \
  -H 'accept: application/json' \
  -H 'accept-language: en-US' \
  -H 'authorization: Bearer YOUR_TOKEN' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  --data-raw @booking-cart-service.json
```

#### Example answer

```http
HTTP/1.1 204 No Content
```

> **info:** Use the cart read step after this call if the interface must immediately display the refreshed cart content and pricing.

***

**Response codes**

* **OK Response (200):** not documented in Swagger. The successful contract is `204 No Content`, so no response body is returned.
* **Error (400):** the payload is invalid, incomplete or not valid JSON.
* **Error (401):** authentication is missing, invalid or expired.
* **Error (403):** access is forbidden because of a customer or issuer mismatch.
* **Error (404):** not documented in Swagger.
* **Error (501):** upsell on a multi-stay booking is not available on this route.

**Related route**: [POST https://api.clubmed.com//v1/customers/{customer\_id}/bookings/{booking\_id}/cart/services](https://api.clubmed.com/doc?search=POST%20%2Fv1%2Fcustomers%2F%7Bcustomer_id%7D%2Fbookings%2F%7Bbooking_id%7D%2Fcart%2Fservices)

## 3 - Validate services without payment when possible

This route validates additional services of a booking without payment if possible. Use it only when the selected services can be confirmed without going through a payment phase.

#### Prerequisites

* Reuse the `customer_id` and `booking_id` of the updated booking.
* Send `accept-language`, `authorization`, and `x-api-key`.
* Make sure the added services do not require payment before calling this validation step.

#### Calling CURL

```bash
curl -X 'POST' \
  'https://api.clubmed.com/v0/customers/123456789/bookings/0123456789/services_no_payment_validation' \
  -H 'accept: application/json' \
  -H 'accept-language: en-US' \
  -H 'authorization: Bearer YOUR_TOKEN' \
  -H 'x-api-key: YOUR_API_KEY'
```

#### Example answer

```http
HTTP/1.1 204 No Content
```

> **info:** When payment is still required, this route is not the right validation endpoint and the journey must continue through the payment flow.

***

**Response codes**

* **OK Response (200):** not documented in Swagger. The successful contract is `204 No Content`, so no response body is returned.
* **Error (400):** the request is invalid or the booking cannot be validated in its current state.
* **Error (401):** authentication is missing, invalid or expired.
* **Error (403):** access is forbidden because of a customer, issuer or locale mismatch.
* **Error (404):** the targeted booking was not found.

**Related route**: [POST https://api.clubmed.com//v0/customers/{customer\_id}/bookings/{booking\_id}/services\_no\_payment\_validation](https://api.clubmed.com/doc?search=POST%20%2Fv0%2Fcustomers%2F%7Bcustomer_id%7D%2Fbookings%2F%7Bbooking_id%7D%2Fservices_no_payment_validation)

## 4 - List subscribed services

Use `GET /v3/customers/{customer_id}/bookings/{booking_id}/services` to read back the subscribed services after the upsell cart has been confirmed.

#### Prerequisites

* Reuse the `customer_id` and `booking_id` of the booking.
* Send `accept-language`, `authorization`, and `x-api-key`.
* Optionally add `status` in query if the UI only needs validated, pending, or cancelled services.

#### Calling CURL

```bash
curl -X 'GET' \
  'https://api.clubmed.com/v3/customers/123456789/bookings/0123456789/services?status=VALIDATED' \
  -H 'accept: application/json' \
  -H 'accept-language: en-US' \
  -H 'authorization: Bearer YOUR_TOKEN' \
  -H 'x-api-key: YOUR_API_KEY'
```

#### Example answer

```json
[
  {
    "id": "BALVDP",
    "type": "TRANSFER",
    "currency": "EUR",
    "schedules": [
      {
        "start_date": "20260211",
        "end_date": "20260211",
        "attendees": [
          {
            "id": "A",
            "status": "VALIDATED",
            "price": 16,
            "discounts": []
          }
        ]
      }
    ],
    "transfer_information": [
      {
        "journey_type": "OUTBOUND",
        "meeting_point": "Airport"
      }
    ]
  }
]
```

> **info:** the `status` filter is useful when the booking contains many service events and the UI only needs the active subset.

***

**Response codes**

* **OK Response (200):** returns the services currently subscribed on the booking.
* **Error (400):** one input value is invalid.
* **Error (401):** authentication is missing, invalid, or expired.
* **Error (403):** access is forbidden because of a customer, issuer, or locale mismatch.
* **Error (404):** the booking was not found.

**Related route**: [GET https://api.clubmed.com//v3/customers/{customer\_id}/bookings/{booking\_id}/services](https://api.clubmed.com/doc?search=GET%20%2Fv3%2Fcustomers%2F%7Bcustomer_id%7D%2Fbookings%2F%7Bbooking_id%7D%2Fservices)
