Payments and allocation
The order engine records every payment and refund, and allocates each one to order lines. From the allocation it answers who paid how much for what: per group, trip, purchase order, line and passenger.
The order engine does not collect money. Payment collection happens in the payment service provider or the payment page, and fiscal documents stay with billing. The channel or integration records the outcome here with the provider's reference in externalRef.
Recording a payment
POST /api/journeys/v1/oms-ops/payments
| Field | Meaning |
|---|---|
kind | payment (default) or refund. |
anchor | Where the money belongs: { level, ref } with level trip, purchase_order or group. |
scenario | The allocation scenario from the tenant's policy, for example deposit, balance, ancillary_purchase, agency_bulk or refund. The scenario decides the allocation method and which anchor levels it allows. |
method | How it was paid, for example card, wallet, bank_transfer. |
payer | { ref, name?, contact?, role }. |
amountMinor, currency | Always positive. The currency must match the lines'. |
receivedAt | When the money was received. Default now. |
externalRef | The payment provider, bank or billing reference. |
idempotencyKey | Business key: a repeat returns the existing payment with status 200. |
allocation | Optional override: method, or manual legs { lineId, amountMinor } when the scenario allows manual allocation. |
refundOf | For a refund, the payment being refunded. |
actor | Who recorded it: { id, name?, role, channel? }. |
The response is the payment with its allocation legs (one per line), allocatedMinor, unallocatedMinor and refundedMinor.
Allocation methods
| Method | How the amount is split across the open balance of the anchor's lines |
|---|---|
sequential | Fills lines in the order of the scenario's product priority (for example the cruise fare before drinks and excursions). |
proportional | In proportion to each line's open balance, with exact rounding (largest remainder). |
rule | The first matching rule of the policy decides, for example agency bulk payments filling accommodation first. |
manual | The legs given in the request. |
Money above the open balance follows the policy's overpayment setting: hold_unallocated keeps it on the payment as unallocated, reject refuses the payment with 422 overpayment.
The allocation policy (scenarios, rules, overpayment handling, re-allocation on change) is versioned tenant configuration. GET /order-orchestration/payment-rules shows the payment rules and POST /order-orchestration/payment-rules/test simulates a split without writing anything.
Refunds
A refund is a payment record with kind: refund, a positive amountMinor and refundOf naming the original payment. It reverses the original payment's legs (unallocated money first, then its line legs proportionally), written as negative legs with reason refund. A refund cannot exceed what is left of the original payment (422 refund_exceeds_payment).
Refunds are also created for you:
- applying a change refunds the money the remaining lines no longer need, to the payments it came from;
- a guest choosing a refund in a mass change cancels the lines and publishes
oms.refund.requested.
Every refund publishes oms.payment.recorded and oms.payment.allocated. Refunds created by changes and mass changes also publish oms.refund.requested, which the payment owner acts on to pay the money out. A refund recorded directly with POST /oms-ops/payments records money already paid back, so it does not publish oms.refund.requested.
Re-allocation
When lines change (a cabin is cancelled, a price changes), allocation is re-run for the affected scope if the policy has reallocateOnChange, or on request with POST /oms-ops/balances/{level}/{ref}/reallocate. Re-allocation releases legs and applies new ones as compensating entries (reallocate_release, reallocate_apply) under a runId. Nothing is overwritten: the ledger is append-only, so the allocation at any point can be reconstructed.
Balances
| Read | Call |
|---|---|
| A balance with its purchase orders, trips and lines | GET /oms-ops/balances/{level}/{ref} |
Payments at a scope (and below with within=true) | GET /oms-ops/balances/{level}/{ref}/payments |
| One payment and its legs | GET /oms-ops/payments/{paymentId} |
A balance gives amountMinor, paidMinor, openMinor, unallocatedMinor and a status: unpaid, partially_paid, paid, refunded or no_charge.
Passenger-level balances
Allocation is to order lines. Each line is split into passenger units: one per passenger on the line (passengerIds), by the explicit passenger shares a change recorded, or equally otherwise. From the units the order engine answers per passenger:
| Read | Call |
|---|---|
| The balance per passenger, with the fee and refund each would get if cancelled as of a date | GET /oms-ops/balances/{level}/{ref}/passengers?asOf= |
| A payment's legs split to passengers | GET /oms-ops/payments/{paymentId}/passengers |
A payment cannot be allocated directly to a passenger. Passenger figures are derived from line allocation. To direct money to one passenger's products, anchor the payment at the purchase order or use manual legs on that passenger's lines. See Availability.
See the end-to-end example and the reference for Payments and allocation.