Bookings: Booking journey

  • Booking
  • Booking
  • 8 routes
How do I turn a booking intent into a confirmed option?

This guide explains how to transform a booking intent into a confirmed option with the Club Med API.

It covers proposal search, optional services and insurance handling, attendee qualification, and booking creation.

Overview

This scenario documents a booking-preparation flow that starts from proposal search and ends with booking creation.

Prerequisites

  • A valid x-api-key and accept-language.
  • The booking criteria required to search a proposal.
  • A proposal_id returned by the search step before adding services, insurance, or attendee data.

Expected result

The application can create or retrieve a proposal, enrich it with optional services or insurance, qualify attendees, and create the booking option.

Process workflow

Legend:
Mandatory
Optional
1

Search matching proposals

Mandatory

Use POST/v3/proposals/search to create the proposal that will drive the booking journey. This first step calculates price, stock, and optionability from the submitted booking criteria and returns the proposal_id required by all later steps.

Prerequisites

  • Send accept-language and x-api-key.
  • Add authorization when the seller or partner context requires it.
  • Prepare a booking payload with product, dates, number of attendees, and package context.

Calling CURL

curl -X 'POST' \
  'https://api.clubmed.com/v3/proposals/search' \
  -H 'accept: application/json' \
  -H 'accept-language: en-US' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{ ... }'

Example answer

{
  "id": "123456",
  "product_id": "MPAC",
  "price": {
    "total": 9815.4,
    "currency": "EUR"
  },
  "remaining_stock": 2,
  "option_available": true
}

info: The returned proposal_id becomes the working file for services, attendees, insurance, and booking creation.


Response codes

  • 200 OK: returns the proposal matching the submitted criteria.
  • 400 Bad Request: the payload is invalid, incomplete, or inconsistent.
  • 401 Unauthorized: authentication is missing, invalid, or expired.
  • 403 Forbidden: the current context cannot create the proposal.
  • 404 Not Found: the product cannot be found.
  • 409 Conflict: the proposal criteria are no longer valid.
POST/v3/proposals/search
See more
2

List available additional services

Optional

Use GET/v0/additional_services with proposal_id to list the additional services available for the current proposal. This step is typically used to surface childcare, transfer, rental, or activity upsells before the proposal is qualified.

Prerequisites

  • Reuse a valid proposal_id.
  • Send accept-language and x-api-key.
  • Optionally add types when you want to focus on a specific family of services.

Calling CURL

curl -X 'GET' \
  'https://api.clubmed.com/v0/additional_services?proposal_id=123456' \
  -H 'accept: application/json' \
  -H 'accept-language: en-US' \
  -H 'x-api-key: YOUR_API_KEY'

Example answer

[
  {
    "id": "VMOSK1",
    "type": "CHILDCARE",
    "currency": "EUR",
    "schedules": [
      {
        "start_date": "20100430",
        "end_date": "20100430",
        "remaining_stock": 2
      }
    ]
  }
]

info: Only attach services that come from this service-search response. It is the reference list for compatible upsells.


Response codes

  • 200 OK: returns the services available for the proposal.
  • 206 Partial Content: the result is partial and more pages may exist.
  • 400 Bad Request: the proposal or filters are invalid.
  • 401 Unauthorized: authentication is missing, invalid, or expired.
  • 403 Forbidden: the current market or authentication does not allow this lookup.
  • 404 Not Found: the proposal cannot be found.
  • 409 Conflict: the proposal criteria are no longer valid.
  • 416 Requested Range Not Satisfiable: the requested range is invalid.
GET/v0/additional_services
See more
3

Add selected additional services

Optional

Use PUT/v0/proposals/{proposal_id}/services to apply the selected additional services to the proposal. This route works in cancel-and-replace mode, so each call must send the full service selection you want to keep on the proposal.

Prerequisites

  • Provide proposal_id.
  • Send accept-language, authorization when required, and x-api-key.
  • Build the payload from the identifiers returned by the additional-services search route.

Calling CURL

curl -X 'PUT' \
  'https://api.clubmed.com/v0/proposals/123456/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' \
  -d '{ ... }'

Example answer

HTTP/1.1 204 No Content

info: Because the route is cancel-and-replace, forgetting a previously selected service will remove it from the proposal.


Response codes

  • 204 No Content: the proposal services were updated successfully.
  • 400 Bad Request: services are incompatible, missing, or the payload is invalid.
  • 401 Unauthorized: authentication is missing, invalid, or expired.
  • 404 Not Found: the proposal cannot be found.
  • 409 Conflict: the proposal is no longer economically valid.
PUT/v0/proposals/{proposal_id}/services
See more
4

Qualify proposal attendees

Mandatory

Use PUT/v3/proposals/{proposal_id}/attendees to attach or update attendees on the proposal before turning it into a booking. This is where identity, household composition, and customer linkage are validated.

Prerequisites

  • Provide proposal_id.
  • Send accept-language, authorization when required, and x-api-key.
  • Prepare an attendee payload that respects the rules on birthdates, documents, and household consistency.

Calling CURL

curl -X 'PUT' \
  'https://api.clubmed.com/v3/proposals/123456/attendees' \
  -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' \
  -d '{ ... }'

Example answer

[
  {
    "attendees": [
      {
        "id": "A",
        "customer_id": "123456789",
        "customer_status": "NEW_CUSTOMER",
        "loyalty_status": "GOLD"
      }
    ]
  }
]

info: Most blocking data-quality issues appear here, so the UI should surface the validation feedback clearly.


