Skip to main content
You search and price flights and hotel stays through Platnova, then book them. Each booking is paid from your NGN business wallet, or from a checkout your customer has already paid. If a booking cannot be completed, the money goes back to your wallet automatically.
“Pay with Platnova” is not yet available for travel (422 payment_method_not_available).
Travel must be enabled for your business. Until it is, every travel route answers 403 partner_product_disabled. If the service is unavailable, routes answer 503 travel_unavailable.

How a booking works

  1. Search. POST /v1/partner/travel/flights/search returns offers.
  2. Quote. POST /v1/partner/travel/flights/quote with { "offer_id", "currency": "NGN" } returns the price you pay, fee included, as amount_minor, along with expires_at.
  3. Book. POST /v1/partner/travel/orders with that exact amount_minor. Your wallet is debited at once and the answer is 202, with the order processing.
  4. Wait for the outcome. You receive the travel.order.confirmed webhook with the booking reference (PNR), or you can poll GET /v1/partner/travel/orders/{partner_reference}.
All amounts are integers in minor units (kobo for NGN). 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. POST /v1/partner/travel/flights/search
The answer is the offer request: its 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
A booking is never priced below what it costs Platnova. The quote’s fee (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.method is one of:
    • wallet: your default wallet in currency is debited.
    • checkout: send payment.checkout_id as well. The checkout must be one of yours, already paid, in the same currency, and for at least amount_minor less 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, then processing, then booked
  • 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 with POST /v1/partner/travel/orders, then read, cancel and receive webhooks by partner_reference.

Search

POST /v1/partner/travel/stays/search
The answer lists 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 in amount_minor. Tell your guest.
  • cancellation_timeline is the refund if the booking is cancelled before each before, 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)
A stay needs 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’s cancellation_timeline: the best step whose before is still more than five minutes away.
  • The cancellation quote’s expires_at is when that step runs out, or 15 minutes, whichever is sooner.
  • Confirming after it answers 409 cancellation_expired. Ask for a new quote.
  • 202 cancellation_pending means the property has not answered yet. Send the same call again.

Cancel a booking

  1. POST /v1/partner/travel/orders/{partner_reference}/cancellation-quote tells 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 as 0.
  2. POST /v1/partner/travel/orders/{partner_reference}/cancellation with { "cancellation_id": "ore_…" } (needs an Idempotency-Key) confirms it. The answer is the cancelled order, and refund_minor is already in your wallet.
    • 202 cancellation_pending: the airline has not answered yet. Send the same call again shortly.
    • 409 cancellation_mismatch: the id is not your latest quote.
    • 409 travel_order_not_cancellable: only a booked order can be cancelled.

Webhooks

Subscribe to travel.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.