Add services to an existing booking

  • Bookings
  • Booking upsell
  • 4 routes
How do I 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.

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.

Process workflow

Legend:
Mandatory
Optional
1

Inspect the booking cart

Mandatory

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

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

{
  "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.
GET/v1/customers/{customer_id}/bookings/{booking_id}/cart
See more
2

Add a service to the cart

Mandatory

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

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/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.
POST/v1/customers/{customer_id}/bookings/{booking_id}/cart/services
See more
3

Validate services without payment when possible

Mandatory

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

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/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.
POST/v0/customers/{customer_id}/bookings/{booking_id}/services_no_payment_validation
See more
4

List subscribed services

Mandatory

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

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

[
  {
    "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.
GET/v3/customers/{customer_id}/bookings/{booking_id}/services
See more