3. API usage & integration
3.1 Which GraphQL calls handle creating, updating, and cancelling refunds?
- Create:
createQuote(request: [quoteRequest]!, isRequote?: Boolean, fetchFromGDS?: Boolean)
- Update:
updateQuote(request: quoteUpdateRequest!, requote?: Boolean)
- Cancel:
cancelQuote(ticketNum: String!): Boolean
3.2 What are the required vs. optional fields?
3.2.1 CreateQuote:
mutation CreateQuote($request: [quoteRequest]!) {
createQuote(request: $request)
}
Minimal variables:
{
"request": [{ "ticketNum": "1282132019309" }]
}
Optional fields in quoteRequest include:
- pnr: is a digital record of a passengers booking: flights, details, and services.
- gds: is global network that distributes travel inventory and enables real-time booking.
- agent: is the user or system that books travel through a GDS.
- issueDate: the tickets creations date.
- refundRequestDate: date refund was requested.
- refundRequestedAt: timestamp when the refund request was logged in the system.
- waiver: exception granted by the airline that overrides normal rules or penalties.
- freeText: is an open field booking or ticket where agents can add notes or special instruction.
- isEmd: stands for individual security electronic miscellaneous document used for security services.
- metadata: data that describes other data.
- iataCode: is the 2-3 letter identifier asign by IATA to airlines and airports.
- clientData: is stored information about a customer, like name, contacts, and preferences (customer information record).
Example using more variables:
{
"request": [
{
"ticketNum": "0192382929393",
"gds": "sabre",
"iataCode": "10839203"
}
]
}
Using the Sync header
When you send a quote, you can control the response behavior using the Sync header.
- No Sync header / Sync = false → Immediate response, confirmation of sending, processing occurs later.
{
"data": {
"createQuote": true
}
}
- With Sync header = true → Later response, but with the full quote result.
{
"data": {
"createQuote": [
{
"decision": "VOLUNTARY",
"refundCandidate": {
"ticketId": 464159578,
"status": "REVIEW",
"isAdminFeeApplicable": true,
"refundableBaseFareAmount": 460,
"refundAmount": 487.14,
"refundCurrencyCode": "EUR",
"refundFareAmount": 460,
"refundTaxAmount": 87.14,
"refundPenaltyAmount": 60,
"refundType": "FULL FARE REFUND",
"isGuaranteedRefund": false,
"overrideRefundRoute": "GDS",
"product": "ARP",
"isVoluntaryRefund": true,
"waiverForceFareRefundWithoutPenalty": true,
"overrideTaxCalculations": false,
"shouldCancelItinerary": false,
"extraParams": {
"currentDate": 1759443208259,
"refundReason": "VOLUNTARY",
"refundability": {
"decision": [],
"buildSegments": true,
"fetchFareRules": true,
"invokeRudder": true,
"involuntary": false,
"reason": "VOLUNTARY",
"refundable": true,
"refundPartialSegments": false,
"roundDigits": 2,
"usdot": false,
"useFareRules": true
},
"fareBreakdown": {
"totalPaidFare": 460,
"openFare": 460,
"usedFare": 0,
"nonRefundableFare": 0,
"refundableFare": 460,
"totalPenaltyAmount": 60
},
"penaltyBreakdown": {
"currency_code": "EUR",
"fare_rules": 60,
"non_refundable_fare": 0,
"fixed_fees": 0,
"vat_fees": 0,
"admin_fees": 0,
"historical_pricing_fee": 0
},
"segments": [
{
"segmentIdx": 1,
"couponIdxs": [
1
],
"couponStatuses": [
"OPEN"
],
"segmentStatus": "OPEN",
"origin": "PAR",
"destination": "BUH",
"stopovers": [],
"originCountry": "FR",
"destinationCountry": "RO",
"stopoversCountries": [],
"departedAt": "2025-09-20T12:00:00.000Z",
"fareBasis": "IOWSFXFR",
"fare": 459.99549596,
"surcharge": 0,
"currencyCode": "EUR",
"marketingAirlineCode": "RO",
"penalties": [],
"extraParams": {
"roe": "0.883723",
"isNoShow": false,
"currencyExchangeDetails": {
"input": {
"amount": 520.52,
"currencyCode": "NUC"
},
"output": {
"amount": 459.99549596,
"currencyCode": "EUR"
},
"rate": 0.883723,
"date": "2025-06-13",
"source": "gds"
},
"currencyExchange": {
"amount": 459.99549596,
"currencyCode": "EUR"
},
"originalCurrencyExchange": {
"amount": 520.52,
"currencyCode": "NUC"
}
}
}
],
"reissue": false,
"lineageCount": 0,
"flightType": "INTERNATIONAL",
"safeBadge": true,
"autogenNotes": ""
},
"notes": ""
},
"refundCandidateCoupons": [
{
"couponIdx": 1,
"fare": 459.99549596,
"currencyCode": "EUR",
"extraParams": {
"isOpen": true,
"iataAreaOrigin": "2",
"countryOfOrigin": "FR",
"currencyExchange": {
"amount": 459.99549596,
"currencyCode": "EUR"
},
"countryAreaOrigin": "EUROPE",
"alternativeOrigins": [
"CDG",
"PAR"
],
"cityIataCodeOrigin": "PAR",
"countryOfOriginName": "France",
"iataAreaDestination": "2",
"countryOfDestination": "RO",
"countryAreaDestination": "EUROPE",
"alternativeDestinations": [
"OTP",
"BUH"
],
"cityIataCodeDestination": "BUH",
"currencyExchangeDetails": {
"input": {
"amount": 520.52,
"currencyCode": "NUC"
},
"output": {
"amount": 459.99549596,
"currencyCode": "EUR"
},
"rate": 0.883723,
"date": "2025-06-13",
"source": "gds"
},
"countryOfDestinationName": "Romania",
"originalCurrencyExchange": {
"amount": 520.52,
"currencyCode": "NUC"
}
}
}
],
"refundCandidateTaxes": [
{
"taxCode": "YQ",
"segmentIdx": 1,
"couponIdx": 1,
"status": "OPEN",
"segmentStatus": "OPEN",
"segmentIsRefundable": true,
"amount": 25,
"currencyCode": "EUR",
"remittance": "fare complement",
"isValid": true,
"willRefund": true,
"isRefundable": true,
"isOpen": true,
"extraParams": {
"originalRemit": "fare complement"
}
},
{
"taxCode": "FR",
"segmentIdx": 1,
"couponIdx": 1,
"status": "OPEN",
"segmentStatus": "OPEN",
"segmentIsRefundable": true,
"amount": 18.19,
"currencyCode": "EUR",
"remittance": "transporting",
"isValid": true,
"willRefund": true,
"isRefundable": true,
"isOpen": true,
"extraParams": {
"explanation": {
"source": "RUDDER_TS",
"adjustments": [
{
"type": "AMOUNT_RECONCILIATION",
"reason": "Adjusted to match input sums"
}
],
"ruleId": "48398136",
"segmentIdxAtSource": 1,
"couponIdxAtSource": 1
},
"originalRemit": "transporting"
}
},
{
"taxCode": "O4",
"segmentIdx": 1,
"couponIdx": 1,
"status": "OPEN",
"segmentStatus": "OPEN",
"segmentIsRefundable": true,
"amount": 30,
"currencyCode": "EUR",
"remittance": "transporting",
"isValid": true,
"willRefund": true,
"isRefundable": true,
"isOpen": true,
"extraParams": {
"explanation": {
"source": "RUDDER_TS",
"adjustments": [
{
"type": "AMOUNT_RECONCILIATION",
"reason": "Adjusted to match input sums"
}
],
"ruleId": "44474192",
"segmentIdxAtSource": 1,
"couponIdxAtSource": 1
},
"originalRemit": "transporting"
}
},
{
"taxCode": "QX",
"segmentIdx": 1,
"couponIdx": 1,
"status": "OPEN",
"segmentStatus": "OPEN",
"segmentIsRefundable": true,
"amount": 13.95,
"currencyCode": "EUR",
"remittance": "transporting",
"isValid": true,
"willRefund": true,
"isRefundable": true,
"isOpen": true,
"extraParams": {
"explanation": {
"source": "RUDDER_TS",
"adjustments": [
{
"type": "AMOUNT_RECONCILIATION",
"reason": "Adjusted to match input sums"
}
],
"ruleId": "49169923",
"segmentIdxAtSource": 1,
"couponIdxAtSource": 1
},
"originalRemit": "transporting"
}
}
],
"refundCandidateFulfillment": {
"totalFare": 460,
"usedFare": 0,
"nonRefundableFare": 0,
"fareToRefund": 460,
"totalTaxes": 87.14,
"usedTaxes": 0,
"nonRefundableTaxes": 0,
"taxesToRefund": 87.14,
"fareRulePenalty": 60,
"vatOnPenalty": 0,
"serviceFee": 0,
"totalPenalties": 60,
"totalRefundAmount": 487.14,
"currency": "EUR"
},
"refundability": {
"decision": [],
"buildSegments": true,
"fetchFareRules": true,
"invokeRudder": true,
"involuntary": false,
"reason": "VOLUNTARY",
"refundable": true,
"refundPartialSegments": false,
"roundDigits": 2,
"usdot": false,
"useFareRules": true
},
"isSafeForRefund": true
}
]
}
}
3.2.2 UpdateQuote:
This mutation is used to update an existing quote with new request parameters.
mutation UpdateQuote($request: quoteUpdateRequest!, $requote: Boolean) {
updateQuote(request: $request, requote: $requote)
}
Minimal variables:
{
"request": { "ticketNum": "1282132019309" }
}
quoteUpdateRequest supports many updatable fields using { from, to }
envelopes (e.g., waiver, freeText, clientVisibility, fulfillment, taxes, etc.).
Updating the waiver of a quote
- null → value or value → null: send requote: true.
{
"request": {
"ticketNum": "1282132019309",
"waiver": { "from": null, "to": "Sample Waiver" }
},
"requote": true
}
- value → different value: requote can be omitted or false.
{
"request": {
"ticketNum": "1282132019309",
"waiver": { "from": "Old", "to": "New" }
},
"requote": false
}
- no change (both null): omit requote or false.
3.2.3 CancelQuote:
mutation CancelQuote($ticketNum: String!) {
cancelQuote(ticketNum: $ticketNum)
}
Variables:
{ "ticketNum": "1282132019309" }
3.3 How do I paginate or filter results?
For filtering use filter inputs decorated with @filter-enabled fields. Operators include equality and generated variants _like _not, _in, _contains, _lt/_lte/_gt/gte, etc. You can also combine with AND/OR.
Example (roles where name contains "admin"):
query Roles($limit: Int, $offset: Int, $roleFilter: RoleFilter) {
roles(limit: $limit, offset: $offset, roleFilter: $roleFilter) {
edges {
node {
id
name
description
}
}
pageInfo {
total
perPage
totalPages
hasNextPage
hasPreviousPage
}
}
}
Variables:
{ "limit": 10, "offset": 0, "roleFilter": { "name_contains": "admin" } }
For pagination (limit & offset), fields annotated with @paginate accept limit and offset and return
{
edges {
cursor
node
},
pageInfo {
total
perPage
totalPages
hasNextPage
hasPreviousPage
}
}
Defaults: limit 10, offset 0.
Example (second page of roles):
{ "limit": 10, "offset": 10, "roleFilter": {} }
3.4 Do you support idempotent operations to prevent duplicates?
Yes. When a new record is created for a ticket/order, it is marked as the current active record and any previous current is unset, ensuring a single active record.
3.5 How do I request a refund?
-
Step 1: Make sure you have a quote for the ticket in question.
-
Step 2: In GraphQL, run the processRefund mutation.
mutation ProcessRefund($input: [processFulfillmentRequest]) { processRefund(input: $input) }
Minimal variables:
{ "input": [ { "fulfillmentRequest": { "ticketNum": "1739240193092" } } ] }
You can submit one or multiple refund requests in a single call.
{ "input": [ { "fulfillmentRequest": { "ticketNum": "1739240193923" } }, { "fulfillmentRequest": { "ticketNum": "1739240193092" } } ] }
Optional fields: gds, iata, and issueDate. If you don’t know them, you can omit them (they’ll be filled in from the ticket number when possible).
{ "input": [ { "fulfillmentRequest": { "ticketNum": "1739240193923", "issueDate": null, "forceCashFopInBSP": null, "isEmd": null, "pnr": null, "refundMode": null, "testingMode": null }, "gds": null, "iata": null } ] }
On success, you’ll receive a per-ticket summary for each submitted ticket.
All tickets successfully enqueued for processing.
{ "data": { "processRefund": { "success": true, "message": "All documents processed successfully", "results": [ { "ticketNum": "1739240193923", "success": true, "message": "Queued for processing" } ] } } }
Partial success.
{ "data": { "processRefund": { "success": false, "message": "Some documents processed; see results", "results": [ { "ticketNum": "23260543607", "success": false, "message": "Invalid ticket num" }, { "ticketNum": "0722989792111", "success": true, "message": "Queued for processing" } ] } } }
No tickets were enqueued for processing.
{ "data": { "processRefund": { "success": false, "message": "No valid requests to process", "results": [ { "ticketNum": "23260543607", "success": false, "message": "Invalid ticket num" }, { "ticketNum": "07229897111", "success": false, "message": "Invalid ticket num" } ] } } }
-
Step 3: Your refund request is complete; the status should be visible in a few seconds.
3.6 How do I search the refund details?
Once your refund request has been created, you can verify and review its information using the following query.
This query allows you to retrieve the details of a specific refund — including its status, associated files, and request metadata. You can also extend the query to include additional related data as needed, depending on your integration or data requirements.
query SearchRefundDetails($filter: DocumentFilter) {
documents(filter: $filter) {
edges {
node {
ticketNum
iataCode
commissionPercent
quote {
product
refundRoute
taxInfo {
code
refundAmount {
quantity
currencyCode
}
}
}
unifiedRefund {
via
requestDate
authorizationDate
fopType
totalRefund
totalFare
totalTax
totalPenalty
currencyCode
document
status
rejectionDate
updatedDate
settlementPeriod
}
}
}
}
}
Updated 11 days ago