Kiwi.com booking API

There are only few basic calls needed to implement the booking API:

  • check_flights for verifying the price received in the search results

  • save_booking for requesting the booking of the tickets. This call opens the booking and returns a booking ID in the response. The system is waiting then for the payment confirmation in the 3rd call

  • tokenize only for Zooz payments, used to encrypt sensitive payment data.

  • confirm_payment is used for confirmation of a successful payment from the user.

Workflow is simple :

  1. search_flight function looks for given flights/journeys

  2. check_flights confirms the price of found flights. It has 2 important parameters - flights_checked (which has to return True) and flights_invalid which has to be False. If the previous is met, the flight is bookable and we can move on to save_booking.

  3. save_booking initiates the booking on our backend. The response is similar to a response from check_flights, but it has more parameters.

  4. confirm_payment confirms that the user payment was successful.

For all requests against our API please always use proper content type in headers: Content-Type: application/json.

Please use booking token you receive in /flights response to prevent errors during booking process.

Date and time format: all parameters that require time or date are in Unix time format.

The responses are G-zipped and need to be unpacked (response header Content-Encoding: gzip).

Testing (sandbox mode):

  • Testing booking can be created by using value test as both name and surname of the first passenger.

  • No real transaction is made in sandbox mode - no real credits are used and no credit cards are needed.

  • When trying to make sandbox booking with Zooz payment, do not forget to set the environment to test.

Please attach an example request-response when contacting our API team.

Resource Group

Booking API Root

This resource does not have any attributes. Instead, it offers the initial API affordances in the form of the links in the JSON body.

It is recommended to follow the “url” link values, Link or Location headers where applicable to retrieve resources. Instead of constructing your own URLs, to keep your client decoupled from implementation details.

Check flights

Resources related to questions in the API.

Check_flights

Endpoint: https://booking-api.skypicker.com/api/v0.1/check_flights?

Can be called more times than just once.

