# Development quickstart

Learn how to search and book a flight with the CitizenPlane (opens new window) API.


Booking a flight only requires four simple steps. Because CitizenPlane processes credit cards but is not authorised to have credit card information, a payment method generated with the Stripe API (opens new window) will be required to process the booking. Upon request and validation, CitizenPlane can also work with a deposit model. CitizenPlane (opens new window) only supports EUR as its currency.


# Testing

You'll be given a sandbox token for the implementation phase & testing process. You can easily search & book test flights using this sandbox token. If you also wish to test the payment step, you can use any of the test cards made available by Stripe (opens new window). No real charge will be induced.


# Complete flow

The search-to-booking flow with the CitizenPlane (opens new window) API is as followed:

  1. Search for Flights
  2. (Optional) Search for Round trip fares
  3. (Optional) Verify price and availability
  4. Create a booking request
  5. (Optional) Gather credit card secured details
  6. Process the booking
  7. (Optional) Retrieve booking and flight information

# Step 1: Search flights

Each time a customer is performing a flight search, you can search CitizenPlane's flight content for flights matching your customer's request.

Flight content

Please note that all our flights are non-refundable, non-exchangeable and have no flex fares. We sell both one-way & round trip fares.

Price and Availability Disclaimer

The search step of the Booking API does not guarantee the validity of prices or availability. It relies solely on a cache and should be considered indicative only. To obtain final and accurate pricing and availability, you must proceed with the request and booking steps.

CitizenPlane cannot be held responsible for discrepancies arising from relying solely on the search results.

# Implementation

All the examples below use screenshots from Kiwi.com (opens new window) booking platform.

Because the above search is a roundtrip, it should be split into the two following requests to our API:

curl "https://booking-api.citizenplane.com/v3/flights?origin=CDG&destination=PMI&start=2025-08-06&end=2025-08-07&seats=2"
-H "Accept: application/json" \
-H "Authorization: Bearer {your_api_token}"

curl "https://booking-api.citizenplane.com/v3/flights?origin=PMI&destination=CDG&start=2025-08-13&end=2025-08-14&seats=2"
-H "Accept: application/json" \
-H "Authorization: Bearer {your_api_token}"

Go to the API reference

In case of a one-way search, only one request to our API is needed.


# Step 2: Search round trip fares

In addition to one-way fares, some CitizenPlane flights are sold with specific round trip fares. To search for roundtrip-fares, you can use a new, dedicated endpoint: v3/roundTrips

Search flow

Please note that CitizenPlane distributes mostly one-way fares. This step should only be used as an additional, post-search flight step and should not by any means replace the search flight step.

# Implementation

curl "https://booking-api.citizenplane.com/v3/roundTrips?origin=CDG&destination=PMI&start=2025-08-06&end=2025-08-07&returnStart=2025-08-13&returnEnd=2025-08-14&seats=2"
-H "Accept: application/json" \
-H "Authorization: Bearer {your_api_token}"

Go to the API reference

If no fares are returned, then one-way fares returned in step 1 must be used.


# Step 3: Verify price and availability

After searching for flights and (optionally) round trip fares, you can make an additional call to verify the price and availability of a specific flight before creating a booking request.
This step is especially important to ensure that the price displayed to your customer is the most up-to-date.

Price and Availability Disclaimer

The verify step checks the current price and seat availability directly with the supplier. This guarantees that the information you display is accurate at the time of booking.

# Implementation

To verify a flight's price and availability, use the following endpoint with the required parameters:

curl --location 'https://booking-api.citizenplane.com/v3/flights/verify' \
--header 'Accept: */*' \
--header 'Content-Type: application/json' \
--header 'Authorization: {your_api_token}' \
--data '{
    "flight_id": 123456,
    "passengers": {
        "adults": 1,
        "children": 0
    },
    "customer_code": "{your_customer_code}"
}'
  • flight_id: The unique ID of the flight you want to verify.
  • passengers: Object specifying the number of adults (required), children (optional, default 0), and infants (optional, default 0, max = adults).
  • customer_code: Your customer code.

The response returns the current price details for the flight, including the adult ticket price, currency, total price, and applicable airport taxes. The infant_price field is only included if passengers.infants is greater than 0.:

