Refund lifecycle & statuses

Every status a refund can take, what coupon statuses mean, how decisions are made, and how to track a refund to its final outcome — so you never have to discover a state by testing.

1. The lifecycle at a glance

  1. QuotecreateQuote reads the ticket from the airline system (GDS/PSS), applies refundability rules, and produces a refund candidate with amounts and a decision.
  2. AcceptanceprocessRefund submits the candidate. A successful response means accepted and queued, not done.
  3. Execution — the fulfillment engine performs the refund in the GDS/PSS and writes a terminal status: REFUNDED or ERROR.
📘

"Queued for processing" is an acknowledgment, not an outcome. The final result arrives later — track it with webhooks or polling (section 5).

2. Refund candidate statuses

StatusMeaningTerminal?Set by
NEWCreated from a quote, not yet actionableNoEngine
READYApproved; fulfillment will pick it upNoClient or rules
REVIEWHeld for manual reviewNoClient or rules
SKIPExcluded from processingEffectivelyClient or rules
REFUNDEDExecuted successfully in the airline systemYesEngine only
ERRORExecution failed after acceptanceYesEngine only
  • REFUNDED and ERROR are written only by the fulfillment engine. Clients can move a candidate to READY, REVIEW, or SKIP — never to a terminal state.
  • Terminal statuses never transition again. Retrying the same ticket doesn't change them.
  • ERROR carries the failure detail in its error history; contact support with the ticket number if it isn't actionable on your side.

3. Coupon statuses

Each flight segment has a coupon with a status in the airline system; refundability is evaluated per coupon.

3.1 Status reference

Deal Engine normalizes Amadeus web-service codes to standard one-letter ("cryptic") codes. The API returns the normalized code.

Raw (GDS/PSS)API returnsMeaning
IOOpen for use (unused)
OKOKConfirmed, unused
ALAAirport control
CKCChecked in
BDLBoarded / lifted
BFFlown / used
EEExchanged / reissued
RFRRefunded
PRPPrinted
PEXPrint exchange
IOOIrregular operations
NAVUNot available
CLO / ZZClosed
QQRevoked by the airline
SSSuspended
VVVoid
YYRefund taxes/fees only
📘

Unrecognized codes pass through unchanged. If you receive a code you can't interpret, treat the coupon as not refundable and contact support.

3.2 Which statuses are refundable?

Refundability checks each coupon against a configured non-refundable status list. Default:

CLO, RF, 1, B, C, E, F, G, L, N, P, Q, R, T, U, V, X, Y, Z

Everything else — open coupons (O, I, OK, A, AL) — is refundable. E (exchanged) routes through reissue-chain handling; U/NAV trigger deeper fare-rule evaluation.

🚧

Fully configurable. These lists — like nearly every rule on this page — are configured per customer, market, and rule set. The values above are defaults; your configuration agreed with Deal Engine is the source of truth.

3.3 UAT note

Fulfillment is not available in sandbox, so refunds never reach REFUNDED there and coupon statuses don't change. See Testing & environments.

4. Refund decisions

4.1 Decision values

Not a fixed enum — configured per customer and flow. Standard values:

ValueMeaning
VOLUNTARYPassenger-initiated, under fare rules
INVOLUNTARYAirline-caused (cancellation, schedule change) — typically penalty-free
IRREGULAR OPERATIONSOperational disruption
VOLUNTARY MILESMiles-paid ticket — only monetary taxes quoted (see Refund amounts)
REJECTEDRefused by a configured rejection rule (4.2)

Your configuration may add variants (e.g. VOLUNTARY_BEFORE_DEPARTURE) or informational reasons (No open coupons found). Deal Engine provides your active list at onboarding.

4.2 When is a refund REJECTED?

Rejections are fully configurable per customer — rejection rules follow your business logic and are set up on demand with Deal Engine. There are no hidden rejection paths: a refund is rejected only when one of your configured rules matches. Example rule:

Reject when a coupon is fail-to-board (U) and the penalty exceeds remaining fare + fuel surcharge (YR) — the refund would be zero or negative.

How a rejection surfaces depends on your configuration:

  • Default (no explicit rejection configuration): the rejection is written to the refund's notes and the quote returns 0 amount to be refunded.
  • Explicit rejection status (on request): a dedicated REJECTED status is added to your quotation statuses, so integrations can branch on the quote status directly instead of inspecting notes and amounts.

Ask Deal Engine to enable the explicit REJECTED quotation status if your integration needs a machine-checkable rejection signal.

4.3 Decision-to-action matrix

DecisionMeaningAction
VOLUNTARY / INVOLUNTARY / IRREGULAR OPERATIONSRefundableProceed with processRefund or your approval flow
VOLUNTARY MILESTaxes-only refundableProceed if tax refund desired; miles reinstated outside Deal Engine
REJECTEDRefused by your configured rules — detected via notes + 0 refund amount, or via the explicit REJECTED quote status if enabled. Retrying returns the same resultDon't auto-retry. Route to manual review/support with the note text
Quote ERRORQuote failed (system/GDS/PSS)Retry with backoff; contact support if persistent

5. Tracking a refund to completion

5.1 Webhooks (recommended)

  • refund_request.status_updated — quote-stage progress
  • refund_candidate.status_updated — candidate changes, including both terminal outcomes

Configured per client and environment — see the Webhooks guide for payloads and setup.

5.2 Polling

Poll unifiedRefund.status or the candidate status every 30–60 seconds (execution can take up to ~2 minutes; faster polling adds nothing). Stop at REFUNDED/ERROR. The authoritative final record — including the executed amount — is Document.refund / unifiedRefund; see Refund amounts & reconciliation.

5.3 Failure after acceptance

Failed execution ends in ERROR (+ webhook if configured). Transient GDS/PSS failures are retried internally (2 retries on network errors) before ERROR; business refusals are never retried.

A candidate that was safe to submit can still fail at execution (GDS/PSS outage, document changed since quoting). Treat REFUNDED — not the acceptance response — as confirmation.


Did this page help you?