GET https://booking-api.skypicker.com/api/v0.1/check_flights?v=2&booking_token=TjFsU9KOyjpEDqm5dNSrO1ZjuRMVMgZrERrSppD325T6P8+P9w468E+3gYirNKm0xjFEaQ8brFkJXYHcFnHHQP5fINbkDjCTreeWig4WZ7B4fBYYSUgmpu0Cq8+F75sB1L9aQ+cDGm5LObGbRYN0pwUDk5LuVOHkDPT1Qmo6XhmrtXw4mLqlylxVlpY+8jS2/eBYqLA7CPIQyfcUqPhx/F26+QR/TnuLRGUvd7cpYS88pyKmqcUiqIMz9FvuwQTxaTrPz8tES/e8I0br2Ukn4YrIvIX3jo30Rxwts1D64ZSjKrZne87kU+PYeizs0RTIYiVu5Zux/kNlWRTw4GuQENl5maQY+cvTyNeEmsSFNAnncJjC9hZeaAE665S2m17ZkQoH5qOydbZF321QBC3qXDzTZS6JFct/tS48NzvLd9u9vfull8wo3cBVl29GyOpSjdY+NJ3UzagFZOpNCT+tjIgElPELVzuzMAy7sqqvGk5b0SAO0D+xBuiOg3NIggZfHyZ+clsgRcMiTj33hVaSuL9PLtkvHV3xMgufu6AdAnVUQdv4qsWH3S4aXckyEVSpuVH1VxzYPm1ikRrUSup8lV/xJsITBR6v/IlkwTuWn6S4oasaojMW6sjrPrZObC0xtQ7jZ53BYcnYD+RGXeT6pTBfWjjjlgq45g5Hi2ta9fo=&bnum=3&pnum=2&affily=picky_{market}&currency=USD&adults=1&children=0&infants=1
Responses200
Headers
Content-Type: application/json
Body
{
  "server_time": 1548314488,
  "additional_order_baggage_fee": 30,
  "extra_fee": 0,
  "bags_price_split": {
    "1": {
      "currency": "EUR",
      "amount": 60.36,
      "base": 50.3,
      "service_flat": 0,
      "service": 10.06
    },
    "2": {
      "currency": "EUR",
      "amount": 60.36,
      "base": 50.3,
      "service_flat": 0,
      "service": 10.06
    },
    "_abp": 0.2
  },
  "currency": "EUR",
  "disabled_bags_in_mmb": false,
  "book_fee": 0,
  "total": 226,
  "max_passengers": 9,
  "bags": {
    "definitions": {
      "cabin_bag": [
        {
          "category": "cabin_bag",
          "restrictions": {
            "width": 20,
            "length": 55,
            "dimensions_sum": null,
            "weight": 10,
            "height": 40
          },
          "_warning": "DEPRECATED DO NOT USE!",
          "price": 0,
          "note": null,
          "currency": "EUR",
          "conditions": {
            "is_priority": [
              "FR"
            ],
            "is_priority_FR": true,
            "passenger_groups": [
              "adult"
            ]
          }
        },
        {
          "category": "cabin_bag",
          "restrictions": {
            "width": 20,
            "length": 55,
            "dimensions_sum": null,
            "weight": 5,
            "height": 40
          },
          "_warning": "DEPRECATED DO NOT USE!",
          "price": 0,
          "note": null,
          "currency": "EUR",
          "conditions": {
            "passenger_groups": [
              "infant"
            ]
          }
        }
      ]
    },
    "_is_deprecated": true
  },
  "conversion": {
    "children_price": 0,
    "additional_order_baggage_fee": 30,
    "adults_price": 169.89,
    "infants_price": 56.09,
    "currency": "EUR",
    "amount": 226,
    "bags_price": {
      "1": 60.36,
      "2": 120.72
    }
  },
  "flights_invalid": false,
  "bags_fee_split": {
    "currency": "EUR",
    "amount": 0,
    "base": 0,
    "service": 0
  },
  "segments": [],
  "flights_checked": true,
  "adults_price": 169.89,
  "one_passenger": 58.666666666666664,
  "discounts": null,
  "flights": [
    {
      "bags_recheck_required": false,
      "source_name": "lcc-FR",
      "combination_src": "PRG",
      "dtime_unix": 1550559900,
      "forced_priority_boarding": true,
      "atime_unix": 1550566500,
      "price": 17.09000015258789,
      "fees": {
        "fee_airline": 0,
        "bags_restrictions": {
          "1": {
            "width": 81,
            "length": 119,
            "dimensions_sum": null,
            "weight": 20,
            "height": 119
          },
          "2": {
            "width": 81,
            "length": 119,
            "dimensions_sum": null,
            "weight": 20,
            "height": 119
          }
        },
        "additional_order_baggage_fee": 15,
        "booking_fee": 0,
        "fee_instead": 0,
        "bags_price": {
          "1": {
            "price": 30.36,
            "price_no_margin": 25.3
          },
          "2": {
            "price": 30.36,
            "price_no_margin": 25.3
          }
        },
        "bags_fee": 0,
        "book_fee": 0,
        "apf": 0
      },
      "src_country": "CZ",
      "return": 0,
      "is_hidden": false,
      "id": "3916461095415522_0",
      "atime_unix_utc": 1550562900,
      "guarantee": false,
      "combination_trip_id": 3916461095415522,
      "src_terminal": null,
      "atime_utc": 1550562900,
      "scraping_start": 0,
      "dst_country": "IT",
      "dst_terminal": null,
      "dst": "CIA",
      "invalid": 0,
      "source": "lcc-FR",
      "checkin": 1550387100,
      "flight_no": "8332",
      "refresh_period": 5,
      "operating_airline": {
        "iata": "FR",
        "name": "Ryanair"
      },
      "max_passengers_for_price": 1,
      "dtime_utc": 1550556300,
      "combination_dst": "CIA",
      "eur": 17.09,
      "src_station": "Václav Havel Airport Prague",
      "vehicle": {
        "type": "aircraft",
        "meal": [],
        "seats": 0
      },
      "dst_station": "Ciampino–G. B. Pastine International",
      "combination_date": 1550556300,
      "dtime_unix_utc": 1550556300,
      "base_fare": {
        "currency": "CZK",
        "amount": 439
      },
      "timestamp": 1548314456,
      "dtime": 1550559900,
      "original_trip_id": 3916461095415522,
      "source_url": "",
      "refresh_ttl": 120,
      "fare_basis": "NFEBDROP",
      "src_name": "Prague",
      "passengers_flight_check": {
        "1": {
          "last_checked": 1548314456,
          "invalid": false,
          "eur": 17.09
        },
        "2": {
          "last_checked": 1548314456,
          "invalid": false,
          "eur": 17.09
        },
        "3": {
          "last_checked": 1548314456,
          "invalid": false,
          "eur": 17.09
        },
        "4": {
          "last_checked": 1548314456,
          "invalid": false,
          "eur": 17.09
        }
      },
      "atime": 1550566500,
      "guarantee_disclaimer": "",
      "refreshed": 1548314456,
      "dst_name": "Rome",
      "src": "PRG",
      "is_cabin_bags_with_priority_boarding": false,
      "combination_return_date": null,
      "found_on": "lcc-FR",
      "infants_conditions": {
        "trolley": true,
        "hand_weight": 5
      },
      "extras": null,
      "airline": {
        "airport_checkin": 55,
        "code": "FR",
        "is_passenger_cardholder": null,
        "grade": "A",
        "booking_doc_needed": 1,
        "close_booking_hours": 6,
        "skip_subairline_merge": null,
        "temporary_disabled": null,
        "hold_weight": 20,
        "hand2_weight": 5,
        "book_fee": 0,
        "id": 11,
        "Name": "Ryanair",
        "hand2_note": "",
        "hold_height": 81,
        "shorter_stopovers_allowed": 1,
        "payment_card_copy_eticket_requirement": false,
        "iatacode": "FR",
        "flight_change_fee": 50,
        "fee_instead": 0,
        "hold_note": "",
        "search_priority": 0,
        "maximum_passengers": 9,
        "hand_note": "",
        "affil_url": null,
        "checkin": 2,
        "iata": "FR",
        "hold_length": 119,
        "passengers_in_search": 1,
        "fee_percent": 0,
        "hand_width": null,
        "lcc": null,
        "active": 1,
        "luggage_only_during_checkin_airlines": null,
        "hold_width": 119,
        "doing_online_checkin": 1,
        "luggage_only_on_web": null,
        "checkin_closure": 2,
        "hand_length": null,
        "is_private_fares_allowed": null,
        "fee_airline": 0,
        "name": "Ryanair",
        "hand2_width": 25,
        "carrier_type": "airline",
        "url": "http://www.ryanair.com/",
        "hand2_height": 20,
        "hand2_length": 40,
        "mmb_link": null,
        "non_active_reason": null,
        "hand_height": null,
        "hand_weight": null
      },
      "eur_children": 17.09,
      "bags_recheck_disclaimer": "",
      "eur_infants": 25
    },
    {
      "bags_recheck_required": false,
      "source_name": "lcc-FR",
      "combination_src": "CIA",
      "dtime_unix": 1551172800,
      "forced_priority_boarding": true,
      "atime_unix": 1551179400,
      "price": 33.45000076293945,
      "fees": {
        "fee_airline": 0,
        "bags_restrictions": {
          "1": {
            "width": 81,
            "length": 119,
            "dimensions_sum": null,
            "weight": 20,
            "height": 119
          },
          "2": {
            "width": 81,
            "length": 119,
            "dimensions_sum": null,
            "weight": 20,
            "height": 119
          }
        },
        "additional_order_baggage_fee": 15,
        "booking_fee": 0,
        "fee_instead": 0,
        "bags_price": {
          "1": {
            "price": 30,
            "price_no_margin": 25
          },
          "2": {
            "price": 30,
            "price_no_margin": 25
          }
        },
        "bags_fee": 0,
        "book_fee": 0,
        "apf": 0
      },
      "src_country": "IT",
      "return": 1,
      "is_hidden": false,
      "id": "3915361597178598_0",
      "atime_unix_utc": 1551175800,
      "guarantee": false,
      "combination_trip_id": 3915361597178598,
      "src_terminal": null,
      "atime_utc": 1551175800,
      "scraping_start": 0,
      "dst_country": "CZ",
      "dst_terminal": null,
      "dst": "PRG",
      "invalid": 0,
      "source": "lcc-FR",
      "checkin": 1551000000,
      "flight_no": "8331",
      "refresh_period": 5,
      "operating_airline": {
        "iata": "FR",
        "name": "Ryanair"
      },
      "max_passengers_for_price": 1,
      "dtime_utc": 1551169200,
      "combination_dst": "PRG",
      "eur": 33.45,
      "src_station": "Ciampino–G. B. Pastine International",
      "vehicle": {
        "type": "aircraft",
        "meal": [],
        "seats": 0
      },
      "dst_station": "Václav Havel Airport Prague",
      "combination_date": 1551169200,
      "dtime_unix_utc": 1551169200,
      "base_fare": {
        "currency": "EUR",
        "amount": 33.45000076293945
      },
      "timestamp": 1548314453,
      "dtime": 1551172800,
      "original_trip_id": 3915361597178598,
      "source_url": "",
      "refresh_ttl": 120,
      "fare_basis": "AZLDIS2",
      "src_name": "Rome",
      "passengers_flight_check": {
        "1": {
          "last_checked": 1548314453,
          "invalid": false,
          "eur": 33.45
        },
        "2": {
          "last_checked": 1548314453,
          "invalid": false,
          "eur": 33.45
        },
        "3": {
          "last_checked": 1548314453,
          "invalid": false,
          "eur": 33.45
        },
        "4": {
          "last_checked": 1548314453,
          "invalid": false,
          "eur": 33.45
        }
      },
      "atime": 1551179400,
      "guarantee_disclaimer": "",
      "refreshed": 1548314453,
      "dst_name": "Prague",
      "src": "CIA",
      "is_cabin_bags_with_priority_boarding": false,
      "combination_return_date": null,
      "found_on": "lcc-FR",
      "infants_conditions": {
        "trolley": true,
        "hand_weight": 5
      },
      "extras": null,
      "airline": {
        "airport_checkin": 55,
        "code": "FR",
        "is_passenger_cardholder": null,
        "grade": "A",
        "booking_doc_needed": 1,
        "close_booking_hours": 6,
        "skip_subairline_merge": null,
        "temporary_disabled": null,
        "hold_weight": 20,
        "hand2_weight": 5,
        "book_fee": 0,
        "id": 11,
        "Name": "Ryanair",
        "hand2_note": "",
        "hold_height": 81,
        "shorter_stopovers_allowed": 1,
        "payment_card_copy_eticket_requirement": false,
        "iatacode": "FR",
        "flight_change_fee": 50,
        "fee_instead": 0,
        "hold_note": "",
        "search_priority": 0,
        "maximum_passengers": 9,
        "hand_note": "",
        "affil_url": null,
        "checkin": 2,
        "iata": "FR",
        "hold_length": 119,
        "passengers_in_search": 1,
        "fee_percent": 0,
        "hand_width": null,
        "lcc": null,
        "active": 1,
        "luggage_only_during_checkin_airlines": null,
        "hold_width": 119,
        "doing_online_checkin": 1,
        "luggage_only_on_web": null,
        "checkin_closure": 2,
        "hand_length": null,
        "is_private_fares_allowed": null,
        "fee_airline": 0,
        "name": "Ryanair",
        "hand2_width": 25,
        "carrier_type": "airline",
        "url": "http://www.ryanair.com/",
        "hand2_height": 20,
        "hand2_length": 40,
        "mmb_link": null,
        "non_active_reason": null,
        "hand_height": null,
        "hand_weight": null
      },
      "eur_children": 33.45,
      "bags_recheck_disclaimer": "",
      "eur_infants": 25
    }
  ],
  "grace_period_fee": null,
  "service_package_price": 0,
  "additional_services": {
    "priority_boarding": {
      "data": {
        "3916461095415522_0": {
          "price_info": {
            "merchant": "0",
            "service": "0",
            "currency": "EUR",
            "amount": "8",
            "base": "8",
            "service_flat": "0"
          },
          "currency": "EUR",
          "price": 8,
          "is_possible": true
        },
        "3915361597178598_0": {
          "price_info": {
            "merchant": "0",
            "service": "0",
            "currency": "EUR",
            "amount": "8",
            "base": "8",
            "service_flat": "0"
          },
          "currency": "EUR",
          "price": 8,
          "is_possible": true
        }
      },
      "type": 0
    }
  },
  "price_change": false,
  "flights_price": 201.62,
  "pnum": 4,
  "insurance_price": {
    "travel_plus": 25.3,
    "skysilver": 11.29,
    "skygold": 25.3,
    "travel_basic": 11.29
  },
  "bags_restrictions": {},
  "orig_price_usage": true,
  "sp_fee": 30.24,
  "document_options": {
    "checkin_date": 1550387100,
    "airport_checkin_price": 110,
    "document_need": 1
  },
  "bags_price": {
    "1": 60.36,
    "2": 120.72
  },
  "flight_real_price": 201.62,
  "transfers": [],
  "adult_threshold": 16,
  "insurance_data": {
    "travel_plus": {
      "price": 25.3,
      "product_num": "04"
    },
    "tarif": "TA",
    "valid_from": null,
    "skysilver": {
      "price": 11.29,
      "product_num": "02"
    },
    "skygold": {
      "price": 25.3,
      "product_num": "04"
    },
    "travel_basic": {
      "price": 11.29,
      "product_num": "02"
    },
    "valid_to": null
  },
  "visas_agreement_requiered": true,
  "children_price": 0,
  "fee_airline": 0,
  "flights_to_check": false,
  "luggage": [
    null,
    null,
    null,
    null,
    20,
    119,
    81,
    119,
    "",
    40,
    20,
    25,
    5,
    "",
    ""
  ],
  "hand_bags_price": {},
  "fees_dropdown": {
    "original_price": 226,
    "conversion": {
      "original_price": 226,
      "base_fare": 201.61,
      "refundable_fee": 0,
      "currency": "EUR",
      "fees": 24.39,
      "merchant_fee": 1.02
    },
    "base_fare": 201.61,
    "merchant_fee": 1.0199999999999996,
    "fees": 24.39,
    "refundable_fee": 0
  },
  "credits_price": 226,
  "booking_token": "oKWrjE3p79Fphzv+baF3C2h1PDgCet9WaEXSzPuPgCEAv+on9q2YST/DjPlyl3WZYCdLEXKEOBtJT96uSi5cLvEfHS/r4ptstFPMzb8oeL6HtCKh/nzMgVI1roK8esqfAsmtfIwxGFIqExy/KKtfOdUYk/BwL/yRCYFqKJvzZPkv6vXipc2VCM2h0tmdD4XvXYnFcyHAX3BdAFyh/AXf0/SqmkK87Sx6ER450eLSR31OBcaXaGUIGTY+EIYCmsgP0+aFuT6UIeIW8cU9bcA8KYnssYY0hF9e09Cgatiu20NzveymJOoui29xQjFpG/5uJuQWKFOgrEcOQMBpvy5qADGSPCODxNecTGSOjWzue4gKQXoVxzP0/6vmWmloyVkyFPxpI3E6yrD0Ak7NLFJRjyrGzke2gsQctHgAd9wpUg3+ODmZNVVtGo3Rx+HgNKDf80F0YEd6PPq9Q1qGUaOqgPmO6iRsVbCuMmFxb+Pbv3TQ+/5y21PjVT/pEitrMxbsCUhy6VSUpNWOAZXhwhixRUabEo5bsg0GZvGcbLMYljL+WwKZwe5vRDyEmxvmvnPgdWX6jxX/5x/GySwOO0xmn8SxQYkojBYKZp91cSV1pO5Xvw8auirxQF1Fr5U4W0hrz8mwsWZrN28sqMAMbK3xOMgBWgcMz38EYQnVw9je42764+eijEJS3YEcCwJVdMTYU7e85ozlkob3j0V7sOEWIIRgMolZduzllqGy3q5rFGv8+0ThM91mD09/lAu3v3yBoLvFILojPfSbJXOCZQO5IZnUMxCUiVhuRFE+CcCBO01VbpJGVzQo+UwNNnbpbJwKNJzPAP0PMW00JxqNP4blZrSSXAIW6yNM06bMLx2CJnXAux27IUFn43PuFTQ+W2Hyp5Tu1MZsIPPRwBSK/oGCeg==",
  "infants_price": 56.09,
  "baggage": {
    "combinations": {
      "hold_bag": [
        {
          "indices": [],
          "price": {
            "currency": "EUR",
            "amount": 0,
            "base": 0,
            "service_flat": 0,
            "service": 0
          },
          "conditions": {
            "passenger_groups": [
              "adult"
            ]
          }
        },
        {
          "indices": [
            0
          ],
          "price": {
            "currency": "EUR",
            "amount": 60.36,
            "base": 50.3,
            "service_flat": 0,
            "service": 10.06
          },
          "conditions": {
            "passenger_groups": [
              "adult"
            ]
          }
        },
        {
          "indices": [
            0,
            0
          ],
          "price": {
            "currency": "EUR",
            "amount": 120.71,
            "base": 100.59,
            "service_flat": 0,
            "service": 20.12
          },
          "conditions": {
            "passenger_groups": [
              "adult"
            ]
          }
        }
      ],
      "hand_bag": [
        {
          "indices": [],
          "price": {
            "currency": "EUR",
            "amount": 0,
            "base": 0,
            "service_flat": 0,
            "service": 0
          },
          "conditions": {
            "passenger_groups": [
              "adult"
            ]
          }
        },
        {
          "indices": [
            0,
            1
          ],
          "price": {
            "currency": "EUR",
            "amount": 0,
            "base": 0,
            "service_flat": 0,
            "service": 0
          },
          "conditions": {
            "is_priority": [
              "FR"
            ],
            "passenger_groups": [
              "adult"
            ]
          }
        },
        {
          "indices": [
            2
          ],
          "price": {
            "currency": "EUR",
            "amount": 0,
            "base": 0,
            "service_flat": 0,
            "service": 0
          },
          "conditions": {
            "passenger_groups": [
              "infant"
            ]
          }
        }
      ]
    },
    "definitions": {
      "hold_bag": [
        {
          "category": "hold_bag",
          "restrictions": {
            "width": 81,
            "length": 119,
            "dimensions_sum": null,
            "weight": 20,
            "height": 119
          },
          "price": {
            "merchant": null,
            "service": 10.06,
            "currency": "EUR",
            "amount": 60.36,
            "base": 50.3,
            "service_flat": 0
          },
          "conditions": {
            "passenger_groups": [
              "adult"
            ]
          }
        }
      ],
      "hand_bag": [
        {
          "category": "cabin_bag",
          "restrictions": {
            "width": 20,
            "length": 55,
            "dimensions_sum": null,
            "weight": 10,
            "height": 40
          },
          "price": {
            "merchant": null,
            "service": 0,
            "currency": "EUR",
            "amount": 0,
            "base": 0,
            "service_flat": 0
          },
          "conditions": {
            "is_priority": [
              "FR"
            ],
            "passenger_groups": [
              "adult"
            ]
          }
        },
        {
          "category": "personal_item",
          "restrictions": {
            "width": 20,
            "length": 40,
            "dimensions_sum": null,
            "weight": 5,
            "height": 25
          },
          "price": {
            "merchant": null,
            "service": 0,
            "currency": "EUR",
            "amount": 0,
            "base": 0,
            "service_flat": 0
          },
          "conditions": {
            "passenger_groups": [
              "adult"
            ]
          }
        },
        {
          "category": "cabin_bag",
          "restrictions": {
            "width": 20,
            "length": 55,
            "dimensions_sum": null,
            "weight": 5,
            "height": 40
          },
          "price": {
            "merchant": null,
            "service": 0,
            "currency": "EUR",
            "amount": 0,
            "base": 0,
            "service_flat": 0
          },
          "conditions": {
            "passenger_groups": [
              "infant"
            ]
          }
        }
      ]
    }
  },
  "infants_conditions": {
    "trolley": true,
    "hand_weight": 5
  },
  "orig_price": 226,
  "bags_fee": 0,
  "flights_real_checked": true,
  "route": [
    "PRG",
    "CIA"
  ]
}

