Payment flow
Norba never holds your money or your traveller’s. You charge the traveller, then pay the airline its own price with your card through the API.
| Who pays whom | What | When |
|---|---|---|
| Traveller → you | Airline price + your markup, on your own checkout. | At your checkout |
| You → airline | Airline price only, on your card, sent through the API. | POST /v1/orders, or later on a hold |
| You → Norba | Our fees. See Pricing and Billing. | Monthly, in arrears |
payment.amount
- Send the total you charged, with at most two decimals. It must cover the airline’s price for the offer plus the seats and extras booked in the same call.
- Anything above that is your markup. The airline is charged its own price only.
payment.currencymust be the airline’s currency for the offer. Leave it out to use it.- Price the offer with
POST /v1/offers/priceno more than 30 minutes before paying for it; otherwise409 offer_not_priced.
| You send | Airline is charged | Result |
|---|---|---|
| 550.00 | 500.00 | Booked. You keep the 50.00 markup. |
| 500.00 | 500.00 | Booked, no markup. |
| 499.98 | — | 400: below the airline's price (one cent is tolerated for rounding). |
Optional: set your markup as a rule on Commissions and it is priced into the offer and shown as service_fee on the order.
The card
Card payments only, in sandbox and production. Cash, BSP (Billing and Settlement Plan), invoice and transfer are never accepted: a payment without a card is refused with 400 payment_method_not_allowed. payment.method can be left out.
| payment.card | Rule |
|---|---|
| brand | Optional, e.g. AMEX, MC, VISA. |
| cvv | Optional. 3 or 4 digits. |
| expiry_month | Required. 1–12. |
| expiry_year | Required. Four digits, not in the past. |
| holder | Required. |
| number | Required. 12 to 19 digits, digits only. |
A malformed card is refused with 400 naming the field. The card is passed to the airline and never stored.
Holds and paying later
- Send no amount and no card and the order is an unpaid hold until
expires_at. - Pay it with
POST /v1/orders/{orderID}/commit, carrying the samepaymentobject. - The amount must cover the airline’s share (the order total minus your
service_fee), in the order’s currency. - An order is paid once: paying it again answers
409 already_paidand nothing is charged. - Every call that pays needs an
Idempotency-Keyheader, reused on every retry. Without it:400 idempotency_key_required.
The hold lifecycle is on Orders Lifecycle; paying for seats, extras or a change on Servicing.
3-D Secure
Norba does not authenticate cardholders. If an airline requires 3-D Secure, authenticate the card yourself and send the result in payment.authentication.
- An airline that cannot take it answers
422: omit the block for that airline. - Only with a
card. A bad block is refused with400naming the field. version"1"or"2";authentication_valuerequired;ecitwo digits;transaction_statusone ofA C N R U Y.- Version 2 needs
ds_transaction_id; version 1 needsxid.
{
"payment": {
"currency": "EUR",
"amount": 550.00,
"card": {
"number": "4111111111111111",
"holder": "Acme Travel SL",
"expiry_month": 11,
"expiry_year": 2030
},
"authentication": {
"version": "2",
"authentication_value": "AAACBhZHkQICA0kAMkeREMAAAgE=",
"eci": "05",
"transaction_status": "Y",
"ds_transaction_id": "9682ed54-9bba-4f33-8e44-0f6f9dfdc9f2"
}
}
}When the answer is lost
201withX-Norba-Payment-Outcome: unknown: the order exists but the payment result is not known yet. Do not pay it again. Payment calls on it answer409 booking_outcome_unknownuntil it is resolved; quoteX-Norba-Attempt-Idto support.502 booking_outcome_unknown: the booking reached the airline. Do not resend it; read the order back.
All codes are on Errors.
Paid is not ticketed
A ticket exists only when the order is ticketed and tickets[] has an entry. Until then, do not confirm the trip to the traveller. Statuses are on Orders Lifecycle.
Refunds
The airline refunds the fare, less any penalty, to the card it charged. Refunding your traveller is up to you. Calls are on Servicing.