Getting Offers

Once you've found a journey, the next step is getting pricing options, what we call offers. An offer represents a specific way to travel that journey, with a price, fare type, and service level.

What is an Offer?

An offer is a pricing option for a journey. Each offer includes:

  • Price: The total cost for your passengers
  • Fare type: How flexible the ticket is (can you change or cancel?)
  • Service class: The level of comfort (standard, first class, etc.)
  • Reservations: Whether seat reservations are included or required

A single journey typically has multiple offers, giving travelers choices between price, flexibility, and comfort. For example:

  • A low-cost, non-refundable option
  • A flexible, refundable option (usually more expensive)
  • A first-class option with guaranteed seats

Getting Offers for a Journey

Use the journeyOffer query (or subscription) to get pricing for a journey. You'll need:

  • The journey ID (from your search results)
  • Passenger information (number and types of travelers)

You can include up to five passengers in a single offer request. This works with all train operators.

Renamed from getJourneyOffer

journeyOffer replaces getJourneyOffer, which is deprecated but keeps working. The journey ID argument is called journeyId on the new field, where the old one called it journey. Nothing else changed.

Use subscriptions for better UX

Getting offers can take up to 30 seconds because train operators have slow systems. Use WebSocket subscriptions to stream results as they arrive. This lets you show progress to users and display offers incrementally. See Subscriptions for details.

Example: Get offers for a journey
graphql
subscription JourneyOffer {
  journeyOffer(
    journeyId: "ad7eaf45-17fe-4e48-911d-c3f5d812e314"
    passengers: [{ type: ADULT }]
  ) {
    status
    itinerary {
      __typename
      ... on SegmentCollection {
        status
        segments {
          departureAt
          origin {
            name
            countryCode
          }
        }
        offers {
          id
          price {
            amount
            currency
          }
          parts {
            ... on AdmissionPart {
              conditions {
                description
                type
              }
              flexibility
              serviceClass
              comfortClass
            }
            ... on ReservationPart {
              conditions {
                description
                type
              }
              flexibility
              comfortClass
              accommodation {
                type
              }
            }
          }
        }
      }
      ... on Stopover {
        location {
          name
          countryCode
        }
      }
    }
  }
}
subscription JourneyOffer {
  journeyOffer(
    journeyId: "b5061160-82b1-490f-a9f2-e4e941fa99ba"
    passengers: [{ type: ADULT }]
  ) {
    status
    itinerary {
      __typename
      ... on SegmentCollection {
        status
        segments {
          departureAt
          origin {
            name
            countryCode
          }
        }
        offers {
          id
          price {
            amount
            currency
          }
          parts {
            ... on AdmissionPart {
              conditions {
                description
                type
              }
              flexibility
              serviceClass
              comfortClass
            }
            ... on ReservationPart {
              conditions {
                description
                type
              }
              flexibility
              comfortClass
              accommodation {
                type
              }
            }
          }
        }
      }
      ... on Stopover {
        location {
          name
          countryCode
        }
      }
    }
  }
}

Round Trips

Some operators sell a genuine return ticket that is cheaper than two singles. They will only quote it if they are asked for both directions at once, so a round trip has to be priced in one call rather than two.

Use combinedJourneyOffer (or its subscription) for this. It takes one journey ID per direction, from two ordinary journeys searches in opposite directions, plus the passengers who are travelling both ways:

Example: Price an outbound and an inbound journey together
graphql
subscription CombinedJourneyOffer {
  combinedJourneyOffer(
    outboundJourneyId: "4236281b-a2f1-4dc5-9271-a0470a895d3e"
    inboundJourneyId: "fbaeaee4-0e62-47ff-9550-077e06a7d910"
    passengers: [{ type: ADULT }]
  ) {
    outbound {
      status
      itinerary {
        ... on SegmentCollection {
          status
          offers {
            id
            price {
              amount
              currency
            }
            memberOf {
              id
            }
          }
        }
      }
    }
    inbound {
      status
      itinerary {
        ... on SegmentCollection {
          status
          offers {
            id
            price {
              amount
              currency
            }
            memberOf {
              id
            }
          }
        }
      }
    }
  }
}
subscription CombinedJourneyOffer {
  combinedJourneyOffer(
    outboundJourneyId: "4973097b-2b66-49e4-aa25-799882b6a054"
    inboundJourneyId: "8425de9d-3488-4ca3-85d0-0d7f2f64d9b5"
    passengers: [{ type: ADULT }]
  ) {
    outbound {
      status
      itinerary {
        ... on SegmentCollection {
          status
          offers {
            id
            price {
              amount
              currency
            }
            memberOf {
              id
            }
          }
        }
      }
    }
    inbound {
      status
      itinerary {
        ... on SegmentCollection {
          status
          offers {
            id
            price {
              amount
              currency
            }
            memberOf {
              id
            }
          }
        }
      }
    }
  }
}