check_flights
GET/api/v0.1/check_flights{?v,booking_token,bnum,pnum,affily,currency,adults,children,infants}

A check flights response has the following attributes important for your implementation. Other parameters are used internally and can be ignored in most cases:

flights_checked - True/False. You need to repeat the check_flights until the value is True. After the first call, our system is running the price validation in the background, which can take up to 5 minutes. Usually, the price is validated in under 30 seconds. Please, repeat the check_flights call with a delay.

flights_invalid - True/False. This value can be set to True, which means that the flight is not bookable anymore because it was either cancelled by the airline or has sold out already. The booking should be cancelled and save_booking should not be called. This is a rare occasion and it should not happen often.

total - The total price, including any fees, always in EUR.

conversion - Converts total to local currency.

conversion: {
        currency: "USD",
        amount: 69.56,
        additional_order_baggage_fee: 16.77,
        children_price: 54.22,
        bags_price: {
            1: 27.95,
            2: 61.49
        }
    }

additional_order_baggage_fee - an extra fee for additional service post booking

document_need

  • States if there is a travel document required for the flight. The value can be set to 0/1/2.

  • The document can be either a passport or an ID, it is a responsibility of the passenger to choose the right ID with which they will be able to travel.

  • document_need : 0 - No need to document details at all.

  • document_need : 1 - In case of B2B cooperation, we need document details at the time of booking, otherwise we do not need document details right now but they will be requested later (in standard flow, after booking confirmation, we are sending email with link to our Manage My Booking section on Kiwi.com where customer fills passport details).

  • document_need : 2 - Document details have to be provided in save_booking request. Indicate IDs without expiration date as null in expiration.

