“Pay with Platnova” is not yet available for travel (
422 payment_method_not_available).403 partner_product_disabled. If the service is unavailable, routes answer 503 travel_unavailable.
How a booking works
- Search.
POST /v1/partner/travel/flights/searchreturns offers. - Quote.
POST /v1/partner/travel/flights/quotewith{ "offer_id", "currency": "NGN" }returns the price you pay, fee included, asamount_minor, along withexpires_at. - Book.
POST /v1/partner/travel/orderswith that exactamount_minor. Your wallet is debited at once and the answer is202, with the orderprocessing. - Wait for the outcome. You receive the
travel.order.confirmedwebhook with the booking reference (PNR), or you can pollGET /v1/partner/travel/orders/{partner_reference}.
100000 is ₦1,000.00.
A travel partner_reference is stricter than other partner references: 1 to 64 letters, digits, ., _ or -, and never ... Anything else is refused with 422 partner_reference_invalid.
Search
POST /v1/partner/travel/flights/search
offers, each with an id and its slices and passengers (the passenger ids you book with). Prices in the search are the airline’s own. Always quote an offer before booking it.
Quote
POST /v1/partner/travel/flights/quote
fee_minor, included in amount_minor) must cover the airline’s fare, the booking provider’s order fee, the exchange cost and a minimum margin. When the normal fee falls short, the fee is raised and cost_floor_applied: true appears; otherwise the field is left out. The fare itself is never changed. If the cost can’t be worked out, the offer is refused as offer_unavailable, never sold at a guess.
Book with exactly the quoted amount_minor. The order is priced the same way, so a quote and its order agree.
Book
POST /v1/partner/travel/orders (needs an Idempotency-Key)
- Infants travel on an adult’s lap: put the infant’s passenger id in that adult’s
infant_passenger_id. payment.methodis one of:wallet: your default wallet incurrencyis debited.checkout: sendpayment.checkout_idas well. The checkout must be one of yours, already paid, in the same currency, and for at leastamount_minorless anything refunded from it. A checkout pays for one booking only. Your wallet is debited the booking amount; the checkout’s payment is what funded it.
The answer
Before any money moves, these are refused:
The order object:
status moves through:
submitting, thenprocessing, thenbooked- or
failed(refunded in full) - or
cancelled(refunded what the airline returns) - or
attention: something unexpected happened and a Platnova person is looking at it. Your money is held, not lost, and we contact you.
Hotels (stays)
A stay follows the same steps and the same order routes as a flight: search, quote, book withPOST /v1/partner/travel/orders, then read, cancel and receive webhooks by partner_reference.
Search
POST /v1/partner/travel/stays/search
results, each a property with a search result id, its accommodation (name, address, photos, rating, amenities) and its cheapest rate. With currency, each result also carries cheapest_amount_minor: an indicative price in your currency, fee included. The quote is the price you pay.
Rates
POST /v1/partner/travel/stays/rates with { "search_result_id": "ssr_…" } returns every room and rate for that property. Each rate has an id, its cancellation_timeline and its conditions. Prices there are the property’s own; quote a rate for yours.
Quote
POST /v1/partner/travel/stays/quote
- A quote is yours alone and lasts until
expires_at(two hours). Book it before then. due_at_accommodation_amount, when present, is paid by the guest at the property, in its own currency. It is not inamount_minor. Tell your guest.cancellation_timelineis the refund if the booking is cancelled before eachbefore, in your currency, at the price you pay now. Our booking fee is never refunded. An empty timeline means the room is non-refundable.
Book
POST /v1/partner/travel/orders (needs an Idempotency-Key)
quote_id, at least one guest, email and phone_number, and takes no offer_id or passengers. payment works as for flights. The answers are the flight answers, plus:
booking_reference on the order and on travel.order.confirmed is the property’s confirmation code.
Cancel a stay
The same two calls as a flight. The refund comes from the quote’scancellation_timeline: the best step whose before is still more than five minutes away.
- The cancellation quote’s
expires_atis when that step runs out, or 15 minutes, whichever is sooner. - Confirming after it answers
409cancellation_expired. Ask for a new quote. 202cancellation_pendingmeans the property has not answered yet. Send the same call again.
Cancel a booking
-
POST /v1/partner/travel/orders/{partner_reference}/cancellation-quotetells you what comes back:For a flight, the refund is the airline’s refund at the rate you booked at. Our booking fee is not returned. A refund that the airline makes as credit or a voucher, or in another currency, shows as0. -
POST /v1/partner/travel/orders/{partner_reference}/cancellationwith{ "cancellation_id": "ore_…" }(needs anIdempotency-Key) confirms it. The answer is the cancelled order, andrefund_minoris already in your wallet.202cancellation_pending: the airline has not answered yet. Send the same call again shortly.409cancellation_mismatch: the id is not your latest quote.409travel_order_not_cancellable: only a booked order can be cancelled.
Webhooks
Subscribe totravel.order.*. Each event carries the order:
details holds, on confirmed, the airline order with its e-tickets, and on failed and cancelled, the reason and the refund.
data.product is flight or stay. Each order is refunded at most once, however many times an event is delivered.