{
  "price": 50,
  "currency": "EUR",
  "infant_price": null,
  "total_price": 50,
  "included_airport_tax": 13.2
}

Go to the API reference

If the price or availability has changed, you should inform your customer and update your booking flow accordingly before proceeding to the booking request step.


# Step 4: Create a booking request

Use the id returned in the flight object to create a booking request. You can specify one or two ids in the flight_ids array parameter. It will simultaneously create as many requests as there are ids specified.

Creating a booking request guarantees your seats and prices (seat & ancillary) for 3 minutes, thus saving you multiple checks to make sure the price hasn't changed or the seats haven't been taken.

Expiration time

A request is a temporary booking object waiting to be fulfilled. If the id of the request hasn't been used to process a booking within these 3 minutes, the request will be considered as expired. Any booking using the id of an expired request will be rejected.

Because checked and cabin bags options can vary between flights, they also have to be linked to their associated flight through the id of each flights. All options must be specified, even if the customer does not select any checked or cabin bags options. In that case, quantity must be set to 0.

# Implementation

Once the customer clicks on book it should generate the following API call

one-way example request

curl -X POST \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: {your_api_token}' \
-d '{
    "flight_ids”: [4014831],
    "passengers": [
        {
            "first_name": "John",
            "last_name": "Doe", 
            "gender": "male",
            "date_of_birth": "1970-01-01",
            "passport_number": "ABCDE123",
            "passport_expiry_date": "01/01/2040",
            "nationality": "fr",
            "passport_country_of_issue": "fr"
        },
        {
            "first_name": "Jane",
            "last_name": "Doe",
            "gender": "female", 
            "date_of_birth": "1970-01-01",
            "passport_number": "ABCDE124",
            "passport_expiry_date": "01/01/2040",
            "nationality": "fr",
            "passport_country_of_issue": "fr"
        }
    ],
    "bags": {
        "4014831": {
            "checked": [
                {
                    "weight": 20,
                    "quantity": 1
                }
            ],
            "cabin": [
                {
                    "dimensions": {
                        "width": 56,
                        "height": 45,
                        "length": 25
                    },
                    "quantity": 1
                },
            ]
        }
    },
    "fare_type": “one_way”,
    "customer_code": “kiwi”
}' 'https://booking-api.citizenplane.com/v3/requests'

round-trip example request