checkin_date - States the date in Unix time format up to which the check-in is open.

luggage

  • It is not possible to add baggage only for part of the itinerary. So if you want 2 pieces of baggage you have to order 2 pieces of baggage for all the flights.

  • Each airline has its own restrictions. It’s usually in airline property of flights block.

  • hand = cabin luggage

  • hold = checked luggage

  • hand2 = second cabin luggage

  • There is property luggage in responses. It is an intersection of airlines restrictions. Type is list/array and values are in the following order:

    hand_length
    hand_width
    hand_height
    hand_weight
    hold_weight
    hold_length
    hold_width
    hold_height
    note = note of hold luggage
    hand2_length
    hand2_width
    hand2_height
    hand2_weight
    hand2_note
    hand_note
  • Counting bags_price:

    • 1 bag = 15 EUR
    • 2 bags = 25 EUR

    If there is just one person travelling with one bag - he’ll pay 15 EUR, for two bags the price would be 25 EUR.

    If there are 2 people travelling, for one bag they would also pay 15 EUR, however for 2 bags, it would only be 30 EUR, because we count it as 1 bag for each person.

    If we have 2 people travelling with 3 bags, they’d pay 40 EUR, because 1 person is carrying 2 bags (25 EUR) and the other just one bag (15 EUR).

    So, 2 people travelling with 4 bags would pay 50 EUR.

    Even if bags_price states that the first (or even second) checked baggage is free, it is necessary to request it in both check_flights and save_booking.

    One person Two people
    One bag 15 EUR 15 EUR
    Two bags 25 EUR 30 EUR
    Three bags not possible 40 EUR
    Four bags not possible 50 EUR

guarantee - True/False. States if Kiwi.com guarantee can be applied to the flight (and only to the specific flight, not the whole itinerary). Kiwi.com guarantee is defined in our terms and conditions.

bags_recheck_required - True/False. If set to True, passenger needs to recheck any hold luggage (between two or more virtually interlined flights or airlines that do not cooperate together).

price_change - True/False. If set to True, your new price can be found in the parameter total. Price change can occur even during save_booking. Price change in save_booking - if the customer accepts the price change, you neither call check_flights nor save_booking again. The parameter “total” changes and you can continue with your booking.

