"""Features that are only available to select agents""" directive @private(agents: [String!]!) on OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | ENUM | ENUM_VALUE | INPUT_FIELD_DEFINITION | INPUT_OBJECT """Date string (ISO 8601 – `YYYY-MM-DD`)""" scalar Date """ Naive date and time string, seconds omitted (ISO 8601 – `YYYY-MM-DDThh:mm`) """ scalar DateTime """ A date-time string at UTC, such as 2007-12-03T10:15:30Z, compliant with the `date-time` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. """ scalar ZonedDateTime """ISO 8601 formatted string, e.g. PT2H15M, P2D, P1M""" scalar Duration """ The `JSONObject` scalar type represents JSON objects as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). """ scalar JSONObject """ A custom field's value, typed by the field's `type`: a Boolean for `BOOLEAN`, a date as a `YYYY-MM-DD` String for `DATE`, and a String for `INPUT`, `TEXTAREA` and `TEL`. """ scalar CustomFieldValue """The mode of transport""" enum Transport { NIGHT_TRAIN TRAIN BUS FERRY NIGHT_BUS } """The current status for a journey result""" enum JourneyStatus { LOADING SUCCESS ERROR } """ Status indicating whether a segment collection was successfully loaded or encountered an error """ enum SegmentCollectionStatus { """The request is loading""" LOADING """The request was successful""" SUCCESS """Status could not be determined due to an error with a prior connection""" INDETERMINATE """An unexpected error occurred""" UNKNOWN """ Too many journey searches in a short time, retry later. See `rateLimits` on `SalesAgent` """ RATE_LIMITED """Allow at least one day from todays date""" ONE_DAY """No fares available for the requested connection""" NO_FARES """No timetable available for the requested date""" NO_TIMETABLE """No availability""" UNABLE_TO_SELL """The requested date falls outside current timetable planning period""" OUTSIDE_TIMETABLE """Online prebook is not possible due to sales restrictions""" PREBOOK_NOT_POSSIBLE """ The party is larger than the train operator behind this leg sells to in one booking """ TOO_MANY_PASSENGERS } """The type of passenger""" enum PassengerType { """Ages 28-59""" ADULT """Ages 0-27""" YOUTH """Ages 60+""" SENIOR } """The resulting product type definition for a passenger""" enum PassengerBundleType { ADULT SENIOR YOUTH CHILD } """The perferred title of a passenger""" enum PassengerTitle { MR MS MX } """Current status of an order""" enum OrderStatus { """Order is confirmed""" CONFIRMED """Order is pending confirmation""" PENDING """The order has failed""" FAILED """All refundable items have been refunded""" REFUNDED """Some refundable items have been refunded""" PARTIALLY_REFUNDED """The refund attempt failed""" REFUND_FAILED """The order has been voided""" VOIDED """Unknown state""" UNKNOWN } """Type of journey""" enum JourneyType { """ Journeys built from predefined itinerary blueprints (curated or editorial routes). May include planned stopovers and specific paths. """ BLUEPRINT """ Fastest end-to-end journeys without planned overnight stopovers. Transfers may occur, but no intentional multi-day segments are included. """ NON_STOP """ Comfort-optimized journeys that may split long routes across days to limit daily travel time and improve overall experience. Default type. """ SMART } """The type of accommodation available""" enum AccommodationType { """Seat in a seated area""" SEAT """Bed in a couchette cabin""" COUCHETTE """Bed in a comfortable sleeper cabin""" BERTH """Accommodation is unknown""" UNKNOWN } """Flexibility of a fare""" enum Flexibility { """No refunds or exchanges""" NON_FLEX """Partly refundable or exchangeable""" SEMI_FLEX """Fully refundable or exchangeable""" FULL_FLEX """Flexibility is unknown""" UNKNOWN } """ Transitional union of `ReturnType` and the travel-condition kinds, present only while `Condition.type` exists on the interface. Each concrete type returns only its own values: `ReturnCondition` REFUND, EXCHANGE or UNKNOWN; `TravelCondition` ROUTE, TRAIN_BOUND or RESTRICTION; `ValidityCondition` has no meaningful type and returns UNKNOWN. The end state removes `type` from `Condition`, narrows `ReturnCondition.type` back to `ReturnType` and `TravelCondition.type` to `TravelConditionType`, and retires this enum. Do not write new code against it: select `type` through `... on ReturnCondition` or `... on TravelCondition`. """ enum ConditionType { """An exchange rule; only returned by `ReturnCondition`.""" EXCHANGE """A refund rule; only returned by `ReturnCondition`.""" REFUND """ The provider stated a refund or exchange rule without saying which — or the condition is a `ValidityCondition`, which has no type. """ UNKNOWN """ The ticket is only valid on a particular route or with particular operators; `description` says which. Example: "Only valid on booked London Northwestern Railway and Northern services." """ ROUTE """ The ticket is only valid on the specific train(s) it was booked for; the passenger may not take an earlier or later service. Typical of UK Advance fares and Deutsche Bahn Sparpreis. A part carrying this never also carries a `ValidityCondition`. A train-bound ticket cannot be broken: the passenger travels the booked trains and changes only at the booked connections, so no separate break-of-journey statement is made. """ TRAIN_BOUND """ Time-of-day and day-of-week limits on when the ticket may be used — peak-hour exclusions and the like — too detailed to repeat inline. `description` points at the full rules and `url` links to the page holding them. """ RESTRICTION } """Type of return covered by a return policy""" enum ReturnType { EXCHANGE REFUND UNKNOWN } """Normalized class of service""" enum ServiceClass { """ Best class available, premium comfort with top-tier amenities and exclusive services """ BEST """ Standard first class, high comfort with enhanced seating and additional perks """ HIGH """ Standard second class, balanced service with essential comfort and amenities """ STANDARD """ Most economical class available, minimal service focused on affordability and essential needs """ BASIC """Service class is not known""" UNKNOWN } """Valid agent payment method""" enum PaymentMethod { INVOICE WALLET STRIPE } """The unit for a given rate limit""" enum RateLimitUnit { MINUTE HOUR DAY } """Categories of amenities describing onboard services and facilities""" enum OnboardAmenityCategory { SNACKS MEAL SLEEP WIFI TOILET WHEELCHAIR BIKE AC SEAT KIDS CHARGING } """Sort direction for ordering results""" enum SortDirection { ASC DESC } """Whether a travel card field is required""" enum FieldRequirement { """The field must always be provided""" ALWAYS """The field is required under certain conditions""" CONDITIONAL """The field is optional""" OPTIONAL } """State of a refund item""" enum RefundItemState { SUCCEEDED PENDING ERROR } """State of a refund""" enum RefundState { SUCCEEDED PENDING ERROR } """The availability of a place, eg. seat or bed""" enum PlaceAvailability { AVAILABLE UNAVAILABLE UNKNOWN } """ Indicates if, and during what timeframe, an offer part is returnable/exchangeable. Use this field to signal: - If the offer part is refundable/exchangeable or not - If so, the relevant period (e.g. only before departure, or at any time) Consult the accompanying description for refund/exchange details (e.g. % refunded, fees). """ enum ReturnConditionTimeframe { """ The offer part is refundable/exchangeable at any time, as described in the condition. """ ALWAYS """ The offer part is refundable/exchangeable only up to the point of departure. See description for details. """ BEFORE_DEPARTURE """The offer part is not refundable/exchangeable.""" NEVER """ It is uncertain or varies when the offer part is refundable/exchangeable; see description for specifics. """ UNKNOWN } """How the tickets for an offer are handed to the traveler""" enum TicketDeliveryMethod { """Delivered electronically; there is nothing to collect before travel.""" E_TICKET """ Collected from a ticket machine at the departure station before travel, using the collection reference issued with the order. """ TICKET_ON_DEPARTURE } """Any unique resource with an ID""" interface Node { id: ID! } """Generic train stop""" interface Stop { name: String! } """ A station where stops may be made but journeys cannot be planned from/to """ type AnonymousLocation implements Stop { name: String! } """Known location from and to which journeys can be planned""" type Location implements Stop { uid: ID! name: String! countryCode: String! coordinates: GeoJsonPoint! """ True when this location stands for a place rather than one station — "Paris" rather than one of its termini. A journey searched from it departs whichever station the route it is sold on uses, so read the departure off the journey's segments rather than assuming it. """ isMeta: Boolean! } """ Coordinates of a given location in GeoJSON Point format. Follows the GeoJSON specification (RFC 7946) using WGS84 coordinate system. Coordinates are stored as [longitude, latitude] array (note the order). Examples: - London: [-0.1278, 51.5074] (longitude, latitude) - Rome: [12.4964, 41.9028] (longitude, latitude) - Stockholm: [18.0686, 59.3293] (longitude, latitude) - Berlin: [13.4050, 52.5200] (longitude, latitude) Note: The type field is always "Point" for this implementation. """ type GeoJsonPoint { type: String! coordinates: [Float!]! } """Operator details""" type Operator { """The unique identifier for the operator.""" code: String name: String! """ The operator's logo. Null when we hold no logo for the operator; show its name instead. Asking for `DARK_MODE` where the operator has no dark-mode logo returns the light-mode logo. """ image( """Format of image""" format: String = "svg" """Which version of the logo to return.""" variant: LogoVariant = LIGHT_MODE ): FileResource } """The brand of the service""" type ServiceBrand { name: String! code: String! """ The service brand's logo. Null when we hold no logo for the brand; show its name instead. Asking for `DARK_MODE` where the brand has no dark-mode logo returns the light-mode logo. """ image( """Format of image""" format: String = "svg" """Which version of the logo to return.""" variant: LogoVariant = LIGHT_MODE ): FileResource } """A version of an operator or service brand logo.""" enum LogoVariant { """The logo for light backgrounds.""" LIGHT_MODE """The logo for dark backgrounds.""" DARK_MODE } """ Individual train segment representing a single physical train journey between two stops. A segment is the atomic unit of travel - it represents one train/bus/ferry that travels from origin to destination, possibly with intermediate stops but no change of transport. Multiple segments can be combined to form an individual journey leg, see `SegmentCollection`. """ type Segment { origin: Stop! destination: Stop! departureAt: DateTime! arrivalAt: DateTime! duration: Int! transport: Transport! operator: Operator! serviceBrand: ServiceBrand identifier: String direction: String amenities: [OnboardAmenity!]! services: [String!]! @deprecated(reason: "Use `amenities` instead") """ Distance traveled on this segment by one passenger, in km. Null when unknown, for example when we hold no coordinates for a station; always null on orders placed before the figures shipped and on refund items. A journey's distance is the sum of its segments, and unknown if any segment is unknown. The method is described on the distance and CO2 methodology page. """ distance: Quantity """ CO2 emitted for one passenger on this segment, in kg. Multiply by the number of passengers for the party. It is CO2e, well-to-wheel (it includes producing the energy), at average occupancy. Null when unknown, for example when we hold no coordinates for a station; always null on orders placed before the figures shipped and on refund items. A journey's CO2 is the sum of its segments, and unknown if any segment is unknown. The method is described on the distance and CO2 methodology page. """ co2: Quantity } """ An amount with its unit, a symbol such as "km" or "kg" meant for display. """ type Quantity { """The amount, unrounded; round it for display.""" value: Float! """The unit symbol, to print after the value. Not a closed set.""" unit: String! } """ An onboard service or facility that may be available on a `Segment`. Available onboard amenities may vary depending on service class, comfort class and accommodation. """ type OnboardAmenity { category: OnboardAmenityCategory! subCategory: String description: String! } """ Accommodation details for a journey segment. Describes the type of seating or sleeping arrangement available on a train/bus/ferry, including comfort level and specific features. Used to help passengers choose their preferred travel experience. The description field provides human-readable details about the accommodation (e.g. "1 person sleeper cabin"), while subType contains a standardized code representation of the same information (e.g., "SINGLE"). """ type Accommodation { category: AccommodationType! @deprecated(reason: "Use `type` instead") type: AccommodationType! description: String subType: String } """Period for which a serivce is scheduled to run""" type PlanningPeriod { startDate: Date! endDate: Date! """ A bitfield string representation of the days of service encoded as a hexadecimal string. Each bit in the bitfield corresponds to a specific day, starting from the `startDate` and ending on the `endDate`. Each hexadecimal character represents 4 days (bits). Bit interpretation: - Bit 0 = startDate - Bit 1 = startDate + 1 day - Bit 2 = startDate + 2 days - etc. Examples: - "FF" = 8 days of service (11111111 in binary) - "F0" = First 4 days of service (11110000 in binary) - "0F" = Last 4 days of service (00001111 in binary) - "AA" = Every other day (10101010 in binary) To decode: Convert hex to binary, each 1 represents a day with service. """ bitfield: String! } """Items that can make up the itinerary of a Journey""" union ItineraryItem = SegmentCollection | Stopover """Location for an overnight stopover""" type Stopover { location: Location! duration: Duration } """ A collection of connected segments that form a logical journey leg. Represents a sequence of segments that: - Share the same availability status - Can be booked together - Have common offer options - Form a continuous path between major stops Used to group related segments together for pricing and booking purposes. """ type SegmentCollection { status: SegmentCollectionStatus! segments: [Segment!] fares: [Fare!] @deprecated(reason: "Use `offers` instead") offers: [Offer!] planningPeriod: PlanningPeriod """ Strings representing series of Positions encoded using the Google Maps Polyline algorithm. May require decoding. See https://developers.google.com/maps/documentation/utilities/polylinealgorithm """ polylines: [String!] } """ A priced, bookable combination of entitlements for a journey. An offer bundles everything needed to travel on a ticketable segment of an itinerary. It is made up of one or more parts: - `AdmissionPart`: the right-to-travel/tariff entitlement (admission to board) - `ReservationPart`: optional seat/berth reservations and add-ons Pricing and composition: - `price`: total price for all included parts in the requested currency - `parts`: per-part breakdown with their own price and the segments they cover Usage: - returned by journey pricing endpoints and attached to itinerary results - selected when creating a booking (see `JourneyOfferSelection` and `OfferSelectionInput`) - per-part options (e.g., `placeProperties`, `ancillaries`) are configured on ReservationPart items Notes: - Some connections can be traveled without a reservation; such offers only have an AdmissionPart - Sometimes reservations are included, in which case a `ReservationPart` with no price is returned - Long or mixed-operator journeys may include multiple `AdmissionPart` and `ReservationPart` items, each covering different segments """ type Offer implements Node { id: ID! parts: [OfferPart!]! price: Money! """ How the tickets for this offer can be delivered, and which method has been picked so far. Null when delivery information could not be established for this offer — the operator then delivers its own way and nothing can be picked. """ ticketDelivery: TicketDelivery """ The offers of one product sold across several legs. Select an offer from this set for every leg it covers, or nothing from it at all. Null on ordinary offers, which combine freely. Two shapes exist. On some journeys the set is one priced combination and holds a single offer per leg — a return fare and its £0 companion — so those exact offers are the selection. On others every offer of every leg shares one set, because the journey is only sold whole: pick whichever offer you like on each leg, but book them all. A set id names the product these offers are part of, for as long as the offers themselves last. It is not an address: offers are addressed by offer id, and a set id is never sent back. Two products priced identically are two sets, so equal prices are no reason to expect equal ids — and a refreshed journey is a new set of offers, which names its product with a new id. """ memberOf: OfferSet } """One way an offer's tickets can be delivered.""" type TicketDeliveryOption { """How the tickets are handed to the traveler.""" method: TicketDeliveryMethod! } """ The ticket delivery choice for an offer. Record a pick with the `setTicketDelivery` mutation, before creating the order. """ type TicketDelivery { """ The ways this offer's tickets can be issued. Never empty — an offer with no established delivery information carries no `ticketDelivery` at all — but it can hold a single option, meaning delivery is known and there is nothing to pick. """ availableOptions: [TicketDeliveryOption!]! """ The recorded pick, or null when nothing has been picked yet — in which case the operator applies its own default when the order is placed. Always one of `availableOptions`. """ selectedOption: TicketDeliveryOption } """ A set of offers sold, and bookable, only as one product: every leg it covers is booked, each with an offer from the set. It carries no offers of its own; it is an identity and nothing more. Two offers belong to the same product when their `memberOf.id` matches. """ type OfferSet { id: ID! } """ One part that makes up an offer. Each part references the exact `segments` it applies to. The optional `price` reflects the cost of this part; the overall total is reported on `Offer.price`. """ interface OfferPart { segments: [Segment!]! price: Money } """ The admission (tariff) part of an offer. Represents the right to travel for the covered segments (the fare/tariff). Contains the `conditions` the operator stated for the ticket and the `flexibility` level, as well as the normalized `serviceClass` and (operator-specific) `comfortClass`. """ type AdmissionPart implements OfferPart { """ Everything the provider stated about this part: refund and exchange rules (`ReturnCondition`), the dates the ticket may be used on (`ValidityCondition`) and other rules of use (`TravelCondition`), in that order. Render every entry's `description`; see `Condition` for how to treat the kinds. """ conditions: [Condition!]! flexibility: Flexibility! serviceClass: ServiceClass! comfortClass: String """ The corporate codes the operator honored on this part, as it reported them. Empty when none applied, so a code sent at search that is missing here did not discount this part. On a journey sold as one offer per operator the code can apply to one operator's parts and not another's. """ appliedCorporateCodes: [CorporateCode!]! segments: [Segment!]! price: Money } """ The reservation part of an offer. Represents the seat/berth reservation(s) and related options for the covered segments. May expose configurable `placeProperties` (e.g., window/aisle, quiet-zone) and optional `ancillaries` (e.g., luggage, meals). `price` reflects the reservation cost for the part; the offer total is on `Offer.price`. """ type ReservationPart implements OfferPart { id: ID! """ Everything the provider stated about this part: refund and exchange rules (`ReturnCondition`), the dates the ticket may be used on (`ValidityCondition`) and other rules of use (`TravelCondition`), in that order. Render every entry's `description`; see `Condition` for how to treat the kinds. """ conditions: [Condition!]! flexibility: Flexibility! accommodation: Accommodation! placeProperties: [PlaceProperty!] placeAssignments: [PlaceAssignment!] ancillaries: [Ancillary!] serviceClass: ServiceClass! comfortClass: String """ The corporate codes the operator honored on this part, as it reported them. Empty when none applied, so a code sent at search that is missing here did not discount this part. On a journey sold as one offer per operator the code can apply to one operator's parts and not another's. """ appliedCorporateCodes: [CorporateCode!]! segments: [Segment!]! price: Money """Whether this reservation part is included in the offer price""" included: Boolean! """Whether this reservation part can be included or excluded by the user""" optional: Boolean! } """ One part that makes up a booked offer. Each part references the exact `segments` it applies to. The optional `price` reflects the original cost of this part. """ interface BookedOfferPart { segments: [Segment!]! price: Money } """A the part of a booked offer that is the admission""" type BookedAdmissionPart implements BookedOfferPart { segments: [Segment!]! price: Money } """A part of a booked offer that is the reservation""" type BookedReservationPart implements BookedOfferPart { segments: [Segment!]! price: Money } """A place assignment for a passenger""" interface PlaceAssignment { passenger: Passenger! } """A seat assignment for a passenger""" type SeatAssignment implements PlaceAssignment { seatIdentifier: String coachIdentifier: String passenger: Passenger! } """A bed assignment for a passenger""" type BedAssignment implements PlaceAssignment { passenger: Passenger! bedIdentifier: String coachIdentifier: String accommodation: Accommodation } """ An ancillary service that can be selected for a reservation. Additional services or add-ons that passengers can purchase beyond the basic fare. These enhance the travel experience and may include meals, insurance, or special assistance. Common types and examples: - "BREAKFAST": On-board breakfast, pre-ordered meals - "MEAL": On-board dining, pre-ordered meals - "INSURANCE": Travel insurance, cancellation protection - "LUGGAGE": Extra baggage allowance, bike transport - "UPGRADE": Seat upgrades, priority boarding - "ENTERTAINMENT": WiFi access, entertainment packages The price field indicates the additional cost, while selections track which passengers have chosen this service. """ type Ancillary { id: ID! name: String! type: String! description: String image: FileResource price: Money selections: [AncillarySelection!]! } """A selection of an ancillary service""" type AncillarySelection { id: ID! passengerId: ID! } """ Option relating to the seating arrangement and other aspects of the journey. Allows passengers to specify preferences for their travel experience, such as seat location, cabin type, or special requirements. These properties can be required (mandatory selection) or optional (preference-based). Common property types: - "GENDER": Segregated cabin by gender - "PLACE_OR_COMPARTMENT_LOCATION": Location of the place or compartment - "SPECIAL_COMPARTMENT_TYPE": Special compartment type The availableOptions list shows all possible choices, while selectedOption indicates the passenger's current preference. """ type PlaceProperty { id: ID! type: String! required: Boolean availableOptions: [PlacePropertyOption!]! selectedOption: PlacePropertyOption } """ An option for a place property. Represents a specific choice within a place property category. These options are what passengers can select from when choosing their preferences. Examples by property type: - GENDER: "MEN", "LADIES", "MIXED" - PLACE_OR_COMPARTMENT_LOCATION: "WINDOW", "AISLE", "FRONT", "BACK" - SPECIAL_COMPARTMENT_TYPE: "EASY_ACCESS", "WITHOUT_ANIMALS", "QUIET_ZONE" The value field contains the standardized identifier for the option, while the id field provides a unique reference for selection tracking. """ type PlacePropertyOption { id: ID! value: String! } """ A rule attached to an offer part about using, refunding or exchanging the ticket. Every condition carries `description`: complete, human-readable text that is always safe to show on its own. Tell the kinds apart by `__typename` and read their typed fields through inline fragments (`... on ValidityCondition { validFrom validUntil }`). New kinds may be added over time: render `description` for any `__typename` you do not recognize rather than dropping the entry. The list holds only what the provider stated — the absence of a kind (no `ValidityCondition`, no TRAIN_BOUND) means the provider did not say, never that the rule does not apply. `type` and `timeframe` sit on the interface only so that selections written against the previous `[ReturnCondition!]!` shape keep validating; see their deprecation reasons. """ interface Condition { description: String! type: ConditionType! @deprecated(reason: "Temporary, backwards-compatible migration bridge: existing selections keep working unchanged while it stands. The end state removes this field from Condition; each concrete type then carries its own narrow enum (ReturnCondition.type: ReturnType, TravelCondition.type: TravelConditionType; ValidityCondition has no type). Until then a bare selection returns ConditionType, which also carries the travel-condition values ROUTE, TRAIN_BOUND and RESTRICTION, and UNKNOWN for a ValidityCondition. Select `description` on Condition and structured fields through an inline fragment, e.g. `... on ReturnCondition`.") timeframe: ReturnConditionTimeframe! @deprecated(reason: "Temporary, backwards-compatible migration bridge: existing selections keep working unchanged while it stands. The end state removes this field from Condition — it stays on ReturnCondition, the only type where it means anything; TravelCondition and ValidityCondition return UNKNOWN here. Select `description` on Condition and `timeframe` through `... on ReturnCondition`.") } """ A refund or exchange rule for the ticket. `type` says which of the two it is, `timeframe` until when the rule applies, and `description` is the rule in words. """ type ReturnCondition implements Condition { description: String! """ Whether this is a refund or an exchange rule. A subset of `ConditionType`: only ever REFUND, EXCHANGE or UNKNOWN. """ type: ConditionType! timeframe: ReturnConditionTimeframe! } """ The dates on which the ticket may be used. `validFrom` and `validUntil` are inclusive calendar dates in the operator's local time zone, and they are definite: travel may start on `validFrom` and no later than `validUntil`. There is deliberately no time of day. Operators let the last valid day run on into the following morning — UK National Rail until 04:29, Deutsche Bahn Flexpreis until 10:00 — and they differ on what that overrun permits (starting a journey, or only finishing one), so it is never encoded in these dates; where a provider states it, it is in `description`. Do not convert the dates to timestamps or shift them between time zones. A part with a TRAIN_BOUND `TravelCondition` never has a `ValidityCondition`: the booked departure is its validity. A part with neither has a provider that did not state a validity window; it is not valid indefinitely. """ type ValidityCondition implements Condition { description: String! """ First day, inclusive, on which travel may start. A calendar date in the operator's local time zone — for a ticket bought for a specific outbound date this is that date. Not a timestamp; do not attach a time or a time zone. """ validFrom: Date! """ Last day, inclusive, on which travel may start; equal to `validFrom` for a ticket valid on one day only. A calendar date in the operator's local time zone. Operators extend this day into the following morning (UK National Rail until 04:29, Deutsche Bahn Flexpreis until 10:00) and differ on what that extension permits, so it is deliberately not part of this value; look in `description` for it. """ validUntil: Date! """ Whether the passenger may leave the station partway through the journey and continue later on the same ticket, within the validity dates. `true`: allowed. `false`: not allowed — the ticket buys one continuous journey. `null`: the provider did not say; treat as unknown, never as allowed. UK fares state this per ticket type; many other providers only imply it through the fare family, and those arrive as `null`. """ breakOfJourney: Boolean type: ConditionType! @deprecated(reason: "On this type the field is a placeholder required by the interface and always returns UNKNOWN. Temporary, backwards-compatible migration bridge: existing selections keep working unchanged while it stands. The end state removes this field from Condition; each concrete type then carries its own narrow enum (ReturnCondition.type: ReturnType, TravelCondition.type: TravelConditionType; ValidityCondition has no type). Until then a bare selection returns ConditionType, which also carries the travel-condition values ROUTE, TRAIN_BOUND and RESTRICTION, and UNKNOWN for a ValidityCondition. Select `description` on Condition and structured fields through an inline fragment, e.g. `... on ReturnCondition`.") timeframe: ReturnConditionTimeframe! @deprecated(reason: "On this type the field is a placeholder required by the interface and always returns UNKNOWN. Temporary, backwards-compatible migration bridge: existing selections keep working unchanged while it stands. The end state removes this field from Condition — it stays on ReturnCondition, the only type where it means anything; TravelCondition and ValidityCondition return UNKNOWN here. Select `description` on Condition and `timeframe` through `... on ReturnCondition`.") } """ A rule about how the ticket may be used, other than the dates it is valid on (those are a `ValidityCondition`). `type` says what kind of rule it is, `description` is always the complete text, and `url` is set when a web page holds the full wording of this specific rule. Render `description`; when `url` is present, make it a link. """ type TravelCondition implements Condition { description: String! """ What kind of rule this is. A subset of `ConditionType`: only ever ROUTE, TRAIN_BOUND or RESTRICTION. """ type: ConditionType! """ Web page holding the complete wording of this condition, or `null` when there is none. Show it as a link, labeled by `description`. Today only RESTRICTION conditions carry one. """ url: String timeframe: ReturnConditionTimeframe! @deprecated(reason: "On this type the field is a placeholder required by the interface and always returns UNKNOWN. Temporary, backwards-compatible migration bridge: existing selections keep working unchanged while it stands. The end state removes this field from Condition — it stays on ReturnCondition, the only type where it means anything; TravelCondition and ValidityCondition return UNKNOWN here. Select `description` on Condition and `timeframe` through `... on ReturnCondition`.") } """Journey result produced by any given search algorithm""" interface Journey implements Node { id: ID! status: JourneyStatus! itinerary: [ItineraryItem!] } """ A direct journey with no planned stopovers. Represents the optimal (fastest) end-to-end route from origin to destination without overnight stopovers. Transfers between trains may still occur, but the itinerary does not intentionally include long breaks or multi-day segments. While this optimizes for speed, it may result in less comfortable connections that require transfers at inconvenient times. Use when passengers want the fastest connection in a single travel day where possible. """ type NonStopJourney implements Journey & Node { id: ID! status: JourneyStatus! itinerary: [ItineraryItem!] } """ A journey constructed from a predefined itinerary blueprint. Uses a curated sequence of segments and optional stopovers defined by a blueprint. Blueprints are suitable for editorial or productized routes (e.g. scenic itineraries, recommended routes, or multi-city trips) and can include planned overnight stopovers. Typical use cases: - Publishing recommended routes with fixed or suggested stopovers - Recreating saved or shared itineraries - Ensuring specific paths or operators are used """ type BlueprintJourney implements Journey & Node { id: ID! status: JourneyStatus! itinerary: [ItineraryItem!] } """ A journey that optimizes for comfort by limiting daily travel time. For short distances, provides direct connections when available. For longer routes, automatically segments the journey into multiple days to avoid excessively long travel times. This ensures passenger comfort and builds in buffer time in case of disruptions. Segmentation logic considers factors like night trains, connection times, and time of day to determine whether splitting into multiple days would improve the overall experience. This is the default journey type returned by the API. Typical use cases: - Long-distance trips that would be exhausting in a single day - Routes where overnight breaks improve reliability - Itineraries benefiting from night trains or natural break points """ type SmartJourney implements Journey & Node { id: ID! status: JourneyStatus! itinerary: [ItineraryItem!] } """ The composite offer for a journey: the journey itself (with `itinerary`) carrying the bookable `Offer`s that go together, grouped per `SegmentCollection`. Compose a booking from whichever offer ids you choose (`createBooking`). Produced by `journeyOffer` (single) and `combinedJourneyOffer` (round trip). """ type JourneyOffer implements Journey & Node { id: ID! status: JourneyStatus! itinerary: [ItineraryItem!] } """ An outbound and an inbound journey priced together as a round trip, so providers that sell true return fares can return them. Offers hang off each direction's SegmentCollections, exactly as on a single JourneyOffer. """ type CombinedJourneyOffer { """ The outbound journey (origin → destination) with priced offers, possibly multi-leg """ outbound: JourneyOffer! """ The inbound journey (destination → origin) with priced offers, possibly multi-leg """ inbound: JourneyOffer! } """The journey selected for an offer""" type JourneySelection { itinerary: [ItineraryItem!]! } """Fare offer for given itinerary item""" interface Fare implements Node { id: ID! name: String! price: Money! } """A fare offer for a journey""" type JourneyFare implements Fare & Node { id: ID! name: String! price: Money! } """A bookable fare offer for a journey""" type BookingFare implements Fare & Node { id: ID! name: String! price: Money! description: String refundPolicies: [String!] placePreferences: [PlacePreference!] compartmentTypes: [CompartmentType!] } """The selected fare of a journey offer""" type SelectedFare implements Fare & Node { id: ID! name: String! price: Money! description: String refundPolicies: [String!] placePreference: PlacePreference compartmentType: String } """A compartment type for a fare, e.g. Sleeper or Couchette""" type CompartmentType { name: String! value: String! } """Possible place preferences""" type PlacePreference implements Node { id: ID! name: String! price: Money } """ Passengers grouped by type for fare calculation and pass bundle allocation. Represents a count of passengers of the same type that will be traveling together. This grouping is used to: - Calculate group fares and discounts - Allocate rail passes and other travel products The count field represents the number of passengers of this specific type. """ type PassengerBundle { count: Int! type: PassengerBundleType! } """ Bundle of rail passes and similar travel products. Represents a collection of travel passes that can be purchased together, typically for multiple passengers or extended travel periods. These bundles provide access to train networks across multiple countries. Pass structure: - `class`: "1stclass" (first class travel) or "2ndclass" (second class travel) - `product`: "interrail-global-pass" (33 countries), "interrail-one-country-pass-sweden" (single country). A legacy "eurail-*" key is accepted as an alias for its "interrail-*" counterpart - `travelDayCount`: Number of days the pass can be used for travel within the validity period - `validityPeriod`: Overall time window when the pass is valid Pass types: - Continuous passes: `travelDayCount` is null (unlimited daily travel during validity period) - Flexi passes: `travelDayCount` specifies exact number of travel days within validity period """ type PassBundle implements Node { id: ID! class: String product: String! price: Money! passengers: [PassengerBundle!]! travelDayCount: Int validityPeriod: Duration } """ Monetary sum using CLDR (Common Locale Data Repository) format. The amount field represents the monetary value in the smallest currency unit: - For currencies with decimal places (USD, EUR, GBP, etc.): amount is in cents (e.g., 1000 = $10.00, 1250 = €12.50) - For currencies without decimal places (JPY, KRW, etc.): amount is in whole units (e.g., 1000 = ¥1000, 1250 = ¥1250) Users are advised to consult the CLDR specification for proper currency formatting and display. The currency field contains the ISO 4217 currency code (e.g., "USD", "EUR", "JPY"). Examples: - USD 1000 = $10.00 (1000 cents) - EUR 1250 = €12.50 (1250 euro cents) - JPY 1000 = ¥1000 (1000 yen, no decimal places) - KRW 5000 = ₩5000 (5000 won, no decimal places) """ type Money { amount: Int! currency: String! } """A passenger with minimal details""" interface Passenger { type: PassengerType! id: ID! age: Int birthDate: Date travelCards: [TravelCard!] """ The corporate agreement codes the passenger was searched and booked with """ corporateCodes: [CorporateCode!]! """ The passenger profile this passenger was named by when the booking was created, as `passengerProfiles` and `me.profile` return its id. It identifies a profile in a profile directory, not a person: the passenger's details are the booking's own, filled in from the profile when the booking was created, and a later change to the profile does not reach them. Null when no profile was named. Only booking creation sets it: `updateBooking` cannot change it, and the order's passenger keeps it. `node` resolves it to the profile, read from the directory again rather than from the booking (see `PassengerProfile.id`). """ passengerProfileId: ID """ The passenger's custom fields: every field the passenger's company defines for its travelers in its profile directory, such as a cost center, an employee number or a project number. The company is that of the passenger profile this passenger was named by, else the booking's. Each field holds the profile's value when the booking was created, or none. From then on the values are the booking's own: a later change to the profile does not reach them, `updateBooking` can set or change them until the booking's order is paid or confirmed, and the order's passenger keeps them. Empty when the company has no profile directory. Booking creation is refused when the company's fields cannot be read. """ customFields: [CustomField!]! } """The minium passenger details""" type PassengerPlaceholder implements Passenger { type: PassengerType! id: ID! age: Int birthDate: Date travelCards: [TravelCard!] """ The corporate agreement codes the passenger was searched and booked with """ corporateCodes: [CorporateCode!]! """ The passenger profile this passenger was named by when the booking was created, as `passengerProfiles` and `me.profile` return its id. It identifies a profile in a profile directory, not a person: the passenger's details are the booking's own, filled in from the profile when the booking was created, and a later change to the profile does not reach them. Null when no profile was named. Only booking creation sets it: `updateBooking` cannot change it, and the order's passenger keeps it. `node` resolves it to the profile, read from the directory again rather than from the booking (see `PassengerProfile.id`). """ passengerProfileId: ID """ The passenger's custom fields: every field the passenger's company defines for its travelers in its profile directory, such as a cost center, an employee number or a project number. The company is that of the passenger profile this passenger was named by, else the booking's. Each field holds the profile's value when the booking was created, or none. From then on the values are the booking's own: a later change to the profile does not reach them, `updateBooking` can set or change them until the booking's order is paid or confirmed, and the order's passenger keeps them. Empty when the company has no profile directory. Booking creation is refused when the company's fields cannot be read. """ customFields: [CustomField!]! } """All passenger details""" type FullPassenger implements Passenger { type: PassengerType! id: ID! firstName: String lastName: String age: Int tel: String email: String birthDate: Date title: PassengerTitle countryResidence: String isContactPerson: Boolean nationality: String passportNumber: String placeOfBirthCity: String placeOfBirthCountry: String travelCards: [TravelCard!] """ The corporate agreement codes the passenger was searched and booked with """ corporateCodes: [CorporateCode!]! """ The passenger profile this passenger was named by when the booking was created, as `passengerProfiles` and `me.profile` return its id. It identifies a profile in a profile directory, not a person: the passenger's details are the booking's own, filled in from the profile when the booking was created, and a later change to the profile does not reach them. Null when no profile was named. Only booking creation sets it: `updateBooking` cannot change it, and the order's passenger keeps it. `node` resolves it to the profile, read from the directory again rather than from the booking (see `PassengerProfile.id`). """ passengerProfileId: ID """ The passenger's custom fields: every field the passenger's company defines for its travelers in its profile directory, such as a cost center, an employee number or a project number. The company is that of the passenger profile this passenger was named by, else the booking's. Each field holds the profile's value when the booking was created, or none. From then on the values are the booking's own: a later change to the profile does not reach them, `updateBooking` can set or change them until the booking's order is paid or confirmed, and the order's passenger keeps them. Empty when the company has no profile directory. Booking creation is refused when the company's fields cannot be read. """ customFields: [CustomField!]! } """ A custom field: one of the fields configured in a profile directory, with the value it holds here. """ type CustomField { """ The profile directory's key for the field: opaque, and particular to how the directory is configured, so the same kind of field can have a different key for another sales agent. Everything that carries the field carries the same key, each with its own value. """ key: String! """ The field's label as configured in the profile directory, such as "Cost Center" or "Employee number": not a fixed vocabulary. """ name: String! """The kind of value the field holds, and so the input to show for it.""" type: CustomFieldType! """ The field's value, of its `type` as `CustomFieldValue` describes it. Null when it was cleared. """ value: CustomFieldValue """Whether the profile directory requires the field to hold a value.""" required: Boolean! """ Whether the field is read-only for you, so you cannot change it. That depends on how the field is configured in the profile directory and on who you are there: the sales agent that manages the directory, a booker for the company the field belongs to, or a traveler booking for themselves. A field configured as read-only, or as not editable, is read-only for everyone; one only the managing sales agent may set is read-only for everyone else; and one a traveler may only read, or only bookers may set, is read-only for a traveler. """ readonly: Boolean! } """ The kind of value a custom field holds, as configured in the profile directory. """ enum CustomFieldType { """A single line of text.""" INPUT """Text that may run over several lines.""" TEXTAREA """Yes or no, typically a checkbox or toggle.""" BOOLEAN """A calendar date.""" DATE """A phone number, kept as written.""" TEL } """ A travel/discount card held by a passenger. Represents loyalty, discount, or rail cards that may entitle the passenger to reduced fares. Examples include BahnCard (Germany), Halbtax (Switzerland), Carte Avantage (France), or Interrail. Use the `travelCardOptions` query to discover available cards and their required input fields. """ type TravelCard { """Unique card type code""" code: String! """Card number or other identifying value, if required by the card type""" identifier: String """Human-readable name of the card""" name: String! } """Input for attaching a travel card to a passenger""" input TravelCardInput { """Card type code""" code: String! """Card number or other identifying value, when required by the card type""" identifier: String } """ A corporate agreement code: a company's negotiated rate with an operator, priced into the passenger's offers at search. """ type CorporateCode { """The agreement code as the operator issued it""" code: String! """The operator holding the agreement""" operator: Operator! } """Input for attaching a corporate agreement code to a passenger""" input CorporateCodeInput { """The agreement code as the operator issued it""" code: String! """ The operator holding the agreement, as its `Operator.code` (for example `aaop_sj`). A code naming an operator we do not know is refused with `CORPORATE_CODE_OPERATOR_UNKNOWN` """ operator: String! } """ An available travel card type that passengers can hold. Use the `code` field when constructing a `TravelCardInput` and consult `inputFields` to determine which additional fields are needed. """ type TravelCardOption { """Unique card type code""" code: String! """Human-readable name of the card""" name: String! """Fields required when using this card type""" inputFields: [CardFieldRequirement!]! } """ Describes whether a specific field is required for a travel card type. Each entry maps a field name (e.g. "identifier") to a requirement level indicating if and when it must be provided. """ type CardFieldRequirement { """Name of the field (e.g. "identifier")""" fieldName: String! """Whether the field is required""" requirement: FieldRequirement! } """ Details required for all passengers on a specific booking. Defines which passenger information fields are mandatory for a particular booking. Requirements are determined by ticketing providers and vary depending on the operator being used. """ type PassengerRequirements { countryResidence: Boolean! dateOfBirth: Boolean! email: Boolean! nationality: Boolean! passportNumber: Boolean! placeOfBirthCity: Boolean! placeOfBirthCountry: Boolean! title: Boolean! tel: Boolean! firstName: Boolean! lastName: Boolean! } """ Represents a temporary booking that holds selected offers, pass bundles, and passenger information before payment and confirmation. Bookings have a limited lifespan and must be confirmed before expiration. If `expiresAt` is reached without confirmation, or if the booking fails for any reason, the booking is automatically canceled and offers are released back to inventory. An expired or failed booking cannot be used again and will need to be recreated from scratch. """ type Booking implements Node { id: ID! expiresAt: DateTime ticketingFee: Money totalPrice: Money passengers: [Passenger!] selections: [BookingSelection!] """ The booking's own custom fields, such as a VAT number or a purchase order number, prefilled from the company's profile and set with `setCustomFields`. Empty when the company has no profile directory. """ customFields: [CustomField!]! requirements: PassengerRequirements termsAndConditions: [String!] } """Selections that can be part of a booking""" union BookingSelection = JourneyOfferSelection | PassBundleSelection """Selected journey offer that is part of a booking""" type JourneyOfferSelection { journey: JourneySelection! offers: [Offer!]! fares: [SelectedFare!]! @deprecated(reason: "Use `offers` instead") } """Selected Interrail bundle that is part of a booking""" type PassBundleSelection { product: String! class: String price: Money! passengers: [PassengerBundle!]! travelDayCount: Int validityPeriod: Duration } """A map of places on e.g. a leg of a journey""" union PlaceMap = SeatMap """A map of seats for each coach""" type SeatMap { coaches: [SeatMapCoach!]! } """A coach with seats""" type SeatMapCoach { identifier: String seats: [SeatMapSeat!]! """ Facilities marked on the floor plan, such as toilets, exits and bicycle spaces """ features: [SeatMapFeature!]! floorPlan: SeatMapFloorPlan! } """ The floor plan of a coach, drawn landscape with the direction of travel to the left. Seats and features are positioned by their top-left corner in the plan's pixels. """ type SeatMapFloorPlan { height: Int! width: Int! image: FileResource! } """A facility marked on a coach's floor plan""" type SeatMapFeature { type: SeatMapFeatureType! xpos: Int! ypos: Int! width: Int! height: Int! } """ The kind of facility a floor plan marks, named after OSDM's Graphics Items code list. Expect values to be added. """ enum SeatMapFeatureType { TOILET_AREA ENTRY_EXIT BICYCLE_AREA WHEELCHAIR_SPACE PRAM_AREA LUGGAGE_AREA BABY_CARE_TABLE PLAYGROUND_AREA RESTAURANT_AREA } """A placement on a coach, eg. a seat or a bed""" interface Placement { availability: PlaceAvailability! } """A seat on a coach""" type SeatMapSeat implements Placement { xpos: Int! ypos: Int! width: Int! height: Int! identifier: String! availability: PlaceAvailability! """ The way the seat faces, in degrees clockwise from the direction of travel on the floor plan: 0 faces the direction of travel, 180 faces away from it. Null when the provider doesn't say. """ orientation: Int """ Whether the seat can be turned to face either way, in which case `orientation` is only how it is set. Null when the provider doesn't say. """ reversible: Boolean } """ Represents a payment that needs to be processed to complete an order. The payment interface defines the common fields shared across different payment methods: - `id`: Unique identifier for the payment - `url`: URL where the customer can complete the payment Different payment implementations (like `StripePayment` or `NoChargeRedirect`) may provide additional fields specific to their payment flow. The payment URL typically redirects to a payment page hosted by All Aboard where the customer can securely enter their payment details. """ interface Payment implements Node { id: ID! url: String! } """Payment using Stripe""" type StripePayment implements Payment & Node { id: ID! url: String! clientSecret: String! @deprecated(reason: "Reserved for internal use") successUrl: String! @deprecated(reason: "Reserved for internal use") cancelUrl: String! @deprecated(reason: "Reserved for internal use") } """ Payment type used when no payment is required. This payment type is used in cases where the order has a total price of 0. The URL field will redirect to the provided `successUrl`. """ type NoChargeRedirect implements Payment & Node { id: ID! url: String! } """Paginated orders list result""" type OrderConnection { edges: [OrderEdge!]! pageInfo: PageInfo! totalCount: Int! } """Pagination information""" type PageInfo { hasNextPage: Boolean! hasPreviousPage: Boolean! startCursor: String endCursor: String } """An order edge in a paginated list""" type OrderEdge { node: Order! cursor: String } """Paginated locations list result""" type LocationConnection { edges: [LocationEdge!]! pageInfo: PageInfo! """ How many locations the whole list holds under the `filter` this page was read with, or every location when there is none, counted when this page was read. Locations are added and withdrawn, so paging through several pages can end on a different number. """ totalCount: Int! } """A location edge in a paginated list""" type LocationEdge { node: Location! cursor: String } """ Finalized order with confirmed bookings and issued tickets. Represents a completed transaction where payment has been processed, offers have been confirmed, and tickets have been or are being issued. Orders are the final state of a booking and contain all travel documentation. The reference field is typically used for customer service inquiries. """ type Order implements Node { """ The order's `order_…` id, the form every operation taking an order id accepts. Orders placed before these ids existed were handed out an id in another form; `node` still resolves those. """ id: ID! createdAt: ZonedDateTime! status: OrderStatus! reference: String! items: [OrderItem!] totalPrice: Money! passengers: [FullPassenger!] metadata: JSONObject """ The booking's custom fields as they were when the order was created. Read-only. """ customFields: [CustomField!]! """The sales agent the order belongs to and is billed to""" salesAgent: SalesAgent! """ Who created the order: the credential's sales agent, and the person when known """ createdBy: OrderCreator! } """Who created an order""" type OrderCreator { """ The sales agent whose credential created the order. Differs from the order's `salesAgent` when a parent agent ordered on behalf of a sub-agent. """ salesAgent: SalesAgent! """The end user who created the order. Null when no signed-in user did.""" user: User } """Items that can be part of an order""" union OrderItem = GenericOrderItem | JourneyOrderItem | PassBundleOrderItem """An unspecified item in an order""" type GenericOrderItem { description: String! price: Money! } """ A booked journey from a journey offer, containing segments, tickets and other resources """ type JourneyOrderItem { segments: [Segment!]! offer: Offer! resources: [OrderResource!] fare: SelectedFare! @deprecated(reason: "Use `offer` instead") tickets: [FileResource!] @deprecated(reason: "Use `resources` instead") } """A resource associated with an order""" union OrderResource = PdfTicket | TicketOnDeparture | CheckInResource | FileResource | SelfServiceResource """ Generic file resource that can be accessed or downloaded. Represents digital assets associated with orders, such as tickets, boarding passes, receipts, and other travel documents. Resources are typically accessed via URLs and may have different formats. Common resource types: - application/pdf: PDF tickets, receipts, and documentation - image/png: QR codes, boarding passes, and visual elements - text/plain: Plain text instructions and confirmations - application/json: Structured data and API responses Resources may have access restrictions or expiration times depending on the type and operator policies. """ type FileResource { name: String type: String! url: String! } """Ticket which can be retrieved on departure""" type TicketOnDeparture { """Ticket collection reference""" reference: String! """Instructions on how to retrieve the ticket""" description: String! } """Ticket issued in PDF format for download""" type PdfTicket { url: String! } """Resource that can be accessed for check-in and ticket issuing""" type CheckInResource { url: String! } """ Resource that provides a self-service link for customers to manage their booking on the provider's website """ type SelfServiceResource { url: String! """ Metadata about the self-service resource, e.g. the booking number and email """ metadata: JSONObject } """ A booked rail pass from a pass bundle offer, containing passenger details and pass information """ type PassBundleOrderItem { passenger: FullPassenger! code: String class: String product: String! price: Money! travelDayCount: Int validityPeriod: Duration } """Represents a potential refund opportunity before execution""" interface RefundableItem { id: ID! description: String! """The amount that will be refunded""" amount: Money """The passengers this item covers, when known""" passengers: [FullPassenger!] } """Contains the corresponding offer part of the refundable item""" type RefundableOfferItem implements RefundableItem { id: ID! description: String! """The amount that will be refunded""" amount: Money """The passengers this item covers, when known""" passengers: [FullPassenger!] """The offer parts that will be refunded""" refundParts: [BookedOfferPart!]! } """Contains the corresponding pass item of the refundable item""" type RefundablePassItem implements RefundableItem { id: ID! description: String! """The amount that will be refunded""" amount: Money """The passengers this item covers, when known""" passengers: [FullPassenger!] """The pass item that will be refunded""" passItem: PassBundleOrderItem } """Represents a refund line item after execution has been initiated""" interface RefundItem { id: ID! state: RefundItemState! description: String! """The amount that will be refunded""" amount: Money """The passengers this item covers, when known""" passengers: [FullPassenger!] } """Contains the corresponding offer part of the refund item""" type RefundOfferItem implements RefundItem { id: ID! state: RefundItemState! description: String! """The amount that will be refunded""" amount: Money """The passengers this item covers, when known""" passengers: [FullPassenger!] """The offer parts that will be refunded""" refundParts: [BookedOfferPart!]! } """Contains the corresponding pass item of the refund item""" type RefundPassItem implements RefundItem { id: ID! state: RefundItemState! description: String! """The amount that will be refunded""" amount: Money """The passengers this item covers, when known""" passengers: [FullPassenger!] """The pass item that will be refunded""" passItem: PassBundleOrderItem } """A refund record capturing the execution of refund items for an order.""" type Refund implements Node { id: ID! state: RefundState! createdAt: ZonedDateTime! items: [RefundItem!]! } """ A cost center belonging to a sales agent, used for billing and payment routing """ type CostCenter { id: ID! name: String! default: Boolean! paymentMethod: PaymentMethod! } """An authorized agent interacting with the API""" type SalesAgent { uid: String! """The sales agent's display name, such as the company or agency name.""" name: String email: String tel: String paymentMethod: PaymentMethod! rateLimits: [RateLimit!]! costCenters: [CostCenter!]! } """Paginated sales agents list result""" type SalesAgentConnection { edges: [SalesAgentEdge!]! pageInfo: PageInfo! """ How many sales agents the whole list holds under the `filter` this page was read with, counted when this page was read. Grants are given and revoked, so paging through several pages can end on a different number. """ totalCount: Int! } """A sales agent edge in a paginated list""" type SalesAgentEdge { node: SalesAgent! cursor: String! } """The authenticated end user, as identified by their user token (JWT)""" type User { """The user's unique id""" id: ID! """The user's email address""" email: String! """The user's given name. Null when their account carries none.""" firstName: String """The user's family name. Null when their account carries none.""" lastName: String """ The user's own passenger profile, for prefilling their passenger details. Null when the sales agent keeps no profile directory, when no profile in it belongs to this user, or when the directory could not be reached. None of those is an error — ask the traveler for their details instead. """ profile: PassengerProfile } """ A traveler's persistent details, offered to prefill a passenger. Every detail is nullable: a directory profile is data we do not control, and a detail it does not hold (or that we could not read) is simply absent rather than fatal. Only `id`, `salesAgent`, `costCenter` and `travelCards` (possibly empty) are always set. It deliberately carries no passenger `type` and no `age` — both depend on a travel date as well as a birth date, and a profile has no journey. Name the profile with `passengerProfileId` when searching and booking, and the API derives them from `birthDate` at the travel date. """ type PassengerProfile implements Node { """ Identifies this profile in the profile directory it was read from. Opaque: keep it for list keys, selection and spotting the same profile on another page, and never parse it. It identifies a profile, not a person: the same person in two directories, or with two agencies, has two ids. `node` reads the profile by this id from the directory; a change made there can take up to ten minutes to show. It is null both for a profile that does not exist and for one the caller may not book for. Reading any profile but the viewer's own requires the `passenger_profiles:read` scope (`FORBIDDEN`), and a directory that cannot be read fails the request (`NO_PROFILE_DIRECTORY`, `UPSTREAM_UNAVAILABLE`). """ id: ID! """ The sales agent the passenger profile belongs to: the company whose profile directory holds it, never null. A booking from this profile is placed on one of its `costCenters`. """ salesAgent: SalesAgent! """ The passenger profile's preferred cost center, never null: our best guess from the directory, to pre-select unless the booker knows better. It is the cost center the directory names for the profile when we recognize it under `salesAgent`, otherwise the sales agent's default. Any of `salesAgent.costCenters` may be booked on instead. """ costCenter: CostCenter! """The traveler's given name""" firstName: String """The traveler's family name""" lastName: String """The traveler's preferred title""" title: PassengerTitle """The traveler's date of birth""" birthDate: Date """The traveler's email address""" email: String """The traveler's telephone number""" tel: String """The traveler's nationality""" nationality: String """Discount cards the traveler holds, as far as we recognize them""" travelCards: [TravelCard!]! } """ A page of passenger profiles. There is no total: the directory keeps none. A page may hold fewer profiles than asked for, or none, while `pageInfo.hasNextPage` is still true, because profiles of companies the caller may not book for are left out after the page was read; keep paging from `pageInfo.endCursor` until `hasNextPage` is false. """ type PassengerProfileConnection { edges: [PassengerProfileEdge!]! """ `startCursor` and `endCursor` are set on every page that was read, even one with no edges, so paging can always continue from `endCursor`. `hasNextPage` is whether the directory has a further page to read. """ pageInfo: PageInfo! } """A passenger profile edge in a paginated list""" type PassengerProfileEdge { node: PassengerProfile! """ Opaque, and this edge's own, so a cache that merges pages by cursor keeps every profile of a page. As `after`, it continues at the page after the one this profile is on, not after this profile: any cursor of a page reads the same next page. """ cursor: String! } """ A sales campaign: an alternative set of terms and products to sell under. Only campaigns the authenticated caller may use are returned, so any code listed here can be passed wherever a campaign code is accepted. """ type Campaign { """ The campaign's code, passed as `campaignCode` in the pass bundle filter to see what the campaign offers. """ code: String! """ Products this campaign currently covers, ordered alphabetically by key. Every product listed has at least one pass on sale under this campaign, and a product not listed has none, so a client can offer the list as-is. Empty when the campaign's terms currently match nothing on sale. Coverage is per campaign, not per party: a listed product can still yield no bundle for a particular set of travelers if it has no pass for one of their passenger types. """ products: [Product!]! } """A product we sell, such as a particular rail pass.""" type Product { """ The product's key, e.g. `interrail-global-pass`. Stable and safe to hardcode: this is the value the pass bundle filter accepts as its `product` and the value a pass bundle reports as its `product`. """ key: String! """ The product's name. Whatever name the product carries in our catalog, in no guaranteed language. Suitable as a fallback label; supply your own copy where you need it localised or on-brand. """ name: String! } """ Rate limit imposed for an agent to prevent API abuse. Implements rate limiting to ensure fair usage of the API across all agents and to protect system resources from excessive requests. When remaining reaches 0, requests are rejected until resetAt. Specific limits are determined by the commercial agreement with each agent. """ type RateLimit { limit: Int! remaining: Int! resetAt: DateTime! resource: String! unit: RateLimitUnit! } """ Via stopover for a journey to break up long trips. Allows passengers to specify intermediate locations where they want to stop and spend time before continuing their journey. This is useful for long-distance travel where passengers want to explore cities along the way or break up overnight journeys. Field requirements: - uid: Required - the location UID where the stopover occurs - duration: Optional - how long to stay (e.g., "P2D" for 2 days) If not specified, the journey will simply route via that location with a change of trains (no extended stopover) """ input ViaInput { uid: ID! duration: Duration } """ Identifies a location. Holds the location's `uid` today. Future identifiers will be added as further optional fields rather than as new arguments. """ input LocationInput { """Unique identifier of the location""" uid: ID! } """ A point in GeoJSON format, following RFC 7946 and using the WGS84 coordinate system. Coordinates are given as [longitude, latitude] (note the order), and `type` is always "Point". Examples: - London: { type: "Point", coordinates: [-0.1278, 51.5074] } - Stockholm: { type: "Point", coordinates: [18.0686, 59.3293] } """ input GeoJSONInput { type: String! coordinates: [Float!]! } """Narrows a list of sales agents. Every field set must match.""" input SalesAgentsFilter { """ Text to find sales agents by: part of a name or a uid. Case is ignored. Best matches first: a name or uid equal to the text, then one starting with it, then a word of the name or a part of the uid starting with it, then any other match. Equal matches are in name order, a sales agent without a name by its uid. Empty or blank text is no text. """ query: String } """What to search passenger profiles by. `query` is required.""" input PassengerProfilesFilter { """ Text to find passenger profiles by, at least one character besides blanks, else `INVALID_ARGUMENT`. Matched against names the way the directory's own search does, or against email addresses when it contains an `@`. """ query: String! """ Narrows the search to the passenger profiles of this sales agent: the caller's own, or one of `accessibleSalesAgents`, else `UNAUTHORIZED`; one whose orders are off is `FORBIDDEN`. It must be a company in the profile directory, else `INVALID_ARGUMENT`. Without it the search spans every company the caller may book for. """ salesAgentUid: String } """ Narrows and orders `locations`. Every field is optional, and which of `query` and `near` are given decides the order: `query` ranks by relevance, `near` without `query` orders by distance, and neither keeps the stable walk order. `countryCode` and `isMeta` only narrow. """ input LocationsFilter { """ Text to find locations by: a name, part of one, or an alias, optionally with an English country name ("paris france"). Case and diacritics are ignored, so "Koln" finds "Köln". Every word has to match. Best matches first: the whole text equal to a name or alias, then starting one, then each word starting a word, then close misspellings. Among equal matches a city comes before its stations and a popular location before a rare one. Empty or blank text is no text. """ query: String """ISO 3166-1 alpha-2 country the locations must be in.""" countryCode: String """ A GeoJSON Point, `[lng, lat]`. Without `query` the locations are ordered by their distance from it; with `query` it only breaks ties between equally good matches. """ near: GeoJSONInput """With `near`: leaves out locations further away than this many metres.""" radius: Int """Only cities (true) or only single stations and stops (false).""" isMeta: Boolean } """Narrows `orders`. Every field set must match.""" input OrdersFilter { """ Text to find orders by. An order reference, a legacy numeric order id, a provider booking reference (PNR or DNR), a pass number or an Interrail order number matches when it equals the whole text; a passenger name ("first last") or email matches when it contains it. Case is ignored and double quotes are dropped. Names and emails are matched as a regular expression, so `.` matches any character, and text with an odd number of double quotes or that is not a valid regular expression is refused. Empty or blank text is no text. """ query: String """ Only orders that belong to this sales agent: the order's `salesAgent`, the agent whose cost center it is on, not `createdBy.salesAgent`. Your own uid or one `accessibleSalesAgents` lists; any other uid, whether a sales agent has it or not, is refused with `UNAUTHORIZED`. """ salesAgentUid: String """ Only orders this user created: `createdBy.user.id`. That is the person who placed the order, not a traveler on it, so an order someone else booked for a person is not among theirs. Orders created with an API key have no user and never match. An id that is not a user id is refused with `INVALID_ARGUMENT`; a user who created none of the orders you can see leaves an empty list. """ createdByUserId: ID } """Passenger details for passholder""" input PassPassengerInput { type: PassengerType age: Int birthDate: Date countryResidence: String nationality: String } """Selects a cost center to bill this passenger's travel against""" input CostCenterInput { id: ID! } """ Input type for basic passenger details. When specifying a passenger's age, either: 1. Provide the `birthDate` field with their date of birth, OR 2. Provide the `age` field with their age at time of travel For passenger types `YOUTH` and `SENIOR`, one of these age fields must be provided to validate eligibility for age-based fares and discounts. For the `ADULT` passenger type, age fields are optional. """ input PassengerPlaceholderInput { type: PassengerType birthDate: Date """Age at the time of travel""" age: Int """ Travel cards held by the passenger. They are part of the price, so pass the same cards when pricing the journey and when creating the booking """ travelCards: [TravelCardInput!] """ Corporate agreement codes priced into this passenger's offers. They are part of the price, so pass the same codes when pricing the journey and when creating the booking. Every passenger in a search or booking carries the same codes, or the request is refused with `CORPORATE_CODES_MIXED`: passengers on different agreements are searched and booked separately """ corporateCodes: [CorporateCodeInput!] """ Cost center to bill this passenger against; defaults to the agent's default cost center """ costCenter: CostCenterInput """ The passenger profile this passenger is, as `passengerProfiles` and `me.profile` return its id. The profile supplies the birth date, the travel cards and, where the request is priced on a cost center (journey search and booking), the cost center. A field sent here overrides the profile's: a `type`, `age` or `birthDate` sent here replaces the profile's birth date, so a `YOUTH` or `SENIOR` type then needs an `age`, as for any passenger. Otherwise type and age are derived from the profile's birth date at the travel date, so a request naming a profile passenger needs a date to derive them at, such as a departure date. A profile without a birth date is priced as an `ADULT` unless a `type` or `age` is sent. Booking creation fills the passenger's details from the profile, where `updateBooking` can change them. Null names no profile, and a null field takes the profile's. Naming any profile but the viewer's own requires the `passenger_profiles:read` scope (`FORBIDDEN`). A profile that does not exist and one the caller may not book for are both `PASSENGER_PROFILE_NOT_FOUND`; a profile that cannot be read fails the request (`NO_PROFILE_DIRECTORY`, `UPSTREAM_UNAVAILABLE`). Booking creation refuses two passengers naming the same profile (`INVALID_ARGUMENT`). Search results show nothing of the profile beyond the type and age. """ passengerProfileId: ID } """ Full passenger details required to complete a booking. Represents the complete set of passenger data that may be required by ticketing providers and operators. Exactly one passenger per booking must be marked as the contact person using `isContactPerson: true`. The contact person must provide both `email` and `tel` so they can receive operational updates. Notes: - Only one passenger should be marked as contact person per booking - When `isContactPerson` is true, `email` and `tel` must be provided - Other fields may be required depending on operator (see `PassengerRequirements`) """ input FullPassengerInput { id: ID! email: String """Phone number with country code (E.123)""" tel: String birthDate: Date firstName: String lastName: String """ Mark this passenger as the booking contact person; requires `email`, `tel` """ isContactPerson: Boolean title: PassengerTitle countryResidence: String nationality: String passportNumber: String placeOfBirthCity: String placeOfBirthCountry: String """ Travel cards held by the passenger. Fixed when the booking is created. On `updateBooking` either leave the field out or echo the stored cards unchanged; any other value is rejected with `TRAVEL_CARDS_IMMUTABLE`, and `null` is read as an empty list rather than as an omission """ travelCards: [TravelCardInput!] """ Corporate agreement codes held by the passenger. Fixed when the booking is created. On `updateBooking` either leave the field out or echo the stored codes unchanged; any other value is rejected with `CORPORATE_CODES_IMMUTABLE`, and `null` is read as an empty list rather than as an omission """ corporateCodes: [CorporateCodeInput!] """ New values for the passenger's custom fields, each naming a field by its key. Fields not listed keep their values; omit this field or send null to change none. A key named twice, a key the passenger has no custom field with, and a field that is `readonly` for you, are refused. Custom fields cannot change once the booking's order is paid or confirmed. """ customFields: [CustomFieldInput!] } """A new value for a custom field, named by its key.""" input CustomFieldInput { """The key of the custom field, as `customFields` returns it.""" key: String! """ The new value, of the field's type as `CustomFieldValue` describes it: a Boolean for a `BOOLEAN` field, a `YYYY-MM-DD` date for a `DATE` field, a String otherwise. Text is trimmed. Null, or blank text, clears it. A value that does not fit the field's type is refused. """ value: CustomFieldValue } """Selection of fare for a journey""" input FareSelectionInput { id: ID! placePreference: ID compartmentType: String } """Selection of offer for a journey""" input OfferSelectionInput { id: ID! } """Selection for a booking""" input BookingSelectionInput { offer: OfferSelectionInput } """ Filter for journey search results by journey type. Use this to restrict which journey variants are returned. Supported types: - SMART: Comfort-optimized journeys; may split long routes across days. Default journey type returned by the API. - BLUEPRINT: Journeys based on predefined itinerary blueprints (curated or editorial routes), can include planned stopovers. - NON_STOP: Fastest end-to-end journeys without planned overnight stopovers. You can combine multiple types to retrieve several variants at once. """ input JourneyFilterInput { types: [JourneyType!] } """ Filter for filtering pass bundles by various criteria. Supported filters: - product: Filter by specific pass product type, e.g. "interrail-global-pass" - class: Filter by travel class (e.g. "1stclass" or "2ndclass") - campaignCode: Filter by promotional campaign code, e.g. "INTERRAIL_2025" Use this to narrow down pass bundle results when searching for available passes. """ input PassBundleFilterInput { product: String class: String campaignCode: String } """Place property to update""" input PlacePropertyInput { optionId: ID! propertyId: ID! } """Ancillary to add to a booking for a given passenger""" input AddAncillaryInput { ancillaryId: ID! passengerId: ID! } """Ancillary selection to remove from a booking""" input RemoveAncillaryInput { id: ID! } """A place selection for a passenger""" input PlaceSelectionInput { seat: SeatSelectionInput } """A seat selection for a passenger""" input SeatSelectionInput { coachIdentifier: String seatIdentifier: String! passengerId: ID! } """ What an access token may do on the order it is bound to. `READ` is implied by `WRITE`, so a token minted with `[WRITE]` comes back carrying both — a credential that may refund an order may read it. """ enum AccessTokenCapability { """Read the order, its bookings, its refunds and its payments.""" READ """Start a refund of the order, and pay for it by card.""" WRITE } """ What an access token is narrowed to. Exactly one order today; the shape is an object so a later narrowing is an added field rather than a breaking change. """ input AccessTokenRestrictionsInput { """ The order the token may reach, as its `order_…` id. Nullable only so that omitting it fails with `INVALID_RESTRICTIONS` rather than as a schema validation error — a token bound to nothing is never minted. An order that does not exist, and one the caller may not read, both fail with `NOT_FOUND`. """ orderId: ID } """ What an access token is narrowed to. See `AccessTokenRestrictionsInput`. """ type AccessTokenRestrictions { """The order the token reaches, as its `order_…` id.""" orderId: ID! } """ A credential that reaches one order and nothing else. Presented in the `api-key` header, or as `Authorization: Bearer`, in place of the agency's own API key — which is what makes it safe to put on a page the public can open. Every request it authenticates is attributed to the agent and user that minted it. """ type AccessToken implements Node { """ The token's own id, for `revokeAccessToken` and `node`. Not the secret. """ id: ID! """ The secret to present as the `api-key` header. Non-null exactly once, on what `createAccessToken` returns. It is stored only as a hash, so nothing can hand it back afterwards: refetching the same token through `node` returns it as null. Lose it and mint another. """ token: String """What the token may do on its order, always at least `READ`.""" capabilities: [AccessTokenCapability!]! """What the token is narrowed to.""" restrictions: AccessTokenRestrictions! """When the token stops working. Always in the future at minting.""" expiresAt: ZonedDateTime! """ When the token was revoked, or null if it was not. Null does not mean the token still works — an unrevoked token past `expiresAt` is refused just the same. """ revokedAt: ZonedDateTime } """Supported queries""" type Query { """ Get location matching given query string Typically one would store the location data in a database. Get the complete location dataset from them agent dashboard (https://allaboard.eu/agent) Blank text answers nothing here, unlike `locations`, where a blank filter is no filter and pages the whole set. """ getLocations( """Search query""" query: String! ): [Location!]! @deprecated(reason: "Use `locations(filter: { query: … })` instead") """Get all available locations""" getAllLocations: [Location!]! @deprecated(reason: "Use `locations` instead") """ Get all possible journeys between origin and destination on given date See: https://docs.allaboard.eu/tickets/ """ getJourneys( """Origin location uid""" origin: ID! """Destination location uid""" destination: ID! """Date of departure""" date: Date! """Optional filter for journey search""" filter: JourneyFilterInput """Optional via stopovers""" via: [ViaInput!] """ Passenger details required for availability. `passengerProfileId` is not read here: availability needs a `type`, `age` or `birthDate` """ passengers: [PassengerPlaceholderInput!] """Currency to display availability prices in""" currency: String = "EUR" ): [Journey!]! @deprecated(reason: "Use `journeys` instead") """ Get all possible journeys between origin and destination on given date See: https://docs.allaboard.eu/tickets/ """ journeys( """Origin location""" origin: LocationInput! """Destination location""" destination: LocationInput! """Date of departure""" date: Date! """Optional filter for journey search""" filter: JourneyFilterInput """Optional via stopovers""" via: [ViaInput!] ): [Journey!]! """ This will check live availablity with the train operators and return the given journey with priced offers. Call this when the user has requested prices. See: https://docs.allaboard.eu/tickets/journey-offer """ getJourneyOffer( """Id of Journey to get fares for""" journey: ID! """Passenger details""" passengers: [PassengerPlaceholderInput!]! """Currency to display prices in""" currency: String = "EUR" ): JourneyOffer! @deprecated(reason: "Use `journeyOffer` instead") """ This will check live availablity with the train operators and return the given journey with priced offers. Call this when the user has requested prices. See: https://docs.allaboard.eu/tickets/journey-offer """ journeyOffer( """Id of the Journey to get fares for""" journeyId: ID! """Passenger details""" passengers: [PassengerPlaceholderInput!]! """Currency to display prices in""" currency: String = "EUR" ): JourneyOffer! """ This will check live availablity for an outbound and an inbound journey priced together as a round trip. Where a provider sells true return fares they surface in the matched legs' offers; otherwise prices match two independent journeyOffer calls. See: https://docs.allaboard.eu/tickets/journey-offer """ combinedJourneyOffer( """Id of the outbound Journey to get fares for""" outboundJourneyId: ID! """ Id of the inbound Journey to get fares for, from a search in the opposite direction """ inboundJourneyId: ID! """Passenger details, applying to both directions""" passengers: [PassengerPlaceholderInput!]! """Currency to display prices in""" currency: String = "EUR" ): CombinedJourneyOffer! """ This will return a journey constructed from a predefined Blueprint. Blueprints are created in the Agent Dashboard and can be either a short connection or a multi‑leg trip with overnight stopovers along the way. See: https://docs.allaboard.eu/blueprints/ """ getJourneyForBlueprint( """Blueprint id to get journey for""" blueprint: ID! """Date of departure""" date: Date! ): Journey """ Get applicable pass bundles for the given passengers See: https://docs.allaboard.eu/passes/ """ getPassBundles( """Passenger details""" passengers: [PassPassengerInput!]! """Planned departure date""" departureDate: Date """Optional filter for pass bundles""" filter: PassBundleFilterInput """Currency to display prices in""" currency: String = "EUR" ): [PassBundle!]! """Get applicable pass bundles for given journey offer""" getPassBundlesForJourneyOffer( """Id of journey offer to get pass bundles for""" journeyOffer: ID! """Passenger details""" passengers: [PassPassengerInput!] """Optional filter for pass bundles""" filter: PassBundleFilterInput """Currency to display prices in""" currency: String = "EUR" ): [PassBundle!]! """Get comparative rating for journeys""" getJourneyRatings( """List of journey ids""" journeys: [ID!]! ): [Float!]! """Get fee for issuing tickets""" getTicketingFee( """List of fares to get ticketing fee for""" fares: [ID!] """Id of pass bundle to get ticketing fee for""" passBundle: ID """Currency to display prices in""" currency: String = "EUR" ): Money """ The orders the caller can see, newest first unless `sort` says otherwise, optionally narrowed by `filter`. Cursors are opaque, so do not parse or construct one, and a cursor only continues the list it came from: present it with the same `filter` and `sort`. `totalCount` counts the orders the filter leaves. Pages hold 10 orders by default and 100 at most. """ orders( """Narrows the orders""" filter: OrdersFilter """Cursor to start listing from""" after: String """Cursor to end listing at""" before: String """Number of orders to return (head)""" first: Int """Number of orders to return (tail)""" last: Int """Sort direction for ordering results""" sort: SortDirection = DESC ): OrderConnection! """ Every location we can search and book from, optionally narrowed and ordered by `filter`. Without `filter.query` and `filter.near` the order is ascending on an internal sequence and carries no meaning beyond being stable: it is the order to walk when retrieving all of them. A location that is listed for the whole walk is neither skipped nor repeated, however many are added or withdrawn while it runs. One that joins the list mid-walk is yielded only if it sorts after the cursor reached — and a location that has existed for years can join it, because a location is listed from the day we can sell a journey from it, not from the day the row was created. Repeat the walk to pick those up. With `filter.query` the order is relevance, and with `filter.near` alone it is distance. Those lists are ranked when a page is read, so a location added or withdrawn between two pages can shift the ones after it by a place; they are for finding a location, not for retrieving all of them. Cursors are opaque, so do not parse or construct one, and a cursor only continues the list it came from: present it with the same `filter`. `totalCount` counts the locations the filter leaves. Pages hold 25 locations by default and 100 at most. """ locations( """Narrows the locations and, with a text or a point, orders them""" filter: LocationsFilter """Cursor to start listing from""" after: String """Cursor to end listing at""" before: String """Number of locations to return (head)""" first: Int """Number of locations to return (tail)""" last: Int ): LocationConnection! """ Use this query to get anything that implements the Node interface. It's the recommended way to get entities based on their id. See: https://docs.allaboard.eu/intro/node """ node( """Id of node""" id: ID! """Currency to display prices in""" currency: String = "EUR" ): Node """ Get available travel card options. Returns the list of supported travel cards that can be attached to passengers. Use the returned `code` when constructing `TravelCardInput` and consult `inputFields` to determine which additional data is needed. """ travelCardOptions: [TravelCardOption!]! """Get sales agent details""" getSalesAgent: SalesAgent """ The sales agents the caller has been granted access to act on behalf of, never the caller's own agent. Without `filter.query` the list is in `uid` order. With it, the order is relevance, ranked when a page is read, so a sales agent granted or revoked between two pages can shift the ones after it by a place. Cursors are opaque, so do not parse or construct one, and a cursor only continues the list it came from: present it with the same `filter`. `totalCount` counts the sales agents the filter leaves. Pages hold 25 sales agents by default and 100 at most. """ accessibleSalesAgents( """Narrows the sales agents""" filter: SalesAgentsFilter """Number of sales agents to return""" first: Int """Cursor to start listing from""" after: String ): SalesAgentConnection! """ Passenger profiles the caller may book for, found by `filter.query`: an agency's key reaches the profiles of every company it has access to, a company reaches its own. Requires the `passenger_profiles:read` scope, else `FORBIDDEN`. A caller whose sales agent keeps no profile directory gets `NO_PROFILE_DIRECTORY`; a directory that could not be searched, `UPSTREAM_UNAVAILABLE`. Each page is one read of the directory. Pages hold 25 profiles at most, a larger `first` is read as 25, and a page can hold fewer than asked, or none, while `hasNextPage` is still true (see `PassengerProfileConnection`). Cursors are opaque, so do not parse or construct one, and a cursor only continues the search it came from: present it with the same `filter` and `first`, else `INVALID_ARGUMENT`. """ passengerProfiles( """What to search by; `filter.query` is required.""" filter: PassengerProfilesFilter! """How many profiles to read, 1 to 25; 25 by default, more is read as 25.""" first: Int """ A cursor from a previous page of the same search; the page after it is read. """ after: String ): PassengerProfileConnection! """ Get the authenticated end user. Requires a user token (JWT) in the `Authorization` header. A request without one has no end user and fails with the `USER_TOKEN_MISSING` error code. Note that an `api-key` header takes precedence over `Authorization`, so send only the user token when querying this field. """ me: User """ The sales campaigns available to the authenticated caller, ordered by code. Every code returned is one the caller may sell under, so a client can offer the list as-is. The baseline terms a sale falls back to when no campaign is given are not a campaign to select and are never listed. Campaigns are not named here — a code has no display copy — so pair the codes with your own labels. A campaign runs for a period and drops out of the listing once it ends, so re-read this rather than caching codes indefinitely. A booking already taken under a campaign is unaffected by its ending and can still be completed. Which campaigns are available depends on who the request is authenticated as. An `api-key` header takes precedence over `Authorization`, so send only the user token (JWT) to list what an end user may sell under. """ campaigns: [Campaign!]! """Get a map of places for a given offer and part""" placeMapForPart( """Id of offer""" offerId: ID! """Id of part""" partId: ID! ): PlaceMap """Returns a list of refundable items that can be refunded""" refundableItems( """Id of the order""" orderId: ID! ): [RefundableItem!]! """List all executed refunds for an order""" refunds( """Id of the order""" orderId: ID! ): [Refund!]! } """Supported subscriptions""" type Subscription { """ This will check live availablity with the train operators and return the given journey with priced offers. Call this when the user has requested prices. Journeys will be streamed as the routing algorithm resolves the best routes. See: https://docs.allaboard.eu/tickets/journey-offer """ getJourneys( """Origin location uid""" origin: ID! """Destination location uid""" destination: ID! """Date of departure""" date: Date! """Optional filter for journey search""" filter: JourneyFilterInput """Optional via stopovers""" via: [ViaInput!] """ Passenger details required for availability. `passengerProfileId` is not read here: availability needs a `type`, `age` or `birthDate` """ passengers: [PassengerPlaceholderInput!] """Currency to display availability prices in""" currency: String = "EUR" ): [Journey!]! @deprecated(reason: "Use `journeys` instead") """ Get all possible journeys between origin and destination on given date Journeys will be streamed as the routing algorithm resolves the best routes. See: https://docs.allaboard.eu/tickets/ """ journeys( """Origin location""" origin: LocationInput! """Destination location""" destination: LocationInput! """Date of departure""" date: Date! """Optional filter for journey search""" filter: JourneyFilterInput """Optional via stopovers""" via: [ViaInput!] ): [Journey!]! """ This will check live availablity with the train operators and return the given journey with priced offers. Call this when the user has requested prices. The response is streamed, meaning that as operators return offers for parts of the journey, the result will update with more data for every payload. See: https://docs.allaboard.eu/tickets/journey-offer """ getJourneyOffer( """Id of Journey to get fares for""" journey: ID! """Passenger details""" passengers: [PassengerPlaceholderInput!]! """Currency to display prices in""" currency: String = "EUR" ): JourneyOffer! @deprecated(reason: "Use `journeyOffer` instead") """ This will check live availablity with the train operators and return the given journey with priced offers. Call this when the user has requested prices. The response is streamed, meaning that as operators return offers for parts of the journey, the result will update with more data for every payload. See: https://docs.allaboard.eu/tickets/journey-offer """ journeyOffer( """Id of the Journey to get fares for""" journeyId: ID! """Passenger details""" passengers: [PassengerPlaceholderInput!]! """Currency to display prices in""" currency: String = "EUR" ): JourneyOffer! """ This will check live availablity for an outbound and an inbound journey priced together as a round trip. Where a provider sells true return fares they surface in the matched legs' offers; otherwise prices match two independent journeyOffer calls. The response is streamed, updating as each direction's legs resolve. See: https://docs.allaboard.eu/tickets/journey-offer """ combinedJourneyOffer( """Id of the outbound Journey to get fares for""" outboundJourneyId: ID! """ Id of the inbound Journey to get fares for, from a search in the opposite direction """ inboundJourneyId: ID! """Passenger details, applying to both directions""" passengers: [PassengerPlaceholderInput!]! """Currency to display prices in""" currency: String = "EUR" ): CombinedJourneyOffer! """ This will return a journey constructed from a predefined Blueprint. Blueprints are created in the Agent Dashboard and can be either a short connection or a multi‑leg trip with overnight stopovers along the way. The journey is streamed as the blueprint is being resolved into a journey. See: https://docs.allaboard.eu/blueprints/ """ getJourneyForBlueprint( """Blueprint id to get journey for""" blueprint: ID! """Date of departure""" date: Date! ): Journey } """Supported mutations""" type Mutation { """ Given a journey offer id, this will create a booking with the given journey offer. A booking is a temporary entity that holds the selected offers and passenger details. See: https://docs.allaboard.eu/tickets/book-tickets, https://docs.allaboard.eu/passes/booking """ createBooking( """Ids of offers to add to booking""" offerIds: [ID!] """Id of pass bundle to att to booking""" passBundle: ID """Currency to display prices in""" currency: String = "EUR" """Partner id for tracking""" partnerId: String """Passenger details to add to booking""" passengers: [PassengerPlaceholderInput!] ): Booking! """ Select offers and update passenger details Given a booking id and an offer id, this will select the offer in the booking. This is useful when the user has selected an offer and wants to add it to the booking. Given a booking id and an array of passenger details, this will update the passenger details in the booking. See booking.requirements for required passenger fields. At least one passenger must be marked as the contact person with \`isContactPerson: true\` and \`email\` and \`tel\` must be provided. """ updateBooking( """Id of booking to update""" id: ID! """Passenger details to update""" passengers: [FullPassengerInput!] """Booking selections to update""" selections: [BookingSelectionInput!] ): Booking! """Update an offer part of a booking""" updatePart( """Id of part to update""" id: ID! """Id of booking to update""" booking: ID! """Toggle inclusion of an optional reservation part""" include: Boolean """Place properties to update""" placeProperties: [PlacePropertyInput!] """Ancillaries to add""" addAncillaries: [AddAncillaryInput!] """Ancillaries to remove""" removeAncillaries: [RemoveAncillaryInput!] """Places to select""" placeSelections: [PlaceSelectionInput!] ): Booking! """ Set values of the booking's custom fields, by key. Fields not sent keep their values, and if any field is refused, none is saved. Not allowed once the booking's order is paid or confirmed. """ setCustomFields( """Id of booking to update""" bookingId: ID! """The fields to set, each named by its key""" fields: [CustomFieldInput!]! ): Booking! """ Record how the tickets for one offer should be delivered. Returns the updated offer. Nothing else about the booking changes — no price, no selection, no other field — so there is nothing to refetch beyond the one case below. One call covers the whole offer: every cost center of a multi-cost-center booking, and both halves of a return whose inward direction is priced into the outward fare. That inward half is a separate `Offer` with its own id, and it is the only offer other than the returned one that a call can change, so refetch it through the booking if you are displaying it. Its `selectedOption` takes the same method when that method is among its own `availableOptions`, and is cleared to null when it is not — a linked half is never left holding a delivery its own options do not list. Two separately selected single offers are set separately, even when the operator goes on to deliver them together — in that case it settles one delivery for both at purchase. """ setTicketDelivery( """Id of the offer to set the delivery method for""" offerId: ID! """The method of one of the offer's `ticketDelivery.availableOptions`""" method: TicketDeliveryMethod! ): Offer! """ Initialise payment for an order through All Aboard. The recommended flow is to first create an order with \`createOrder\` and then pass its \`id\` here as \`orderId\`. Once the payment has been succesfully processed, the user will be redirected to the successUrl with the \`{order}\` placeholder replaced by the order id. If the payment is canceled, the user will be redirected to the cancelUrl. For backwards compatibility a \`booking\` may be passed instead of \`orderId\`, in which case an order is created automatically before payment is initialised. See: https://docs.allaboard.eu/payments/ """ createPayment( """Id of the order to pay for (from createOrder)""" orderId: ID """URL to redirect to in the case of payment cancellation""" cancelUrl: String! """URI Template (RFC 6570) compliant string with {order} placeholder""" successUrl: String! """Optional 2-letter language tag used to localise the payment page URL""" language: String = "en" ): Payment! """ This will create an order from a booking. An order is a temporary entity that holds the selected offers and passenger details and prebooks the tickets. It is normally after creating an order that you would collect payment. See: https://docs.allaboard.eu/docs/orders """ createOrder( """Id of booking to confirm""" booking: ID! """JSON encoded string of metadata to attach to order""" metadata: JSONObject ): Order! """ This will finalize an order and start issuing tickets. See: https://docs.allaboard.eu/docs/orders """ finalizeOrder( """Id of order to finalize""" order: ID! ): Order! """Execute refunds for selected refundable items""" refundItems( """Id of the order to refund items from""" orderId: ID! """List of refundable item IDs to refund""" refundableItemIds: [ID!]! ): Refund """ Mint an access token for one order. Returns the token with its secret on `token`, the only time that value is ever readable. Present it in the `api-key` header to read that order, and — with `WRITE` — to refund it and to pay for it by card. Minting is refused with `NOT_AUTHORIZED` unless the caller could itself do everything the token is asked for: reading the order for `READ`, and refunding it and paying for it by card for `WRITE`. A request authenticated by an access token cannot mint another one, so a token's lifetime cannot be extended by minting from behind it. An order that does not exist, and one the caller may not read, both fail with `NOT_FOUND`. Empty `restrictions` fails with `INVALID_RESTRICTIONS`, and a `ttlSeconds` outside 1..86400 with `INVALID_TTL`. """ createAccessToken( """What the token is narrowed to. Must name an order.""" restrictions: AccessTokenRestrictionsInput! """ What the token may do. Omit it for `[READ]`; `[WRITE]` implies `READ`. An explicitly empty list fails with `INVALID_CAPABILITIES`. """ capabilities: [AccessTokenCapability!] = [READ] """How long the token lives, in seconds. 1..86400, default 900.""" ttlSeconds: Int = 900 ): AccessToken! """ Revoke an access token, so it stops authenticating anything immediately. Idempotent: revoking an already-revoked token succeeds and leaves the original `revokedAt` alone, so the trail keeps saying when the credential actually stopped working. Allowed for the agency that minted the token, or any agency above it in the agent tree; anything else fails with `NOT_AUTHORIZED`. An id that names no token fails with `NOT_FOUND`. The returned token carries `token: null` — the secret is unreadable here as everywhere else. """ revokeAccessToken( """The `AccessToken.id` to revoke.""" id: ID! ): AccessToken! }