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:
Discovering Flex Plans on a departure
Displaying tiers and cancellation terms to your customers
Adding a Flex Plan Service to a booking
Confirming by payment and delivering add-ons
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 anavailability.statusofNOT_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
Confirmedonly when its purchase price is paid in full; it cannot be confirmed on a tour deposit alone. Additionally, the parent tour service must beConfirmedbefore 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_percentper 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_termsfield 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) withrefund_percentandtravel_credit_percent.After booking - use the amount-based service cancellation terms, keyed by the departure service id. Each window carries
refund_amountandtravel_credit_amountresolved 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 a404response. Theterms.typefield 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.depositcontains only the deposit amount for the departure service itself.The
flex_plan_servicesresource has nodepositfield - the fullpurchase_priceis due to confirm.
At payment time, present your customer with the following options:
Full payment for all services - the sum of every service’s
purchase_price, or the booking’samount_owingfield (these should be identical).Tour deposit + full payment for Flex - the sum of
departure_services.depositandflex_plan_services.purchase_price.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 addsflex_plan_services.purchase_priceon 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:
statusmoves toConfirmedanddate_confirmedis 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_dateis 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.
Cancellednever appears instatus_transitions[]and is rejected byPATCH. 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.