visas_agreement_requiered - True/False. This parameter is only for Kiwi.com internal use and does not display correct VISA requirements, please do not refer to this parameter for VISA information.

URI Parameters
HideShow
v
integer (required) Example: 2

API version, use 2

booking_token
string (required) Example: TjFsU9KOyjpEDqm5dNSrO1ZjuRMVMgZrERrSppD325T6P8+P9w468E+3gYirNKm0xjFEaQ8brFkJXYHcFnHHQP5fINbkDjCTreeWig4WZ7B4fBYYSUgmpu0Cq8+F75sB1L9aQ+cDGm5LObGbRYN0pwUDk5LuVOHkDPT1Qmo6XhmrtXw4mLqlylxVlpY+8jS2/eBYqLA7CPIQyfcUqPhx/F26+QR/TnuLRGUvd7cpYS88pyKmqcUiqIMz9FvuwQTxaTrPz8tES/e8I0br2Ukn4YrIvIX3jo30Rxwts1D64ZSjKrZne87kU+PYeizs0RTIYiVu5Zux/kNlWRTw4GuQENl5maQY+cvTyNeEmsSFNAnncJjC9hZeaAE665S2m17ZkQoH5qOydbZF321QBC3qXDzTZS6JFct/tS48NzvLd9u9vfull8wo3cBVl29GyOpSjdY+NJ3UzagFZOpNCT+tjIgElPELVzuzMAy7sqqvGk5b0SAO0D+xBuiOg3NIggZfHyZ+clsgRcMiTj33hVaSuL9PLtkvHV3xMgufu6AdAnVUQdv4qsWH3S4aXckyEVSpuVH1VxzYPm1ikRrUSup8lV/xJsITBR6v/IlkwTuWn6S4oasaojMW6sjrPrZObC0xtQ7jZ53BYcnYD+RGXeT6pTBfWjjjlgq45g5Hi2ta9fo=

The token received in the search results

bnum
integer (required) Example: 3

The number of bags for the booking, even if bags_price states that the first (or even second) checked baggage is free, it is necessary to request it

pnum
integer (required) Example: 2

Number of passengers. Allowed range is 1-9

affily
string (required) Example: picky_{market}

Your affiliate/partner ID, with option to add market as follows: _us, where complete param looks like: affily=picky_us

currency
string (optional) Example: USD

Conversion will be in chosen currency, but the total price and other prices are always in EUR. Default in EUR.

visitor_uniqid: `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855` (optional, string) - User’s session id, should be unique per user. **If used, the same have to be used for all requests in session (check_flights, save_booking, confirm_payment)**
string (required) 
adults
integer (optional) Example: 1

Number of adults (total sum of all adults children and infants must be equal to pnum)

children
integer (optional) Example: 0

Number of children (total sum of all adults children and infants must be equal to pnum)

infants
integer (optional) Example: 1

Number of infants (total sum of all adults children and infants must be equal to pnum)


Save booking

Resources related to questions in the API.

Save_booking

Endpoint: https://booking-api.skypicker.com/api/v0.1/save_booking?

Can be called just once and only for booking that was already checked by check-flight with return value True for parameter flights_checked.

Save booking creates booking order in our system (reservation number in parameter booking_id is not the same for us and the airlines). The order should be confirmed after payment transaction is done, otherwise it won’t be fully processed.

UTF-8 encoding has to be used for all save booking requests.

