Booking Flex on a Departure

Note

This tutorial follows from completing the Creating Your First Booking and Confirming Services tutorials - you’ll need a booking, a customer, and a departure service in place, and an understanding of how services are confirmed. Refer to those tutorials for the full process of making and confirming a booking.

Flex is G Adventures’ flexible cancellation product. Purchased alongside a tour, it upgrades the booking’s cancellation terms, allowing travellers to cancel much closer to the trip departure and receive a refund and/or Future Travel Credit (FTC) according to the terms of the tier they purchased. Depending on the tier, Flex also bundles ancillary perks such as a travel eSIM and delayed-luggage protection, delivered through the flex plan service addons resource.

In this tutorial, you’ll walk through the full Flex lifecycle:

  1. Discovering Flex Plans on a departure

  2. Displaying tiers and cancellation terms to your customers

  3. Adding a Flex Plan Service to a booking

  4. Confirming by payment and delivering add-ons

  5. Exercising the Flex terms and viewing the enacted terms

Before You Begin

Keep the following rules in mind - they determine whether Flex can be sold at all:

  • Stop-sell window. Flex is only available while the departure is more than 60 days away (90 days for National Geographic Signature departures). Inside that window, Flex Plans still appear in departures.addons[] but will have an availability.status of NOT_BOOKABLE.

  • Late-attach window. Flex must be purchased at the time of booking or within 48 hours of the original departure service confirmation. Optioned Flex services auto-expire at the end of this window if not paid.

  • CEU exclusion. Flex is not offered where CEU (DACH; Austria, Switzerland, Germany) terms apply. See Handling CEU (DACH) Customers for details.

  • Agency eligibility. Flex can be disabled per agency or agency chain; if disabled for your agency, Flex products will not be purchasable on your bookings.

  • One tier per departure service. A departure service can carry at most one Flex service, and therefore one tier. If travellers on the same service want different tiers, the departure service must be split between travellers so each tier can be purchased on its own service.

  • Full payment to confirm. A Flex service is Confirmed only when its purchase price is paid in full; it cannot be confirmed on a tour deposit alone. Additionally, the parent tour service must be Confirmed before the optioned Flex Plan Service can be confirmed.

  • Flex is 100% non-refundable once confirmed, and cannot be cancelled via the API. Cancellation of a confirmed Flex service must be handled manually by contacting our sales teams.

Discovering Flex Plans on a Departure

Flex Plans appear as add-on products on the departure, one per available flex tier. Fetch the departure and filter the addons[] list for entries with a type of flex_plans:

GET /departures/1234567/ HTTP/1.1
Host: rest.gadventures.com
Accept: application/json

And in the response, snipped for focus:

{
  "id": "1234567",
  "addons": [
    {
      "product": {
        "id": "111",
        "href": "https://rest.gadventures.com/flex_plans/111/",
        "name": "Flexier",
        "type": "flex_plans",
        "sub_type": "Flex"
      },
      "start_date": "2026-08-01",
      "finish_date": "2026-10-01",
      "halt_booking_date": "2026-10-01"
    }
  ]
}

Next, fetch each flex plan for its pricing and availability:

GET /flex_plans/111/ HTTP/1.1
Host: rest.gadventures.com
Accept: application/json

Check availability.status - only plans reporting AVAILABLE can be purchased. The resolved monetary amounts per room, price band, and currency are found under rooms[], in the same shape as departure pricing.

Displaying Flex to Customers

Labeling

Always label Flex products with the API-provided name (inherited from the flex tier) rather than internal codes such as product_line values. Tier names are marketing-controlled and may change between tier versions; treat the API value as the source of truth at display time.

Tier Comparison

When a departure offers multiple Flex Plans, display them side by side so customers can compare:

  • the price (from rooms[] for the relevant price band and currency);

  • the cancellation windows (refund_percent / travel_credit_percent per window from the plan’s flex cancellation terms);

  • the latest exercise point (the final window with a non-zero refund or FTC percentage);

  • any bundled perks included with the tier.

Displaying Cancellation Terms: Percent vs Amount

There are two representations of cancellation terms, and it matters which one you show:

  • Base terms (no Flex) - the departure’s standard cancellation terms, referenced from the cancellation_terms field on the departure resource. Useful for showing customers what they get without Flex, side by side with each tier.

  • Before purchase - use the percentage-based flex cancellation terms linked from the plan. Each window carries concrete dates for the departure (effective_from_date / effective_until_date) with refund_percent and travel_credit_percent.

  • After booking - use the amount-based service cancellation terms, keyed by the departure service id. Each window carries refund_amount and travel_credit_amount resolved against the actual purchase price. Note that these are only available for bookings with a Flex Plan Service - for bookings without one, the request returns a 404 response. The terms.type field identifies whether the generic terms (cancellation_terms) or the flex terms (flex_cancellation_terms) currently apply. Show these amounts (not recomputed percentages) when a customer asks “what do I get if I cancel today?”.

Handling CEU (DACH) Customers

Flex is not offered where CEU (DACH) terms apply (customers resident in, or agencies based in: Austria, Switzerland, or Germany).

GET /departures/1234567/ HTTP/1.1
Host: rest.gadventures.com
Accept: application/json

When Flex is unavailable for the resolved country, do not display Flex plans or pricing. Show a simple message such as:

Flex is not available for this booking.

Avoid implying the customer can change eligibility by, for example, changing agencies - CEU eligibility is determined by the resident/business address on the booking.

Purchasing: Creating the Flex Plan Service

With a booking and a departure service in place, create a flex plan service alongside it:

POST /flex_plan_services/ HTTP/1.1
Host: rest.gadventures.com
Accept: application/json
Content-Type:application/json

{
    "booking": { "id": "999" },
    "departure_service": { "id": "5678" },
    "product": { "id": "111" }
}

The response is 201 Created with the service in the Option status, and the departure service referenced under associated_services[]. Note the option_expiry_date - if the service is not confirmed by full payment before then (the end of the 48-hour late-attach window or the stop-sell boundary, whichever comes first), it auto-expires.

While in Option, no add-ons are attached. The new service also appears alongside the departure service in the booking’s services list (/bookings/999/services/), with a type of flex_plan_services and sub_type of Flex.

Warning

Before a Flex Plan Service covers the departure service, requests to service cancellation terms return a 404 response - the resource only exists once Flex has been purchased for the service.

From the moment the Flex service covers the departure service, the departure service’s service cancellation terms resolve to the plan’s flex terms. This resolution is asynchronous - allow a few seconds after creating the Flex Plan Service, and retry the request if you still receive a 404 response.

GET /service_cancellation_terms/5678/ HTTP/1.1
Host: rest.gadventures.com
Accept: application/json

The response will report a terms.type of flex_cancellation_terms.

If the option is no longer wanted, it can be released explicitly:

PATCH /flex_plan_services/12345/ HTTP/1.1
Host: rest.gadventures.com
Accept: application/json
Content-Type:application/json

{
    "status": "Expired"
}

Displaying Deposits and Payment Amounts

Flex must be paid in full to confirm, so it changes how you present payment amounts at checkout (see Deposits for the general deposit workflow):

  • departure_services.deposit contains only the deposit amount for the departure service itself.

  • The flex_plan_services resource has no deposit field - the full purchase_price is due to confirm.

At payment time, present your customer with the following options:

  1. Full payment for all services - the sum of every service’s purchase_price, or the booking’s amount_owing field (these should be identical).

  2. Tour deposit + full payment for Flex - the sum of departure_services.deposit and flex_plan_services.purchase_price.

  3. Custom amount for the tour + full payment for Flex - the customer enters an amount that must be at least departure_services.deposit, and the interface adds flex_plan_services.purchase_price on top.

The above assumes the customer wants the Flex service Confirmed. If they only want to hold it as an Option, no payment is required for the Flex service - it simply remains in Option until its option_expiry_date.

Confirming by Payment and Delivering Add-ons

Confirmation is driven by payment: pay the Flex service’s purchase_price in full through the usual booking payment flow. On confirmation:

  • status moves to Confirmed and date_confirmed is set.

  • If the tier bundles ancillary products, flex plan service addons are attached under flex_plan_addons[], one per covered customer.

Poll the service to observe the confirmed state, then fetch each addon to surface its delivery artifacts to the traveller:

GET /flex_plan_addons/12345/ HTTP/1.1
Host: rest.gadventures.com
Accept: application/json

Each addon lists its bundled products[] (a category of ESIM or LUGGAGE_PROTECTION, plus a display name) along with an order_url where the traveller activates the products, a support_url, and a terms_url. For a travel eSIM, the order_url is where the traveller claims and installs the eSIM before departure. For Blue Ribbon luggage protection, it is where they register bags and file a claim. No fulfilment-provider identifiers are exposed through the API - the addon carries only these customer-facing artifacts.

Warning

Render the addon URLs (order_url, support_url, terms_url) as HTML-safe content - escape values for your output context rather than injecting them into markup verbatim.

Exercising the Flex Terms

Exercising Flex means cancelling the covered departure service while the confirmed Flex service applies. Cancel the departure service as usual:

PATCH /departure_services/5678/ HTTP/1.1
Host: rest.gadventures.com
Accept: application/json
Content-Type:application/json

{
    "status": "Cancelled"
}

Viewing the Enacted Terms

The refund, FTC, and penalty applied are determined by the service cancellation terms of the tour service - the window containing the cancellation date determines the refund_amount and travel_credit_amount:

GET /service_cancellation_terms/5678/ HTTP/1.1
Host: rest.gadventures.com
Accept: application/json

When the cancellation is processed:

  • finish_date is set on the Flex Plan Service.

  • Bundled add-on products are cancelled alongside the service.

  • FTCs issued by Flex carry the booking and travel windows defined for the purchased tier (12 and 24 months from issuance respectively for G Adventures tiers).

The Flex service itself remains non-refundable regardless of the exercise outcome.

What You Cannot Do via the API

  • Cancel a ``Confirmed`` Flex service. Cancelled never appears in status_transitions[] and is rejected by PATCH. Cancellation of a confirmed Flex service is handled manually by G Adventures staff on a case-by-case basis by contacting our sales teams.

  • Attach more than one Flex service to a departure service. Requests violating the one-tier-per-service constraint are rejected.

  • Purchase Flex for CEU-classified bookings, for agencies where Flex has been disabled, or outside the stop-sell and late-attach windows.

Resource Reference