Response codes

  • 200 OK: returns the updated attendee structure.
  • 400 Bad Request: attendee data is invalid, incomplete, duplicated, or inconsistent.
  • 401 Unauthorized: authentication is missing, invalid, or expired.
  • 403 Forbidden: at least one customer is not allowed to continue.
  • 409 Conflict: the proposal is no longer economically valid.
PUT/v3/proposals/{proposal_id}/attendees
See more
5

List available insurance options

Optional

Use GET/v0/additional_services with types=INSURANCE to list the insurance products available for the proposal. This step isolates the insurance subset so the user can review guarantees before adding or replacing them on the proposal.

Prerequisites

  • Reuse a valid proposal_id.
  • Send accept-language and x-api-key.
  • Add types=INSURANCE to focus on insurance services only.

Calling CURL

curl -X 'GET' \
  'https://api.clubmed.com/v0/additional_services?proposal_id=123456&types=INSURANCE' \
  -H 'accept: application/json' \
  -H 'accept-language: en-US' \
  -H 'x-api-key: YOUR_API_KEY'

Example answer

[
  {
    "id": "TRAVEL_INSURANCE",
    "type": "INSURANCE",
    "currency": "EUR",
    "schedules": [
      {
        "start_date": "20100430",
        "end_date": "20100430",
        "remaining_stock": 99
      }
    ]
  }
]

info: Filtering the service search on INSURANCE keeps the UI focused on insurance choices instead of the full additional-service catalog.


Response codes

  • 200 OK: returns the insurance services available for the proposal.
  • 206 Partial Content: the result is partial and more pages may exist.
  • 400 Bad Request: the proposal or filters are invalid.
  • 401 Unauthorized: authentication is missing, invalid, or expired.
  • 403 Forbidden: the current market or authentication does not allow this lookup.
  • 404 Not Found: the proposal cannot be found.
  • 409 Conflict: the proposal criteria are no longer valid.
  • 416 Requested Range Not Satisfiable: the requested range is invalid.
GET/v0/additional_services
See more
6

Add the selected insurance

Optional

Use PUT/v0/proposals/{proposal_id}/services to apply the selected insurance to the proposal. Because the route behaves as cancel-and-replace, the insurance payload must be merged with the rest of the services you want to keep.

Prerequisites

  • Provide proposal_id.
  • Send accept-language, authorization when required, and x-api-key.
  • Build the insurance payload from identifiers returned by the insurance-service search step.

Calling CURL

curl -X 'PUT' \
  'https://api.clubmed.com/v0/proposals/123456/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' \
  -d '{ ... }'

Example answer

HTTP/1.1 204 No Content

info: Never send only the new insurance if other services must remain on the proposal. The route replaces the whole service list.


Response codes

  • 204 No Content: the proposal services were updated successfully.
  • 400 Bad Request: services are incompatible, missing, or the payload is invalid.
  • 401 Unauthorized: authentication is missing, invalid, or expired.
  • 404 Not Found: the proposal cannot be found.
  • 409 Conflict: the proposal is no longer economically valid.
PUT/v0/proposals/{proposal_id}/services
See more
7

Remove an insurance from the proposal

Optional

Use PUT/v0/proposals/{proposal_id}/services to remove an insurance from the proposal by sending an updated service list without that insurance. Because the route replaces the full list, removal is done by omission in the new payload.

Prerequisites

  • Provide proposal_id.
  • Send accept-language, authorization when required, and x-api-key.
  • Start from the current proposal service state so you only remove the targeted insurance.

Calling CURL

curl -X 'PUT' \
  'https://api.clubmed.com/v0/proposals/123456/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' \
  -d '{ ... }'

Example answer

HTTP/1.1 204 No Content

info: To remove only one insurance safely, rebuild the payload from the latest service state instead of composing it from memory.


Response codes

  • 204 No Content: the service list was updated successfully.
  • 400 Bad Request: services are incompatible, missing, or the payload is invalid.
  • 401 Unauthorized: authentication is missing, invalid, or expired.
  • 404 Not Found: the proposal cannot be found.
  • 409 Conflict: the proposal is no longer economically valid.
PUT/v0/proposals/{proposal_id}/services
See more
8

Create the booking option

Mandatory

Use POST/v3/bookings to create the booking option from the qualified proposal. This is the step that turns the proposal into a booking file and consumes Club Med stock.

Prerequisites

  • Send accept-language, authorization when required, and x-api-key.
  • Make sure attendee data has already been qualified on the proposal.
  • Keep the same locale that was used for proposal creation and qualification.

Calling CURL

curl -X 'POST' \
  'https://api.clubmed.com/v3/bookings' \
  -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' \
  -d '{ ... }'

Example answer

{
  "booking_id": "654321",
  "households": [
    {
      "attendees": [
        {
          "customer_id": 987654,
          "type": "MAIN"
        }
      ]
    }
  ],
  "option_durability": {
    "is_reliable": true,
    "expiration_date_time": "20160415T10:23:00.234Z"
  }
}

info: Booking creation is the committing step of the journey. If it fails, the error usually points to stale proposal data, missing services, or attendee inconsistencies.


Response codes

  • 200 OK: the booking was created and confirmation data is returned.
  • 201 Created: the booking was created successfully.
  • 400 Bad Request: the payload is invalid or one required data element is missing.
  • 401 Unauthorized: authentication is missing, invalid, or expired.
  • 403 Forbidden: the current context is not allowed to create the booking.
  • 409 Conflict: price, stock, promotion, or transport conditions are no longer valid.
  • 419: the related flight is no longer available.
POST/v3/bookings
See more