POST https://booking-api.skypicker.com/api/v0.1/save_booking?v=2
Requestsexample 1
Headers
Content-Type: application/json
Body
{
  "lang": "en",
  "bags": 3,
  "passengers": [
    {
      "name": "test",
      "surname": "test",
      "title": "ms",
      "phone": "+44 44857282842",
      "birthday": 326246400,
      "expiration": 1760054400,
      "cardno": "D25845822",
      "nationality": "SE",
      "email": "[email protected]",
      "category": "adults",
      "hold_bags": {
        "341202495": {
          "1": 1,
          "2": 1,
          "3": 0
        },
        "341214132": {
          "1": 1,
          "2": 1,
          "3": 0
        }
      }
    },
    {
      "name": "John",
      "surname": "Smith",
      "title": "mr",
      "phone": "+44 44857282842",
      "birthday": 1513728000,
      "expiration": 1639958400,
      "cardno": "D25845222",
      "nationality": "SE",
      "email": "[email protected]",
      "category": "infants",
      "hold_bags": {
        "341202495": {
          "1": 1,
          "2": 0,
          "3": 0
        },
        "341214132": {
          "1": 1,
          "2": 0,
          "3": 0
        }
      }
    }
  ],
  "locale": "en-US",
  "currency": "usd",
  "booking_token": "TjFsU9KOyjpEDqm5dNSrO1ZjuRMVMgZrERrSppD325T6P8+P9w468E+3gYirNKm0xjFEaQ8brFkJXYHcFnHHQP5fINbkDjCTreeWig4WZ7B4fBYYSUgmpu0Cq8+F75sB1L9aQ+cDGm5LObGbRYN0pwUDk5LuVOHkDPT1Qmo6XhmrtXw4mLqlylxVlpY+8jS2/eBYqLA7CPIQyfcUqPhx/F26+QR/TnuLRGUvd7cpYS88pyKmqcUiqIMz9FvuwQTxaTrPz8tES/e8I0br2Ukn4YrIvIX3jo30Rxwts1D64ZSjKrZne87kU+PYeizs0RTIYiVu5Zux/kNlWRTw4GuQENl5maQY+cvTyNeEmsSFNAnncJjC9hZeaAE665S2m17ZkQoH5qOydbZF321QBC3qXDzTZS6JFct/tS48NzvLd9u9vfull8wo3cBVl29GyOpSjdY+NJ3UzagFZOpNCT+tjIgElPELVzuzMAy7sqqvGk5b0SAO0D+xBuiOg3NIggZfHyZ+clsgRcMiTj33hVaSuL9PLtkvHV3xMgufu6AdAnVUQdv4qsWH3S4aXckyEVSpuVH1VxzYPm1ikRrUSup8lV/xJsITBR6v/IlkwTuWn6S4oasaojMW6sjrPrZObC0xtQ7jZ53BYcnYD+RGXeT6pTBfWjjjlgq45g5Hi2ta9fo=",
  "affily": "affilid",
  "booked_at": "affilid",
  "user_id": "test",
  "secret_token": "test",
  "immediate_confirmation": false
}
Responses200
Headers
Content-Type: application/json
Body
{
  "server_time": 1513841133,
  "flights_checked": true,
  "extra_fee": 0,
  "eur_payment_price": 450.2,
  "book_fee": 7.88,
  "total": 450.2,
  "max_passengers": 9,
  "flights_invalid": false,
  "additional_order_baggage_fee": 6,
  "adults_price": 184.12,
  "one_passenger": 184.115,
  "sandbox": true,
  "flights": [
    {
      "bags_recheck_required": false,
      "dtime_unix": 1524646800,
      "extra": "",
      "atime_unix": 1524651600,
      "priority_boarding": {
        "currency": null,
        "price": null,
        "is_possible": false
      },
      "price": 323,
      "currency": "NOK",
      "price_new": 323,
      "src_country": "CZ",
      "id": 341214132,
      "atime_unix_utc": 1524644400,
      "guarantee": false,
      "atime_utc": 1524644400,
      "scraping_start": 0,
      "dst": "CPH",
      "invalid": null,
      "dst_country": "DK",
      "checkin": 1524560400,
      "flight_no": 3581,
      "operating_airline": {
        "iata": "D8",
        "name": "Norwegian International"
      },
      "max_passengers_for_price": 9,
      "dtime_utc": 1524639600,
      "eur": 32,
      "src_station": "Václav Havel Airport Prague",
      "forced_priority_boarding": false,
      "dst_station": "Copenhagen",
      "return": 0,
      "dtime_unix_utc": 1524639600,
      "passengers": "1",
      "eur_new": 32,
      "timestamp": 1513840615,
      "dtime": 1524646800,
      "refreshed": 0,
      "src_name": "Prague",
      "src_id": 5212,
      "passengers_flight_check": {
        "1": {
          "timestamp": 1513840615,
          "invalid": null,
          "eur": 32
        },
        "2": {
          "timestamp": 1513840615,
          "invalid": null,
          "eur": 32
        }
      },
      "atime": 1524651600,
      "guarantee_disclaimer": "",
      "src": "PRG",
      "dst_name": "Copenhagen",
      "dst_id": 1979,
      "infants_conditions": {
        "trolley": true,
        "hand_weight": 5
      },
      "airline": {
        "airport_checkin": 0,
        "hand2_width": null,
        "grade": "A",
        "iatacode": "D8",
        "close_booking_hours": 4,
        "temporary_disabled": null,
        "hold_weight": 20,
        "hand2_weight": null,
        "id": 276,
        "Name": "Norwegian International",
        "hand2_note": "",
        "hold_height": 38,
        "shorter_stopovers_allowed": 1,
        "booking_doc_needed": 1,
        "hand_width": 40,
        "hold_note": "",
        "checkin_closure": 2,
        "hand_note": "",
        "affil_url": "http://www.norwegian.com",
        "checkin": 1,
        "iata": "D8",
        "hold_length": 70,
        "passengers_in_search": 1,
        "lcc": 0,
        "active": 1,
        "hold_width": 50,
        "doing_online_checkin": 1,
        "maximum_passengers": 9,
        "hand_length": 55,
        "name": "Norwegian International",
        "hand2_height": null,
        "url": "",
        "hand2_length": null,
        "non_active_reason": null,
        "hand_height": 23,
        "hand_weight": 10
      },
      "disabled": null,
      "bags_recheck_disclaimer": "",
      "eur_infants": 22.79,
      "eur_children": 55.22
    },
    {
      "bags_recheck_required": true,
      "dtime_unix": 1524683400,
      "extra": "",
      "atime_unix": 1524691800,
      "priority_boarding": {
        "currency": null,
        "price": null,
        "is_possible": false
      },
      "price": 1094,
      "currency": "NOK",
      "price_new": 1094,
      "src_country": "DK",
      "id": 341202495,
      "atime_unix_utc": 1524706200,
      "guarantee": true,
      "atime_utc": 1524706200,
      "scraping_start": 0,
      "dst": "JFK",
      "invalid": null,
      "dst_country": "US",
      "checkin": 1524597000,
      "flight_no": 7011,
      "operating_airline": {
        "iata": "DY",
        "name": "Norwegian"
      },
      "max_passengers_for_price": 9,
      "dtime_utc": 1524676200,
      "eur": 110,
      "src_station": "Copenhagen",
      "forced_priority_boarding": false,
      "dst_station": "John F. Kennedy International",
      "return": 0,
      "dtime_unix_utc": 1524676200,
      "passengers": "1",
      "eur_new": 110,
      "timestamp": 1513840614,
      "dtime": 1524683400,
      "refreshed": 0,
      "src_name": "Copenhagen",
      "src_id": 1979,
      "passengers_flight_check": {
        "1": {
          "timestamp": 1513840614,
          "invalid": null,
          "eur": 110
        },
        "2": {
          "timestamp": 1513840614,
          "invalid": null,
          "eur": 110
        }
      },
      "atime": 1524691800,
      "guarantee_disclaimer": "",
      "src": "CPH",
      "dst_name": "New York City",
      "dst_id": 8353,
      "infants_conditions": {
        "trolley": true,
        "hand_weight": 5
      },
      "airline": {
        "airport_checkin": 0,
        "hand2_width": 25,
        "grade": "A",
        "iatacode": "DY",
        "close_booking_hours": 4,
        "temporary_disabled": null,
        "hold_weight": 20,
        "hand2_weight": 4,
        "id": 17,
        "Name": "Norwegian",
        "hand2_note": "",
        "hold_height": 79,
        "shorter_stopovers_allowed": 1,
        "booking_doc_needed": 0,
        "hand_width": 40,
        "hold_note": "max 300cm (length + width + height)",
        "checkin_closure": 2,
        "hand_note": "",
        "affil_url": "http://www.norwegian.com",
        "checkin": 1,
        "iata": "DY",
        "hold_length": 250,
        "passengers_in_search": 1,
        "lcc": 1,
        "active": 1,
        "hold_width": 112,
        "doing_online_checkin": 1,
        "maximum_passengers": 9,
        "hand_length": 55,
        "name": "Norwegian",
        "hand2_height": 20,
        "url": "",
        "hand2_length": 33,
        "non_active_reason": null,
        "hand_height": 23,
        "hand_weight": 6
      },
      "disabled": null,
      "bags_recheck_disclaimer": "",
      "eur_infants": 79.98,
      "eur_children": 34.56
    }
  ],
  "status_code": 200,
  "auth_token": "6d4343f0-aef4-49ec-af68-807a53320867",
  "transaction_id": "sandbox_5130968",
  "status": "success",
  "price_change": false,
  "flights_price": 244.76999999999998,
  "pnum": 2,
  "insurance_price": {
    "travel_plus": 43.94,
    "skysilver": 26.93,
    "skygold": 43.94,
    "travel_basic": 26.93
  },
  "promocode": {
    "discount": 0,
    "used": false
  },
  "bags_restrictions": {
    "341202495": {
      "hold_combinations": [
        [
          1
        ],
        [
          1,
          2
        ]
      ],
      "max_hand": 0,
      "hands": {},
      "holds": {
        "1": {
          "note": null,
          "category": "hold",
          "price": 45,
          "restrictions": {
            "width": 79,
            "length": 250,
            "dimensions_sum": 300,
            "weight": 20,
            "height": 112
          },
          "currency": "USD"
        },
        "2": {
          "note": null,
          "category": "hold",
          "price": 95,
          "restrictions": {
            "width": 79,
            "length": 250,
            "dimensions_sum": 300,
            "weight": 20,
            "height": 112
          },
          "currency": "USD"
        }
      },
      "hand_type": "pcs",
      "hold_type": "pcs",
      "max_hold": 2,
      "hand_combinations": []
    }
  },
  "orig_price_usage": true,
  "sp_fee": 37.9,
  "document_options": {
    "checkin_date": 1524560400,
    "airport_checkin_price": 0,
    "document_need": 1
  },
  "bags_price": {
    "1": 60.6,
    "2": 167.43
  },
  "flight_real_price": 252.64999999999998,
  "transfers": [],
  "insurance_data": {
    "travel_plus": {
      "price": 43.94,
      "product_num": "03"
    },
    "tarif": "TB",
    "valid_from": null,
    "skysilver": {
      "price": 26.93,
      "product_num": "01"
    },
    "skygold": {
      "price": 43.94,
      "product_num": "03"
    },
    "travel_basic": {
      "price": 26.93,
      "product_num": "01"
    },
    "valid_to": null
  },
  "visas_agreement_requiered": false,
  "passengers": [
    {
      "category": "adults",
      "created_at": 1513841133,
      "surname": "test",
      "name": "test",
      "insurance_type": "none",
      "title": "ms",
      "cardno": "D25845822",
      "checkin": "",
      "insurance_sent": null,
      "updated_at": 1513841133,
      "insurance_price": 0,
      "birthday": "1980-05-04",
      "expiration": null,
      "nationality": "se",
      "pk": 7783919,
      "bid": 5130968,
      "visa": null,
      "issuer": ""
    },
    {
      "category": "infants",
      "created_at": 1513841133,
      "surname": "Smith",
      "name": "John",
      "insurance_type": "none",
      "title": "mr",
      "cardno": "D25845222",
      "checkin": "",
      "insurance_sent": null,
      "updated_at": 1513841133,
      "insurance_price": 0,
      "birthday": "2017-12-20",
      "expiration": null,
      "nationality": "se",
      "pk": 7783918,
      "bid": 5130968,
      "visa": null,
      "issuer": ""
    },
    {
      "category": "child",
      "created_at": 1513841133,
      "surname": "Smith",
      "name": "John",
      "insurance_type": "none",
      "title": "mr",
      "cardno": "D25845222",
      "checkin": "",
      "insurance_sent": null,
      "updated_at": 1513841133,
      "insurance_price": 0,
      "birthday": "2017-12-20",
      "expiration": null,
      "nationality": "se",
      "pk": 7783918,
      "bid": 5130968,
      "visa": null,
      "issuer": ""
    }
  ],
  "fee_airline": 0,
  "payu_token": null,
  "flights_to_check": false,
  "luggage": [
    55,
    40,
    23,
    6,
    20,
    70,
    50,
    38,
    "max 300cm (length + width + height)",
    null,
    null,
    null,
    null,
    "",
    ""
  ],
  "hand_bags_price": {},
  "credits_price": 450.2,
  "infants_price": 144.89,
  "booking_id": 5130968,
  "infants_conditions": {
    "trolley": true,
    "hand_weight": 5
  },
  "orig_price": 329,
  "bags_fee": 121.2,
  "flights_real_checked": true,
  "route": [
    "PRG",
    "JFK"
  ]
}