You get back an outbound and an inbound journey offer. Each one is exactly what journeyOffer would have returned for that direction, so anything you already do with a one-way offer works unchanged on either side.

What the round trip buys you shows up in the prices. Where the traveller retraces their outward route, and the operator sells a return fare for it, that fare replaces the two one-way prices for those parts of the journey. Everywhere else — an outbound and inbound that take different routes, or an operator with no return fare to sell — you get the same prices as two separate journeyOffer calls. Either way the call succeeds; there is nothing to detect and no fallback to write.

A return fare is one ticket, priced on one direction

A return fare arrives as a full-price offer on one direction and a companion offer costing nothing on the other. The two are one ticket and are bookable only together, so an offer at no cost here is not a free add-on. Both directions arrive in the same response, so you can match them up: offers sharing a memberOf.id belong to the same ticket and must all be selected, or none of them. See Offer Sets.

Book the round trip as a single booking: pass the offer IDs you selected from both directions to createBooking in one offerIds list. Two bookings, one per direction, cannot express a return fare — the offers of a set have to be selected together.

Pricing two directions takes at least as long as pricing one, so prefer the subscription here even more than for a single journey. Each direction streams independently, and a payload arrives whenever either side has something new.

Understanding Offer Parts

Offers consist of parts that describe what's included. The two main types are:

Admission Parts

The right to travel: the basic ticket. This includes:

  • Flexibility: Can you change or cancel? (FULL_FLEX, SEMI_FLEX, NON_FLEX)
  • Service class: Standard, high-speed, premium, etc.
  • Comfort class: First class, second class, etc.

Reservation Parts

A reserved seat or accommodation. This includes:

  • Flexibility: Same as admission parts
  • Comfort class: The class of the reserved seat
  • Accommodation: Type of reservation (seat, couchette, sleeper, etc.)

Most offers include both admission (the right to travel) and reservation (a specific seat). Some journeys only require admission. You can sit anywhere in your class.

Passenger Requirements

When requesting offers, provide passenger information:

  • For adults: Age or birth date is optional
  • For youth/seniors: Age or birth date is required (for discount eligibility)

The API uses this information to calculate correct pricing and ensure passengers qualify for age-based discounts.

Offer Availability

Finding a journey doesn't guarantee offers are available. The API checks real-time availability with train operators, and sometimes:

  • Tickets aren't on sale yet (too far in advance)
  • Tickets are sold out (popular routes, last-minute bookings)
  • The exact journey isn't available (but similar alternatives might be)

When offers are available, they may have slight timing variations from your original journey search. The overall route stays the same, but departure times might shift slightly. The API ensures:

  • Safe connection times between trains
  • The same comfort level
  • The same overall itinerary

Choosing Which Journey to Price

When you search for journeys, you'll get multiple options for the same day. Which one should you price? Here are some strategies:

Filter by Journey Type

If you know what type of journey your users want, filter during the search:

  • SMART (default): Most comfortable, may include overnight stops
  • NON_STOP: Fastest route, but may be less comfortable
  • BLUEPRINT: Pre-defined expert itineraries

See Finding Journeys for details on filtering.

Use Journey Ratings

The API includes a rating system that scores journeys based on travel time, comfort, connection quality, and more. Ratings range from 0 to 1, where 1 is the best possible journey.

Use getJourneyRatings to compare multiple journeys and pick the highest-rated option:

Example: Compare journey ratings
graphql
query GetJourneyRatings {
  getJourneyRatings(
    journeys: [
      "5d51de44-bfde-4286-a0a7-014aa8c8d82b"
      "76897f2a-6110-4acd-9873-1e8b868eb79c"
      "c403e5fb-d82d-4e33-b315-e673a7e02b25"
    ]
  )
}
query GetJourneyRatings {
  getJourneyRatings(
    journeys: [
      "2344a06b-67a7-4383-89e9-87f6f9f0a2e6"
      "156cf6ac-3070-4542-b513-1a9f2d37c4c3"
      "2f0c1a30-182d-42a5-9463-ddc01a866b21"
    ]
  )
}

Let Users Choose

For user-facing applications, show multiple journey options and let users pick. Display:

  • Departure and arrival times
  • Number of changes
  • Total travel time
  • Journey type (if helpful)

Then price the journey the user selects.

Responsible API usage

The All Aboard API operates on fair use principles. Only request offers for journeys you're reasonably confident users will book. See API Usage and Look-to-Book for details on our fair use policy.

Next Steps

Once you have offers, the next step is creating a booking. See Booking Tickets to learn how to:

  • Create a booking from an offer
  • Add passenger details
  • Select specific offers and seat preferences
  • Complete the purchase