curl -X POST \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: {your_api_token}' \
-d '{
    "flight_ids”: [4014831, 3795943],
    "passengers": [
        {
            "first_name": "John",
            "last_name": "Doe", 
            "gender": "male",
            "date_of_birth": "1970-01-01",
            "passport_number": "ABCDE123",
            "passport_expiry_date": "01/01/2040",
            "nationality": "fr",
            "passport_country_of_issue": "fr"
        },
        {
            "first_name": "Jane",
            "last_name": "Doe",
            "gender": "female",
            "date_of_birth": "1970-01-01", 
            "passport_number": "ABCDE124",
            "passport_expiry_date": "01/01/2040",
            "nationality": "fr",
            "passport_country_of_issue": "fr"
        }
    ],
    "bags": {
        "4014831": {
            "checked": [
                {
                    "weight": 20,
                    "quantity": 1
                }
            ],
            "cabin": [
                {
                    "dimensions": {
                        "width": 56,
                        "height": 45,
                        "length": 25
                    },
                    "quantity": 1
                },
            ]
        }
        {
        "3795943": {
            "checked": [
                {
                    "weight": 20,
                    "quantity": 1
                }
            ],
            "cabin": [
                {
                    "dimensions": {
                        "width": 56,
                        "height": 45,
                        "length": 25
                    },
                    "quantity": 1
                },
            ]
        }
    },
    "fare_type": “round_trip”,
    "customer_code": “kiwi”
}' 'https://booking-api.citizenplane.com/v3/requests'

Go to the API reference


# Step 5: Gather credit card details (optional)

# For Self PSP integrations

WARNING

You can skip this step if your organization is authorized to use the setting self_psp: true. Refer to the self PSP setting section for more information.

# Generate a payment method

Once the customer has entered its payment information and prior to processing the booking, you'll need to send the credit card information to Stripe (opens new window) to generate a payment method we'll use to process the booking. Because of PCI compliance (opens new window) issues, CitizenPlane cannot directly process credit card information. Therefore, you need to send us a payment_method generated with Stripe along with 3D secure information if needed.

Authentication

To authenticate your request to Stripe, use the Stripe restricted token (appended with sk) we'll assign to you.

# Implementation

Once the customer clicks on pay it should send the following request to the Stripe API

curl https://api.stripe.com/v1/payment_methods \
-u sk_test_wZGrX11MrIk123a9mpOoL9: \
-d card[number]=4242424242424242 \
-d card[exp_month]=12 \
-d card[exp_year]=2019 \
-d card[cvc]=123 \
-d type=card

Go to the API reference


# Step 6: Process the booking

The payment method returned by Stripe (opens new window) includes a payment id appended by pm that you need to add in your booking payload in order to allow CitizenPlane (opens new window) to process the payment.


# Regarding Self PSP setting

If your organisation is authorised to use self_psp setting, you can omit the payment_method and three_d_secure fields and instead add the key self_psp: true.

To be authorised, please contact tech@citizenplane.com.

# Regarding 3D Secure results

If needed, you can pass 3D Secure results directly at this stage to ensure you won't have failed bookings. 3D Secure results should be formatted as follow:

Field Description Possible Values
three_d_secure.version
REQUIRED
The version of 3D Secure that was performed. - 1.0.2
- 2.1.0
- 2.2.0
three_d_secure.electronic_commerce_indicator
REQUIRED
The Electronic Commerce Indicator (ECI) is returned by your 3D Secure provider and indicates what degree of authentication was performed.

Note: If your provider returns an ECI of 07 or 00, please discard it: authentication has failed. If desired, you may make an unauthenticated payment by leaving three_d_secure unset.
- 05: Fully authenticated. The customer likely proved their identity to the issuing bank.

- 06: Attempt acknowledged. The customer, or the entire issuing bank, is not set up for 3D Secure. Or the issuing bank is experiencing an outage. CitizenPlane will return a payment error in that case.

- 01: Attempt acknowledged (Mastercard variant). CitizenPlane will return a payment error in that case.

- 02: Fully authenticated (Mastercard variant).
three_d_secure.cryptogram
REQUIRED
The cryptogram, also known as the "authentication value" (AAV, CAVV or AEVV). This value is 20 bytes, base64-encoded into a 28-character string. Most 3D Secure providers will return the base64-encoded version, which is what you should specify here. -
three_d_secure.transaction_id
REQUIRED
For 3D Secure 1, the XID. For 3D Secure 2, the Directory Server Transaction ID (dsTransID). -

Each booking payload has to be linked with up to two requests with the request_ids array parameter containing the different ids. You also have to pass the customer's information with a customer_code string.

Identify the customer

The customer is always the entity whose card is used to process the booking. Only VCCs or B2B cards should be used.

Though optional, it is highly recommended that you add a unique external_id in order to be able to trace back the booking in our system.

curl -X POST \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: {your_api_token}' \
-d '{
  "request_ids”: [244401, 244402],
  "customer_code": "kiwi",
  "external_id": "ABC123",
  "first_name": "John",
  "last_name": "Doe",
  "gender": "male",
  "email": "john.doe@example.com",
  "phonenumber": "+33600000000",
  "payment_method": "pm_1IxrDoCLoBt04Rh8deU0seLG",
  "three_d_secure": {
    "version": "2.2.0",
    "electronic_commerce_indicator": "05",
    "cryptogram": "4BQwsg4yuKt0S1LI1nDZTcO9vUM=",
    "transaction_id": "f879ea1c-aa2c-4441-806d-e30406466d79"
  }

  "self_psp": true // TO USE ONLY IF YOUR TEAM IS AUTHORIZED TO APPLY THIS SETTING

}' 'https://booking-api.citizenplane.com/v3/bookings'

Go to the API reference


# Step 7: Retrieve booking and flight information

# Implementation

If you wish to retrieve booking information and most importantly, the latest flight information attached to the booking, you can use the below endpoint. This endpoints allows you to check for potential schedule changes and automatically process them.

curl 'https://booking-api.citizenplane.com/v3/bookings?cp_reference=CPKVLF' \
-H 'Accept: application/json' \
-H 'Authorization: {your_api_token}'

Go to the API reference