save_booking
POST/api/v0.1/save_booking{?v}

The response is the same as for check_flights with a few additional attributes. Booking is confirmed when save_booking returns a 200 http code.

save_booking requests and responses are slightly different according to the used payment method (Zooz or credits).

  • for Zooz payment, you need to add parameter payment_gateway with value payu to the request body - "payment_gateway": "payu"

Please always send booked_at and affily in save_booking.

  • affily is a unique affiliate id that is assigned to each partner and cannot be changed, it coresponds to the parameter partner on search. It will stay with you for the whole time you deal with Kiwi.com. If you are not sure about what it is, contact our Business Development Manager.

  • booked_at is the page where the booking was made, ussually same as affily .

  • And most importantly, please always use some identificator instead of “picky”. (e.g. affily=otto_us), so that we know who you are.

Please note: There are occasionally cases where there are more bags sent to save_booking than is allowed.

The maximum number of bags that can be ordered is the number of prices in bags_price * (multiplied by) the number of passengers.

E.g.:

  • bags_price = {} => no bag can be ordered

  • bags_price = {1: 30}, length(passengers) = 2 => 2 bags may be ordered

  • bags_price = {1: 30, 2: 60}, length(passengers) = 2 => 4 bags may be ordered

A number of bags has to equal the number of hold_bags in passengers dict.

Example:

"bags": 1

Has to equal the:

"passengers": [
    {
        "title": "Mr",
        "name": "test",
        "surname": "test",
        ...
        "hold_bags": {
            "00ed01af47020000af2500b4_0": {
                "1": 1
            },
            "01af22f5470200009cdfdb11_0": {
                "1": 1
            }
        }
    },{
        "title": "Mr",
        "name": "testing",
        "surname": "tester",
        ...
        "hold_bags": {
            "00ed01af47020000af2500b4_0": {
                "1": 0
            },
            "01af22f5470200009cdfdb11_0": {
                "1": 0
            }
        }
    }
]

Post method body parameters:

lang (string) - language, used en as default. For this string use format ISO 639-1 in which en has to be lowercase.

bags (integer) - number of bags in the booking, even if bags_price states that the first (or even second) checked baggage is free, it is necessary to request it in both check_flights and save_booking

passengers (array[string]) - list of passengers with their details

  • name (string) - first name (and middle name of a passenger), if you need to add middle name please send it in this parameter in format: “first_name|middle_name”

  • surname (string) - last name, please send it in the following format: “last_name”

  • contact details - have to be provided at least for one passenger from a whole booking. This passenger must be an adult.

    • email (string) - users always have to use the email address which is used for their deposit account, or else they are not able to use their credit funds for ancillaries in MMB.
    • phone (string) - users have to use their company or dummy number (not passenger’s) to make sure no communication can get to the end passenger from kiwi.com side.
  • cardno (string)

    • it is an alphanumeric string with maximum length of twenty characters. E.g. D54169411x
    • number of a travel document (ID or passport), you can check if it is required in response from check_flights in parameter document_need
    • note that most countries require at least 6 months until the document expires (from the time of departure of last flight)
  • birthday (int) - date in UTC (Unix time format)

  • nationality - has to be in ISO 3166-1 alpha-2 format (nationality of the passenger, not the country where the travel document was issued)

  • title - Mr and Ms only

  • expiration (int) - Unix timestamp, expiration of travel document

  • category - adults, children, infants

  • hold_bags

    • baggage for passenger specified over each flight (316953800 in the example is flight id)
    • 1 0/1 number of first hold bags for given passenger
    • 2 0/1 number of second hold bags for given passenger (1 needs to have value 1 before you try to order second baggage for passenger)
    • 3 0/1 number of third hold bags for given passenger (1 and 2 need to have value 1 before you try to order third baggage for passenger)
    • ID can be found in the check_flights response. Example: 3916461095415522_0. Each flight has its own hold_bags ID

locale (string) - optional parameter. Use en-US as default. For this string use two formats ISO 639-1 and ISO 3166-1. Use two lowercase characters (indicating language as in lang parameter), dash, and two uppercase characters (indicating country).

currency (string) - partner can choose their own currency and conversion is done by us (see conversion parameter in check_flights). The total is always in EUR.

booking_token (string) - the hash received in the search results. This hash contains all the data about flights needed to finish the booking

billing_details - optional parameter for adding details to invoice - different billing details than the passenger details for the booking

"billing_details": {
    "company_name": "",
    "vat_number": "",
    "company_id": "",
    "name": "",
    "street_address": "",
    "postal_code": "",
    "country": "",
    "city": "",
}

price_change - if the customer accepts the price change, you neither call check_flights nor save_booking again. The parameter “total” changes and you can continue with your booking.

Payment with credits requires these additional params:

user_id (string)

  • in combination with secret_token allows access to your deposit

  • if you are not sure about your unique value, please contact our Business Development Manager

  • for sandbox bookings, you can use value "test"

secret_token (string)

  • in combination with user_id allows access to your deposit

  • if you are not sure about your unique value, please contact our Business Development Manager

  • keep this value secret to protect money in your Kiwi.com deposit

  • for sandbox bookings, you can use value "test"

immediate_confirmation (boolean)

  • Use immediate_confirmation=false. Otherwise, it is automatically set True. Consequently, we deduct funds and book the flights. This parameter is always required.

custom_markup

  • optional parameter

  • can be used in save_booking body to enable custom markup in case of additional charges at the partner’s side

  • it should be used only for partners connected via Zooz

  • partner should inform their account manager about the usage of this parameter as the custom_markup is not paid automatically unless we know about it

  • {"custom_markup": {"amount": x.y}}

  • amount - amount that is charged, always in EUR regardless of booking currency

Success response contains the following important data:

  • transaction_id - when paying with credits, this is used in confirm_payment call

  • payu_token - when paying via Zooz, this is used in confirm_payment call as paymentToken parameter

  • payu_public_key - when paying via Zooz, this is used in payment tokenization as public key parameter

NOTE: You need to add to the request parameter payment_gateway with value payu in order to get payu_token and payu_public_key in the response.

If you want to forward user’s IP address, just add this to the request: "forwarded_data": {"ip_address":"123.123.123.123"}

ERRORS

The booking processing can fail for various reasons, therefore there are also error codes. For example, if you try to book a flight which is about to depart shortly, you’ll get: {"status": "error", "msg": "can't order anymore"}

Other examples:

{‘status’: ‘error’, ‘msg’: “can’t order, young passengers”}

{‘status’: ‘failed’}

{“status”: “error”, “msg”: “Payment error”}

{‘status’: ‘error’, ‘msg’: ‘server error’}

Validation error:

{
    "status": "error",
    "msg": "invalid request data",
    "errors": {
        "general": "Can't book - less infants than adults"
    }
}
  • ValidationError(‘Currency is blocked’)

  • ValidationError(“Can’t book - less infants than adults”)

  • ValidationError(‘Partner is not enabled for production’)

  • ValidationError(‘Invalid booking_token’)

  • ValidationError(‘Invalid ip address for affil_id’)

  • ValidationError(‘Requested too many bags’)

URI Parameters
HideShow
v
integer (required) Example: 2

API version, use 2

visitor_uniqid: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 (optional, string) - User’s session id, should be unique per user. **If used, the same have to be used for all requests in session (check_flights, save_booking, confirm_payment)**
string (required) 

Payment

There are two ways the user can pay:

  • Zooz payment

  • credits

Zooz Payment

The Zooz implementation and program selection need to be done through Kiwi.com. Not Zooz directly. Please arrange that with our Business Development Manager.

Caution

This is a guide for implementing new payment method via Zooz, for troubleshooting any old implementation, please contact our Business Development Manager

To see the diagram of Zooz payment please go here: BookingflowZooz.pdf

Check out Zooz documentation for implementing their javascript solution.

How to implement this solution:

  1. download POS library from Zooz (here: https://js.paymentsos.com/latest/token.min.js)

  2. Set environment variable - call POS.setEnvironment()

    • acceptable values are: test or live - this is also the way how to create a sandbox payment
  3. Set public key - call POS.setPublicKey()

    • the public key was sent to you in save_booking response in the parameter payu_public_key
  4. Now you tokenize payment information of customer - POS.tokenize(params, function (response) {...handleResponse})

  5. Call confirm_payment endpoint (POST https://booking-api.skypicker.com/api/v0.1/confirm_payment)

    • use paymentMethodToken, paymentCvv (returned by Zooz) and paymentToken (returned by save_booking as payu_token) params for Zooz
  6. OK response looks like: {"status": 0} and error: {"status": -1}

Credits Payment

  • REQUIREMENT: immediate_confirmation = False

Basic flow (immediate_confirmation must be False):

When the payment is done with credits, payment steps are skipped and user is transferred to confirm_payment.

Confirm_payment

Confirm payment confirms that the user payment was successful, it is used for both credits and Zooz payments (described above).

Confirm_payment has input parameter booking_id. It is not mandatory to provide this parameter but it is recommended.

Confirm_payment API call needs to be sent within 30 minutes of save_booking call, any later and you may receive error response {"status": -1, "msg": "confirm payment timeout"} and the payment for the reservation will not be successful, reservation will not completed.

Credits:

  • transaction_id is sent.

  • booking_id

Zooz:

  • paymentMethodToken from JavaScript SDK is sent

  • paymentToken from save_booking API call is sent (called payu_token in save_booking)

  • booking_id

  • paymentCvv tokenized CVV from POS.tokenize

  • sandbox boolean


Response

  • status - should be 0 (zero) that means the confirm_payment was successful, any other result means that something went wrong.

  • price - the average price of the booking per passenger (total divided by the number of passengers from save_booking request).

POST https://booking-api.skypicker.com/api/v0.1/confirm_payment?v=2
Requestsexample 1
Headers
Content-Type: application/json
Body
{
  "transaction_id": "sandbox_5130968",
  "booking_id": "5130968"
}
Responses200
Headers
Content-Type: application/json
Body
{
  "status": 0,
  "price": 225.1
}

confirm_payment
POST/api/v0.1/confirm_payment{?v}

URI Parameters
HideShow
v
integer (required) Example: 2

API version, use 2


FAQ

In case you can’t find what you were looking for in the documents or FAQ, please, contact us directly at [email protected].

Q: When I send request to zooz, I get this error:

{"responseObject":{"errorDescription":"Cannot login, please check the provided credentials.","responseErrorCode":-1,"errorMessage":"Cannot login, please check the provided credentials."},"responseStatus":1}

What am I doing wrong?

A: You’re getting this message because in save_booking you have to send your affilid in booked_at parameter.

"booked_at": "affilid"

If any other value is used the system would throw the error above.

Q: How to make a sandbox booking?

A: You need to use value test for parameter name of the first passenger and value test for parameter surname of the first passenger.

Please contact our Business Development Manager with booking numbers of test bookings, if you want to know that everything is running smoothly.

Q: How do you decide the language in which are all emails from Kiwi.com sent?

A: A language used in communication with a customer is determined by value of parameter lang which is sent to save_booking.

Generated by aglio on 10 Dec 2019