# API Reference

The CitizenPlane API is based on REST (opens new window), returns JSON responses and uses standard HTTP codes. The API base url is https://booking-api.citizenplane.com/v3.

To get started with CitizenPlane API, send us a mail. We'll create your account, and send the credentials to start using our API.

URL-based versioning is supported in our API. Each version will be appended to the base url.

# Authentication

The CitizenPlane API uses Bearer Tokens to authenticate requests. All requests made whithout authentication will fail, as well as requests made over plain HTTP rather than HTTPS.

To get your token, send us a mail and we'll assign one for you.

# Errors

CitizenPlane uses conventional HTTP response codes to indicate the success or failure of an API request. Codes in the 4xx range indicate a request that failed given the information provided (e.g., a required parameter was omitted, a request has expired, a charge failed, etc.). Codes in the 5xx range indicate an internal error, which is rare.

# HTTP Status Codes Summary

Code Status Meaning
400 Bad Request Your request is invalid (e.g payload sent doesn't match request signature)
401 Unauthorized Your API key is wrong
403 Forbidden The requested action cannot be permitted (e.g process a booking on a ABORTED request)
404 Not Found The specified data could not be found (e.g flight_id doesn't exist)
409 Conflict The request wasn't processed. Potential reasons are: flight is no longer available or found in our cache, unacceptable price difference between request & booking, flight has already been booked, etc.
422 Unprocessable Entity A validation error has occured (these are payment-related errors)
500 Internal Server Error Error on CitizenPlane's end. Try again later and contact us if the issue remain

# Test mode

Test mode tokens will be provided during your integration period. These tokens will allow you to search for flights and process bookings on a set of demo flights with no danger of spending any money or booking flights you don't want.

# Going live

Before switching to production, you'll need to complete a test phase to ensure your integration works correctly. During this phase, you should:

  1. Send test PNRs covering different booking scenarios:

    • Multiple adults and infants
    • With and without checked bags
    • With and without cabin bags
  2. Once your test bookings are validated by our team, we will provide production API tokens

  3. We recommend doing a few live test bookings in production with real payments to verify the full flow works as expected. These bookings will be canceled & refunded free of charge.

  4. After successful live testing, you can fully switch your integration to production

Please contact our support team when you're ready to begin the go-live process. We'll guide you through the test scenarios and help ensure a smooth transition to production.

# Key concepts

The CitizenPlane API is very simple to use and implement. In only 4 steps, you can complete an entire booking flow, from searching a flight to processing the booking. You'll only need to understand a few concepts in order to get started with the CitizenPlane API.

# Booking requests

In order to process a booking, a booking request must be created first. Creating a booking request allows you to have the most up-to-date information regarding price & availability. You'll only need one or two request ids to confirm and process the booking.

The request will expire after 3 minutes and any booking using an id for an expired request will fail.

Check our development quickstart to get an overview of the complete booking flow.

# Customers

Customers in the CitizenPlane API are the entity (ie businesses) whose card is processed during the booking. Customers must be identified with a unique customer_code, sent both at every step of the booking process. Customer codes are used to identify OTAs within CitizenPlane's system (e.g govoyagesfr for GoVoyages.fr (opens new window), kiwicom for Kiwi.com (opens new window)). If you want to know to list of supported OTAs or add your OTA and get a customer code, please contact us.

Note

Even when connecting directly to the API (without going through a third party), you must still specify a customer code. In this case, you will be provided with both an API token and a customer code.

# Exporting our content

If you need an exhaustive list of all the content we provide, you can contact our tech team to activate a drop of a CSV file on our ftp server.

We offer two specific formats: routes or flights. Formats specification will be detailed below. We recommend that you use the routes format, which is a lighter version of our complete export.

# Files structure

Depending on distribution agreements, several files can be dropped onto your FTP folder. You can have as many exports as you have customers with specific content distribution rules. For every other customers, a file containing our entire content will also be available. If no customers have specific distribution rules, you will only get the "all" content file.

Customers

Customers are identified by a customer code, sent during the flight search and subsequent steps (request, booking).

All files are appended with the API version currently in use.

TIP

To avoid any confusion, we've also kept the legacy file names: cp_routes.csv & cp_flights.csv. These legacy files will stay for a couple months to allow you to complete the migration to the new file naming structure.

Example routes export structure:

cp_routes_customerOne_v3.csv
cp_routes_customerTwo_v3.csv
cp_routes_all_v3.csv
cp_routes.csv // legacy name

Example flights export structure:

cp_flights_customerOne_v3.csv
cp_flights_customerTwo_v3.csv
cp_flights_all_v3.csv
cp_flights.csv // legacy name

# Routes format

departureAirport;arrivalAirport;departureDate
BSL;PRN;21.06.2025
MLH;PRN;21.06.2025
AAL;AYT;22.06.2025
ACE;CGN;22.06.2025
ADB;AMS;22.06.2025
ADB;CGN;22.06.2025
...

# Flights format

departureAirport;arrivalAirport;departureDate;marketingAirlineCode;marketingFlightNumber;operatingAirlineCode;operatingFlightNumber;bookingClass;classOfService;availableSeats;fareType;baseFareAmountAdult;supplementSumAmountAdult;totalFareAmountAdult;baseFareAmountChild;supplementSumAmountChild;totalFareAmountChild;baseFareAmountInfant;supplementSumAmountInfant;totalFareAmountInfant;currency;journeyDuration;overNight;stops;segmentFirstDepartureAirport;segmentFirstArrivalAirport;segmentFirstMarketingAirlineCode;segmentFirstMarketingFlightNumber;segmentFirstOperatingAirlineCode;segmentFirstOperatingFlightNumber;segmentFirstDepartureTime;segmentFirstArrivalTime;segmentFirstBookingClass;segmentFirstClassofService;segmentSecondDepartureAirport;segmentSecondArrivalAirport;segmentSecondMarketingAirlineCode;segmentSecondMarketingFlightNumber;segmentSecondOperatingAirlineCode;segmentSecondOperatingFlightNumber;segmentSecondDepartureTime;segmentSecondArrivalTime;segmentSecondBookingClass;segmentSecondClassofService;segmentThirdDepartureAirport;segmentThirdArrivalAirport;segmentThirdMarketingAirlineCode;segmentThirdMarketingFlightNumber;segmentThirdOperatingAirlineCode;segmentThirdOperatingFlightNumber;segmentThirdDepartureTime;segmentThirdArrivalTime;segmentThirdBookingClass;segmentThirdClassofService;baggageFirstWeight;baggageFirstAmount;baggageSecondWeight;baggageSecondAmount;baggageThirdWeight;baggageThirdAmount;checkInFee;airportCheckInFee;creditCardFee;combinationGroup;flightKey;tariffClass
NAS;FLL;19.11.2025;WU;102;WU;102;Y;Y;*;OW;;;243.08;;;243.08;;;63.35;EUR;;0;0;NAS;FLL;WU;102;WU;102;11:00;11:50;Y;Y;;;;;;;;;;;;;;;;;;;;;18;0.00;;;;;;;0.03;;;
PRN;DUS;19.11.2025;IV;620;IV;620;Y;Y;*;OW;;;324.45;;;324.45;;;85.90;EUR;;0;0;PRN;DUS;IV;620;IV;620;11:05;13:30;Y;Y;;;;;;;;;;;;;;;;;;;;;20;0.00;;;;;;;0.03;;;
PRN;STR;19.11.2025;IV;630;IV;630;Y;Y;*;OW;;;224.54;;;224.54;;;58.09;EUR;;0;0;PRN;STR;IV;630;IV;630;11:50;13:50;Y;Y;;;;;;;;;;;;;;;;;;;;;20;0.00;;;;;;;0.03;;;
PRN;MLH;19.11.2025;C3;1806;C3;1806;Y;Y;2;OW;;;115.36;;;115.36;;;30.90;EUR;;0;0;PRN;MLH;C3;1806;C3;1806;13:30;15:40;Y;Y;;;;;;;;;;;;;;;;;;;;;20;0.00;;;;;;;0.03;;;
...

# Endpoints

# Search flights

Use this endpoint to retrieve a list of flights that you can book. Each flight is identified by a unique ID that will be needed to create a request.

GET

https://booking-api.citizenplane.com/v3/flights

# Our flight content

All flights prices are in EUR only. All flights can have one, two or three segments and are non-refundable, non-exchangeable with no flex fares. We sell both one-way & round trip fares, although round trip fares are not always available (while one-way fares are always available).

# Query parameters

Parameter Type Status Description
origin string required Origin airport IATA code (CDG for instance). Airport city codes are not currently supported.
destination string required Destination airport IATA code (AYT for instance). Airport city codes are not currently supported.
start date optional Date from which the flight search will be operated. Expected format: YYYY-MM-DD. Defaults to current day.
end date optional Date until which the flight search will be operated, up to max +3 days from start. Expected format: YYYY-MM-DD. Defaults to start + 3 days.
seats integer optional Minimum number of seats to search for.
customerCode string optional Unique code to identify the customer making this request
next_page_id string optional Specify the page to retrieve. You get the first next_page_id cursor at the end of the first page of results. Each page displays up to 100 results.

Example request

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

# Response elements

Field Type Description
cc_fee float Credit card fee amount in percentage. This fee is included in the total price when paying by credit card. Default is 0.03 (3%).
infant_price float Price for an infant ticket (under 2 years old). Can be null if infant tickets are not available.
included_airport_tax float Airport taxes and fees that are included in the total price.
price float Base fare price for an adult or child ticket, excluding bag fees

Example response

{
	"results": [
		{
			"id": 4014831,
			"need_apis": true,
			"cabin_class": "economy",
			"booking_class": "Y",
			"included_airport_tax": 59.71,
			"duration": "07:55",
            "bags": {
                "checked": [
                    {
                        "weight": 20,
                        "quantity": 1,
                        "price": 36.00
                    }
                ],
                "cabin": [
                    {
                        "dimensions": {
                          "width": 56,
                          "height": 45,
                          "length": 25
                        },
                        "quantity": 1,
                        "price": 0.00
                    }
                ]
            },
			"departure_date": "2025-08-06 13:45:00",
			"arrival_date": "2025-08-06 22:40:00",
			"origin": {
				"iata_code": "CDG",
				"city_name": "Paris",
				"country_name": "France",
				"timezone": "Europe/Paris"
			},
			"destination": {
				"iata_code": "AYT",
				"city_name": "Antalya",
				"country_name": "Turkey",
				"timezone": "Europe/Istanbul"
			},
			"segments": [
				{
					"via_airport": null,
					"origin": {
						"iata_code": "CDG",
						"city_name": "Paris",
						"country_name": "France",
						"timezone": "Europe/Paris"
					},
					"destination": {
						"iata_code": "WAW",
						"city_name": "Warsaw",
						"country_name": "Poland",
						"timezone": "Europe/Warsaw"
					},
					"operating_carrier_flight_number": 1346,
					"operating_carrier": {
						"name": "Air France",
						"iata_code": "AF"
					},
					"marketing_carrier_flight_number": 1346,
					"marketing_carrier": {
						"name": "Air France",
						"iata_code": "AF"
					},
					"departure_date": "2025-08-06 13:45:00",
					"arrival_date": "2025-08-06 16:05:00",
					"duration": "02:20"
				},
				{
					"via_airport": null,
					"origin": {
						"iata_code": "WAW",
						"city_name": "Warsaw",
						"country_name": "Poland",
						"timezone": "Europe/Warsaw"
					},
					"destination": {
						"iata_code": "AYT",
						"city_name": "Antalya",
						"country_name": "Turkey",
						"timezone": "Europe/Istanbul"
					},
					"operating_carrier_flight_number": 421,
					"operating_carrier": {
						"name": "Sunexpress",
						"iata_code": "XQ"
					},
					"marketing_carrier_flight_number": 421,
					"marketing_carrier": {
						"name": "Sunexpress",
						"iata_code": "XQ"
					},
					"departure_date": "2025-08-06 18:40:00",
					"arrival_date": "2025-08-06 22:40:00",
					"duration": "03:00"
				}
			],
			"available_seats": 10,
			"price": 483.07,
			"infant_price": 129.78,
			"cc_fee": 0.03
		},
		{
			"id": 4014832,
			"need_apis": true,
			"cabin_class": "economy",
			"booking_class": "Y",
			"included_airport_tax": 77.53,
			"duration": "03:55",
            "bags": {
                "checked": [
                    {
                        "weight": 20,
                        "quantity": 1,
                        "price": 36.05
                    }
                ],
                "cabin": [
                    {
                        "dimensions": {
                          "width": 56,
                          "height": 45,
                          "length": 25
                        },
                        "quantity": 1,
                        "price": 0.00
                    }
                ]
            },
			"departure_date": "2025-08-06 17:45:00",
			"arrival_date": "2025-08-06 22:40:00",
			"origin": {
				"iata_code": "CDG",
				"city_name": "Paris",
				"country_name": "France",
				"timezone": "Europe/Paris"
			},
			"destination": {
				"iata_code": "AYT",
				"city_name": "Antalya",
				"country_name": "Turkey",
				"timezone": "Europe/Istanbul"
			},
			"segments": [
				{
					"via_airport": null,
					"origin": {
						"iata_code": "CDG",
						"city_name": "Paris",
						"country_name": "France",
						"timezone": "Europe/Paris"
					},
					"destination": {
						"iata_code": "AYT",
						"city_name": "Antalya",
						"country_name": "Turkey",
						"timezone": "Europe/Istanbul"
					},
					"operating_carrier_flight_number": 511,
					"operating_carrier": {
						"name": "Sunexpress",
						"iata_code": "XQ"
					},
					"marketing_carrier_flight_number": 511,
					"marketing_carrier": {
						"name": "Sunexpress",
						"iata_code": "XQ"
					},
					"departure_date": "2025-08-06 17:45:00",
					"arrival_date": "2025-08-06 22:40:00",
					"duration": "03:55"
				}
			],
			"available_seats": 10,
			"price": 627.27,
			"infant_price": 169.95,
			"cc_fee": 0.03
		},
		{...},
		{...},
	],
	"next_page_id": null
}

# Search one-way fares (required)

To search one-way fares and get complete flight details, use the /flights endpoint defined above. This endpoint returns all essential flight information including:

  • Available fares
  • Checked and cabin baggage options with dimensions and prices
  • Flight segments and timings
  • Available seats

# Search roundtrip fares (optional)

This endpoint is optional and should only be used to check if special roundtrip fares exist for your search criteria. It will return results if and only if specific roundtrip fares are available.

Important

You must always perform two separate one-way searches using the /flights endpoint to:

  1. Get complete flight details for both outbound and return flight
  2. Compare individual one-way fares with any available roundtrip fares to find the best fare available

GET

https://booking-api.citizenplane.com/v3/roundTrips

# Query parameters

Parameter Type Status Description
origin string required Origin airport IATA code (CDG for instance). Airport city codes are not currently supported.
destination string required Destination airport IATA code (AYT for instance). Airport city codes are not currently supported.
start date optional Date from which the flight search will be operated. Expected format: YYYY-MM-DD. Defaults to current day.
end date optional Date until which the flight search will be operated, up to max +3 days from start. Expected format: YYYY-MM-DD. Defaults to start + 3 days.
returnStart date optional Date from which the return flight search will be operated. Expected format: YYYY-MM-DD. Defaults to start + 1 day.
returnEnd date optional Date until which the return flight search will be operated, up to max +3 days from returnStart. Expected format: YYYY-MM-DD. Defaults to end + 1 days.
customerCode string optional Unique code to identify the customer making this request
seats integer optional Minimum number of seats to search for.
next_page_id string optional Specify the page to retrieve. You get the first next_page_id cursor at the end of the first page of results. Each page displays up to 100 results.

Example request

curl "https://booking-api.citizenplane.com/v3/roundTrips?origin=CDG&destination=AYT&start=2025-08-06&seats=1&returnStart=2025-08-13&customerCode={your_code}" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer {your_api_token}"

# Response elements

Field Type Description
checked_bags_prices array Array of prices for checked bags applicable for the whole roundtrip. Each element represents the total price for one checked bag on both outbound and return flights.
cabin_bags_prices array Array of prices for cabin bags applicable for the whole roundtrip. Each element represents the total price for one cabin bag on both outbound and return flights.
cc_fees float Credit card fee amount in percentage. This fee is included in the total price when paying by credit card. Default is 0.03 (3%).
infant_price float Price for an infant ticket (under 2 years old) for the roundtrip. Can be null if infant tickets are not available.
included_airport_tax float Total airport taxes and fees that are included in the roundtrip price.
price float Base fare price for an adult or child roundtrip ticket, excluding bag fees
available_seats integer Number of seats available at this fare for the roundtrip

Example response

{
    "fares": [
        {
          "outward_id": 4014831,
          "return_id": 4014832,
          "price": 600,
          "infant_price": 200,
          "checked_bags_prices": [
            72
          ],
          "cabin_bags_prices": [
            0
          ],
          "included_airport_tax": 72,
          "cc_fees": 0.03,
          "available_seats": 9
        }
      ],
	"flights": [
		{
			"id": 4014831,
			"need_apis": true,
			"cabin_class": "economy",
			"booking_class": "Y",
			"included_airport_tax": 59.71,
			"duration": "07:55",
			"departure_date": "2025-08-06 13:45:00",
			"arrival_date": "2025-08-06 22:40:00",
			"origin": {
				"iata_code": "CDG",
				"city_name": "Paris",
				"country_name": "France",
				"timezone": "Europe/Paris"
			},
			"destination": {
				"iata_code": "AYT",
				"city_name": "Antalya",
				"country_name": "Turkey",
				"timezone": "Europe/Istanbul"
			},
			"segments": [
				{
					"via_airport": null,
					"origin": {
						"iata_code": "CDG",
						"city_name": "Paris",
						"country_name": "France",
						"timezone": "Europe/Paris"
					},
					"destination": {
						"iata_code": "WAW",
						"city_name": "Warsaw",
						"country_name": "Poland",
						"timezone": "Europe/Warsaw"
					},
					"operating_carrier_flight_number": 1346,
					"operating_carrier": {
						"name": "Air France",
						"iata_code": "AF"
					},
					"marketing_carrier_flight_number": 1346,
					"marketing_carrier": {
						"name": "Air France",
						"iata_code": "AF"
					},
					"departure_date": "2025-08-06 13:45:00",
					"arrival_date": "2025-08-06 16:05:00",
					"duration": "02:20"
				},
				{
					"via_airport": null,
					"origin": {
						"iata_code": "WAW",
						"city_name": "Warsaw",
						"country_name": "Poland",
						"timezone": "Europe/Warsaw"
					},
					"destination": {
						"iata_code": "AYT",
						"city_name": "Antalya",
						"country_name": "Turkey",
						"timezone": "Europe/Istanbul"
					},
					"operating_carrier_flight_number": 421,
					"operating_carrier": {
						"name": "Sunexpress",
						"iata_code": "XQ"
					},
					"marketing_carrier_flight_number": 421,
					"marketing_carrier": {
						"name": "Sunexpress",
						"iata_code": "XQ"
					},
					"departure_date": "2025-08-06 18:40:00",
					"arrival_date": "2025-08-06 22:40:00",
					"duration": "03:00"
				}
			],
		},
		{
			"id": 4014832,
			"need_apis": true,
			"cabin_class": "economy",
			"booking_class": "Y",
			"included_airport_tax": 77.53,
			"duration": "03:55",
			"departure_date": "2025-08-06 17:45:00",
			"arrival_date": "2025-08-06 22:40:00",
			"origin": {
				"iata_code": "CDG",
				"city_name": "Paris",
				"country_name": "France",
				"timezone": "Europe/Paris"
			},
			"destination": {
				"iata_code": "AYT",
				"city_name": "Antalya",
				"country_name": "Turkey",
				"timezone": "Europe/Istanbul"
			},
			"segments": [
				{
					"via_airport": null,
					"origin": {
						"iata_code": "CDG",
						"city_name": "Paris",
						"country_name": "France",
						"timezone": "Europe/Paris"
					},
					"destination": {
						"iata_code": "AYT",
						"city_name": "Antalya",
						"country_name": "Turkey",
						"timezone": "Europe/Istanbul"
					},
					"operating_carrier_flight_number": 511,
					"operating_carrier": {
						"name": "Sunexpress",
						"iata_code": "XQ"
					},
					"marketing_carrier_flight_number": 511,
					"marketing_carrier": {
						"name": "Sunexpress",
						"iata_code": "XQ"
					},
					"departure_date": "2025-08-06 17:45:00",
					"arrival_date": "2025-08-06 22:40:00",
					"duration": "03:55"
				}
			],
		},
		{...},
		{...},
	],
	"next_page_id": null
}

# Verify price and availability

The verify endpoint allows customers to confirm the latest price and availability for a specific flight using live data.

If the requested number of seats is available, the response will include the real-time seat price, currency, total price, and applicable airport taxes. The price is identical for adults and children. The infant_price field is only included if passengers.infants is greater than 0.

POST

https://booking-api.citizenplane.com/v3/flights/verify

# Parameters

Parameter Type Status Description
flight_id integer required The unique flight ID to verify
customer_code string optional Unique code to identify the customer making the request
passengers object required Object specifying the number of adults, children, and infants (see below)
# Passengers object
Parameter Type Status Description
adults integer required Number of adults (min 1, max 9)
children integer optional Number of children (default 0, max 9)
infants integer optional Number of infants (default 0, max = adults)

Example request

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}"
}'

Example response

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

# Create a booking request

This endpoint creates booking requests for one or two flights (identified by their id). You can thus simultaneously create two different requests.

POST

https://booking-api.citizenplane.com/v3/requests

Expired requests

A request only lasts for five minutes. Past that deadline, a new request will have to be created to create a booking.

Bags

All available bag options (checked & cabin) returned in the flight search must be specified in the request payload, even if you don't want to book any bags. For example, if a flight offers two checked bag options (20kg and 30kg) and one cabin bag option, you must include all three options in your request with their quantities (set to 0 if not selected).

# Body parameters

Parameter Type Status Description
flight_ids array required An array containing up to two flight_id
customer_code string optional Unique code to identify the customer making this request
passengers array required An array containing personal information for each passenger on this booking. See child arguments
bags object required An object containing all available checked & cabin bag options for each flight, with their selected quantities. Every bag option returned in flight search must be included. See child arguments
fare_type string required type of fare chosen for the given flight(s). Two options possible: one_way or round_trip. Chose round_trip if you want to book a round trip fare, chose one_way otherwise.

# Passengers parameters

Parameter Type Status Description
first_name string required Passenger's first name
middle_name string optional Passenger's middle name (if applicable)
last_name string required Passenger's last name
gender string required Passenger's gender
date_of_birth string required Passenger's date of birth
birth_country string optional Passenger's birth country
passport_number string optional Passenger's passport number
passport_expiry_date string optional Passenger's passport expiry date
passport_country_of_issue string optional Passenger's passport country of issue
nationality string optional Passenger's nationality

# Bags

The bags parameter is an object whose keys must match the ids sent in the flight_ids parameter. For each flight, you must include all checked & cabin bag options that were returned in the flight search response, even if you don't want to book any bags. For example, if a flight offers a 20kg and 30kg checked bag option, both must be specified in your request with their quantities (set to 0 if not selected).

Bags are not attached to a passenger. They are attached to a booking. If a booking contains three passengers, you can book up to three checked bags and three cabin bags.

Each checked bags option contains two parameters:

Parameter Type Status Description
quantity number required the number of the chosen checked bag. The quantity must not exceed the number of passengers
weight number required the weight of the chosen checked bag.

Cabin bags can however be defined both by their dimensions and weight. You can chose to send us either the dimensions or the weight, or both.

Parameter Type Status Description
quantity number required the number of the chosen cabin bag. The quantity must not exceed the number of passengers
dimensions object required dimensions of the chosen cabin bag. Dimensions are composed of width, height and length
weight number required the weight of the chosen cabin bag.

Example request

curl 'https://booking-api.citizenplane.com/v3/requests' \
-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": "1975-06-15",
            "passport_number": "XYZ789",
            "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
                    },
                    "weight": 10,
                    "quantity": 1
                }
            ]
        },
        "3795943": {
            "checked": [
                {
                    "weight": 20,
                    "quantity": 1
                }
            ],
            "cabin": [
                {
                    "dimensions": {
                        "width": 56,
                        "height": 45,
                        "length": 25
                    },
                    "weight": 10,
                    "quantity": 1
                }
            ]
        }
    },
    "fare_type": one_way,
    "customer_code": {your_customer_code}
}'

Example response

{
  "requests": [
    {
      "id": 244401,
      "passengers": {
        "adults": 2,
        "children": 0,
        "infants": 0
      },
      "price": 469,
      "infant_price": null,
      "bags_fee": {
        "checked": 36,
        "cabin": 0
      },
      "cc_fee": 0,
      "customer_code": "{your_customer_code}",
      "created_at": "2025-06-28T00:02:25.317Z",
      "flight": {
        "id": 4014831,
        "need_apis": true,
        "cabin_class": "economy",
        "booking_class": "Y",
        "included_airport_tax": 56.28,
        "duration": "07:55",
        "bags": {
            "checked": [
                {
                    "weight": 20,
                    "quantity": 1,
                    "price": 36.00
                }
            ],
            "cabin": [
                {
                    "dimensions": {
                      "width": 56,
                      "height": 45,
                      "length": 25
                    },
                    "weight": 10,
                    "quantity": 1,
                    "price": 0.00
                }
            ]
        },
        "departure_date": "2025-08-06 13:45:00",
        "arrival_date": "2025-08-06 22:40:00",
        "origin": {
          "iata_code": "CDG",
          "city_name": "Paris",
          "country_name": "France",
          "timezone": "Europe/Paris"
        },
        "destination": {
          "iata_code": "AYT",
          "city_name": "Antalya",
          "country_name": "Turkey",
          "timezone": "Europe/Istanbul"
        },
        "segments": [
          {
            "via_airport": null,
            "origin": {
              "iata_code": "CDG",
              "city_name": "Paris",
              "country_name": "France",
              "timezone": "Europe/Paris"
            },
            "destination": {
              "iata_code": "WAW",
              "city_name": "Warsaw",
              "country_name": "Poland",
              "timezone": "Europe/Warsaw"
            },
            "operating_carrier_flight_number": 1346,
            "operating_carrier": {
              "name": "Air France",
              "iata_code": "AF"
            },
            "marketing_carrier_flight_number": 1346,
            "marketing_carrier": {
              "name": "Air France",
              "iata_code": "AF"
            },
            "departure_date": "2025-08-06 13:45:00",
            "arrival_date": "2025-08-06 16:05:00"
          },
          {
            "via_airport": null,
            "origin": {
              "iata_code": "WAW",
              "city_name": "Warsaw",
              "country_name": "Poland",
              "timezone": "Europe/Warsaw"
            },
            "destination": {
              "iata_code": "AYT",
              "city_name": "Antalya",
              "country_name": "Turkey",
              "timezone": "Europe/Istanbul"
            },
            "operating_carrier_flight_number": 421,
            "operating_carrier": {
              "name": "Sunexpress",
              "iata_code": "XQ"
            },
            "marketing_carrier_flight_number": 421,
            "marketing_carrier": {
              "name": "Sunexpress",
              "iata_code": "XQ"
            },
            "departure_date": "2025-08-06 18:40:00",
            "arrival_date": "2025-08-06 22:40:00"
          }
        ]
      },
      "customer": {
        "name": "{your_company_name}",
        "email": null,
        "is_company": true,
        "company_codes": ["{your_customer_code}"],
        "verified": true,
        "phonenumber": null,
        "gender": null,
        "address": null,
        "postal_code": null,
        "city_name": null,
        "country_code": "{your_country_code}",
        "country_name": "{your_country_name}",
        "vat_number": null,
        "registration_number": null,
        "created_at": "2025-01-27T09:56:15.773Z",
        "updated_at": "2025-01-31T10:26:20.424Z"
      }
    },
    {
      "id": 244402,
      "passengers": {
        "adults": 2,
        "children": 0,
        "infants": 0
      },
      "price": 555,
      "infant_price": null,
      "cc_fee": 0,
      "bags_fee": {
        "checked": 36,
        "cabin": 0
      },
      "customer_code": "{your_customer_code}",
      "created_at": "2025-06-28T00:02:25.319Z",
      "flight": {
        "id": 3795943,
        "need_apis": false,
        "cabin_class": "economy",
        "booking_class": "Y",
        "included_airport_tax": 66.6,
        "duration": "04:20",
        "bags": {
            "checked": [
                {
                    "weight": 20,
                    "quantity": 1,
                    "price": 36.00
                }
            ],
            "cabin": [
                {
                    "weight": 10,
                    "dimensions": {
                      "width": 56,
                      "height": 45,
                      "length": 25
                    },
                    "quantity": 1,
                    "price": 0.00
                }
            ]
        },
        "departure_date": "2025-08-13 13:35:00",
        "arrival_date": "2025-08-13 16:55:00",
        "origin": {
          "iata_code": "AYT",
          "city_name": "Antalya",
          "country_name": "Turkey",
          "timezone": "Europe/Istanbul"
        },
        "destination": {
          "iata_code": "CDG",
          "city_name": "Paris",
          "country_name": "France",
          "timezone": "Europe/Paris"
        },
        "segments": [
          {
            "via_airport": null,
            "origin": {
              "iata_code": "AYT",
              "city_name": "Antalya",
              "country_name": "Turkey",
              "timezone": "Europe/Istanbul"
            },
            "destination": {
              "iata_code": "CDG",
              "city_name": "Paris",
              "country_name": "France",
              "timezone": "Europe/Paris"
            },
            "operating_carrier_flight_number": 510,
            "operating_carrier": {
              "name": "Sunexpress",
              "iata_code": "XQ"
            },
            "marketing_carrier_flight_number": 510,
            "marketing_carrier": {
              "name": "Sunexpress",
              "iata_code": "XQ"
            },
            "departure_date": "2025-08-13 13:35:00",
            "arrival_date": "2025-08-13 16:55:00"
          }
        ]
      },
      "customer": {
        "name": "{your_company_name}",
        "email": null,
        "is_company": true,
        "company_codes": ["{your_customer_code}"],
        "verified": true,
        "phonenumber": null,
        "gender": null,
        "address": null,
        "postal_code": null,
        "city_name": null,
        "country_code": "{your_country_code}",
        "country_name": "{your_country_name}",
        "vat_number": null,
        "registration_number": null,
        "created_at": "2025-01-27T09:56:15.773Z",
        "updated_at": "2025-01-31T10:26:20.424Z"
      }
    }
  ]
}

# Cancel a booking request

Use this endpoint to cancel an existing booking request that is no longer needed. Once cancelled, you can restart a complete booking flow, which will then create a new booking request.

Important

Only pending booking requests can be cancelled

POST

https://booking-api.citizenplane.com/v3/requests/{request_id}/cancel

# Path Parameters

Parameter Type Required Description
request_id string Yes The unique identifier of the booking request to cancel

Example request

curl -X POST 'https://booking-api.citizenplane.com/v3/requests/123456789/cancel' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: {your_api_token}'

Example response

{
  "success": true
}

# Create a Payment Method

WARNING

This step can be omitted if you are authorized to use the self_psp setting and go directly to create a booking.

This external endpoint from Stripe (opens new window) generates a payment_method which will be used in the next step to process the payment and confirm the booking.

POST

https://api.stripe.com/v1/payment_methods

# Using Stripe as payment provider

CitizenPlane's API uses Stripe (opens new window) to process credit card payments. In order to be PCI-compliant (opens new window), CitizenPlane cannot directly process the customer's credit card data.

The Stripe API also returns JSON-encoded responses and accepts form-encoded requests bodies. Several client libraries are available for an easy integration, as explained in the Stripe API documentation (opens new window)

Failed payment

If the payment fails for any reason, the associated request will be considered as aborted and the process is to be started again. In case of a failed payment, the corresponding Stripe error code (opens new window) will be returned.

# Authorization

To perform a request to the Stripe API, you will need to have a Stripe restricted token (e.g sk_test_123456789abcdedf) which we will give along with your CitizenPlane API credentials.

# Card parameters

Parameter Type Status Description
number string required The card number, as a string without any separators
exp_month number required Two-digit number representing the card's expiration month
exp_year number required Four-digit number representing the card's expiration year
cvc string required Card security code. Highly recommended to always include this value, but it's required only for accounts based in European countries
type string required The type of the PaymentMethod (e.g card). An additional hash is included on the PaymentMethod with a name matching this value. It contains additional information specific to the PaymentMethod type.

Example request

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

Example response

{
  "id": "pm_1Ixu0UCLoBt04Rh8x4xr4E2a",
  "object": "payment_method",
  "billing_details": {
    "address": {
      "city": null,
      "country": null,
      "line1": null,
      "line2": null,
      "postal_code": "42424",
      "state": null
    },
    "email": "jenny@example.com",
    "name": null,
    "phone": "+15555555555"
  },
  "card": {
    "brand": "visa",
    "checks": {
      "address_line1_check": null,
      "address_postal_code_check": null,
      "cvc_check": "pass"
    },
    "country": "US",
    "exp_month": 8,
    "exp_year": 2025,
    "fingerprint": "vsS0JwU3bB3xdpsO",
    "funding": "credit",
    "generated_from": null,
    "last4": "4242",
    "networks": {
      "available": ["visa"],
      "preferred": null
    },
    "three_d_secure_usage": {
      "supported": true
    },
    "wallet": null
  },
  "created": 123456789,
  "customer": null,
  "livemode": false,
  "metadata": {
    "order_id": "123456789"
  },
  "type": "card"
}

Payment method

The payment method id will always be appended with pm_ followed by a random string of numbers and letters.

# Create a booking

This endpoint validates the previously created booking requests and processes the booking as well as the associated payment. Once the booking is created, the customer will receive a confirmation by email along with the ticket(s). Passengers can also check their reservation on our website (opens new window). If the booking is linked to multiple requests (up to three), the same PNR will be issued for each booking, so that the customer can find all the bookings with a unique reference.

POST

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

# Body parameters

Parameter Type Status Description
request_ids integer required An array containing up to two different request_id
external_id string optional The id used on your side to identify the booking. This field is optional, though highly recommended in case we need to retrieve a booking in your system
customer_code string optional A unique code used to identify the customer making this reservation (must be already added in CitizenPlane's system).
first_name string required The booker's first name
last_name string required The booker's last name
gender string required The booker's gender
email string required The booker's email
phonenumber string required The booker's phone number
address string optional The booker's address
city_name string optional The booker's city name
country_code string optional The booker's country code
postal_code string optional The booker's postal code
self_psp boolean required (if authorized) This lets you create a booking directly after request step, without needing payment_method to be specified as it is already handled on your side.
payment_method string required (if not using self_psp) An id obtained by sending credit card information to Stripe's API (opens new window)
three_d_secure object optional (if not using self_psp) 3D Secure results obtained previously with your 3D Secure provider

self_psp

The self_psp parameter allows you to book using a deposit model. You'll have to be explicitly authorized for your account to use this setting. A regular payment will be required to ensure that your balance is always positive. A tracking dasbhoard with list of bookings & balance information can be provided upon request.

# 3D Secure parameters

For more in depth information regarding 3D Secure results you may have to pass with booking details, please refer to Stripe API Reference (opens new window)

Parameter Type Status Description
version string required The version of 3D Secure that was performed. Possible enum values: 1.0.2, 2.1.0, 2.2.0
electronic_commerce_indicator string required The Electronic Commerce Indicator (ECI) is returned by your 3D Secure provider and indicates what degree of authentication was performed. (If your provider returns an ECI of 07 or 00, please discard it: authentication has failed. If your provider returns an ECI of 06 or 01, attempt was only acknowledged and payment won't be processed by CitizenPlane. If desired, you may make an unauthenticated payment by leaving three_d_secure unset.)
cryptogram string 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.)
transaction_id boolean required For 3D Secure 1, the XID. For 3D Secure 2, the Directory Server Transaction ID (dsTransID).
curl 'https://booking-api.citizenplane.com/v3/bookings' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: {your_api_token}' \
-d '{
  "request_ids": [ 244401, 244402 ],
  "customer_code": "{your_customer_code}",
  "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
}'

Ticket issuance

A successful booking (200 status response) means the ticket is considered as issued. However, for non-charter flights, the airline PNR may take up to 2 hours to be generated after booking. You should poll the GET booking endpoint regularly to check if the pnr_airline field has been populated.

Example response

{
  "bookings": [
    {
      "id": 253571,
      "flight_id": 4014831,
      "request_id": 244401,
      "cp_reference": "CPKVLF",
      "pnr_airline": null,
      "status": "AWAITING_PNR_AIRLINE", 
      "first_name": "john",
      "last_name": "doe",
      "gender": "male",
      "email": "john.doe@example.com",
      "phonenumber": "0033600000000",
      "address": "n/a",
      "country_code": "n/a",
      "postal_code": "n/a",
      "passenger_count": 2,
      "infant_count": 0,
      "passengers": [
        {
          "id": 426678,
          "booking_id": 253571,
          "gender": "male", 
          "last_name": "doe",
          "first_name": "john",
          "is_infant": false,
          "date_of_birth": "01/01/2001",
          "nationality": null,
          "confirmed": false,
          "confirmed_at": null,
          "canceled": false,
          "canceled_at": null,
          "passport_number": null,
          "passport_expiry_date": null,
          "passport_country_of_issue": null,
          "created_at": "2025-06-28T00:34:21.461Z",
          "updated_at": "2025-06-28T00:34:21.317Z",
          "birth_country": null
        },
        {
          "id": 426679,
          "booking_id": 253571,
          "gender": "female",
          "last_name": "doe", 
          "first_name": "jane",
          "is_infant": false,
          "date_of_birth": "01/01/2002",
          "nationality": null,
          "confirmed": false,
          "confirmed_at": null,
          "canceled": false,
          "canceled_at": null,
          "passport_number": null,
          "passport_expiry_date": null,
          "passport_country_of_issue": null,
          "created_at": "2025-06-28T00:34:21.461Z",
          "updated_at": "2025-06-28T00:34:21.317Z",
          "birth_country": null
        }
      ],
      "bags": {
        "checked": [
            {
                "weight": 20,
                "quantity": 1,
                "price": 36.00
            }
        ],
        "cabin": [
            {
                "dimensions": {
                  "width": 56,
                  "height": 45,
                  "length": 25
                },
                "weight": 10,
                "quantity": 1,
                "price": 0.00
            }
        ]
      },
      "cc_fee": 0,
      "bags_fee": {
        "checked": 36,
        "cabin": 0
      },
      "created_at": "2025-06-28T00:34:21.416Z",
      "price": 469,
      "infant_price": 126,
      "total_price": 938,
      "external_id": "ABC123",
      "flight": {
        "id": 4014831,
        "need_apis": true,
        "cabin_class": "economy",
        "booking_class": "Y",
        "included_airport_tax": 56.28,
        "duration": "07:55",
        "departure_date": "2025-08-06 13:45:00",
        "arrival_date": "2025-08-06 22:40:00",
        "origin": {
          "iata_code": "CDG",
          "city_name": "Paris",
          "country_name": "France",
          "timezone": "Europe/Paris"
        },
        "destination": {
          "iata_code": "AYT",
          "city_name": "Antalya",
          "country_name": "Turkey",
          "timezone": "Europe/Istanbul"
        },
        "segments": [
          {
            "via_airport": null,
            "origin": {
              "iata_code": "CDG",
              "city_name": "Paris",
              "country_name": "France",
              "timezone": "Europe/Paris"
            },
            "destination": {
              "iata_code": "WAW",
              "city_name": "Warsaw",
              "country_name": "Poland",
              "timezone": "Europe/Warsaw"
            },
            "operating_carrier_flight_number": 1346,
            "operating_carrier": {
              "name": "Air France",
              "iata_code": "AF"
            },
            "marketing_carrier_flight_number": 1346,
            "marketing_carrier": {
              "name": "Air France",
              "iata_code": "AF"
            },
            "departure_date": "2025-08-06 13:45:00",
            "arrival_date": "2025-08-06 16:05:00"
          },
          {
            "via_airport": null,
            "origin": {
              "iata_code": "WAW",
              "city_name": "Warsaw",
              "country_name": "Poland",
              "timezone": "Europe/Warsaw"
            },
            "destination": {
              "iata_code": "AYT",
              "city_name": "Antalya",
              "country_name": "Turkey",
              "timezone": "Europe/Istanbul"
            },
            "operating_carrier_flight_number": 421,
            "operating_carrier": {
              "name": "Sunexpress",
              "iata_code": "XQ"
            },
            "marketing_carrier_flight_number": 421,
            "marketing_carrier": {
              "name": "Sunexpress",
              "iata_code": "XQ"
            },
            "departure_date": "2025-08-06 18:40:00",
            "arrival_date": "2025-08-06 22:40:00"
          }
        ]
      }
    },
    {
      "id": 253572,
      "flight_id": 3795943,
      "request_id": 244402,
      "cp_reference": "CPKVLF",
      "pnr_airline": null,
      "status": "AWAITING_PNR_AIRLINE",
      "first_name": "john",
      "last_name": "doe",
      "gender": "male",
      "email": "john.doe@example.com",
      "phonenumber": "0033600000000",
      "address": "n/a",
      "country_code": "n/a",
      "postal_code": "n/a",
      "passenger_count": 2,
      "infant_count": 0,
      "passengers": [
        {
          "id": 426679,
          "booking_id": 253572,
          "gender": "male",
          "last_name": "doe",
          "first_name": "john",
          "is_infant": false,
          "date_of_birth": "01/01/2001",
          "nationality": null,
          "confirmed": false,
          "confirmed_at": null,
          "canceled": false,
          "canceled_at": null,
          "passport_number": null,
          "passport_expiry_date": null,
          "passport_country_of_issue": null,
          "created_at": "2025-06-28T00:34:21.706Z",
          "updated_at": "2025-06-28T00:34:21.659Z",
          "birth_country": null
        },
        {
          "id": 426680,
          "booking_id": 253572,
          "gender": "female",
          "last_name": "doe",
          "first_name": "jane",
          "is_infant": false,
          "date_of_birth": "01/01/2002",
          "nationality": null,
          "confirmed": false,
          "confirmed_at": null,
          "canceled": false,
          "canceled_at": null,
          "passport_number": null,
          "passport_expiry_date": null,
          "passport_country_of_issue": null,
          "created_at": "2025-06-28T00:34:21.706Z",
          "updated_at": "2025-06-28T00:34:21.659Z",
          "birth_country": null
        }
      ],
      "bags": {
        "checked": [
            {
                "weight": 20,
                "quantity": 1,
                "price": 36.00
            }
        ],
        "cabin": [
            {
                "dimensions": {
                  "width": 56,
                  "height": 45,
                  "length": 25
                },
                "weight": 10,
                "quantity": 1,
                "price": 0.00
            }
        ]
      },
      "bags_fee": {
        "checked": 36,
        "cabin": 0
      },
      "cc_fee": 0,
      "created_at": "2025-06-28T00:34:21.695Z",
      "price": 555,
      "infant_price": 150,
      "total_price": 1110,
      "external_id": "ABC123",
      "flight": {
        "id": 3795943,
        "need_apis": false,
        "cabin_class": "economy",
        "booking_class": "Y",
        "included_airport_tax": 66.6,
        "duration": "04:20",
        "departure_date": "2025-08-13 13:35:00",
        "arrival_date": "2025-08-13 16:55:00",
        "origin": {
          "iata_code": "AYT",
          "city_name": "Antalya",
          "country_name": "Turkey",
          "timezone": "Europe/Istanbul"
        },
        "destination": {
          "iata_code": "CDG",
          "city_name": "Paris",
          "country_name": "France",
          "timezone": "Europe/Paris"
        },
        "segments": [
          {
            "via_airport": null,
            "origin": {
              "iata_code": "AYT",
              "city_name": "Antalya",
              "country_name": "Turkey",
              "timezone": "Europe/Istanbul"
            },
            "destination": {
              "iata_code": "CDG",
              "city_name": "Paris",
              "country_name": "France",
              "timezone": "Europe/Paris"
            },
            "operating_carrier_flight_number": 421,
            "operating_carrier": {
              "name": "Sunexpress",
              "iata_code": "XQ"
            },
            "marketing_carrier_flight_number": 421,
            "marketing_carrier": {
              "name": "Sunexpress",
              "iata_code": "XQ"
            },
            "departure_date": "2025-08-13 13:35:00",
            "arrival_date": "2025-08-13 16:55:00"
          }
        ]
      }
    }
  ]
}

# Retrieve booking and flight information

This endpoint retrieves one or two bookings (in case of round trip bookings) and flight information using the cp_reference returned at the booking step. The same cp_reference that can be used for passengers to check their reservation on our website (opens new window). All flight changes along with the final_flight will also be returned, allowing you to automatically check if the flight has received a schedule change.

Two flight objects will be returned in the response:

  • flight, which is the original flight on which the booking was initially made
  • final_flight, the actual flight, with all up to date information

GET

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

# Query parameters

Parameter Type Status Description
cp_reference string required The unique reference returned by /bookings linked to up to 2 bookings

# Flight changes parameters

The flight_changes key is an array listing all changes that occurred on the flight and their respective status which range from WAITING, SEEN, ACCEPTED or REFUSED, depending on the PAX actions.

For each flight_change object you'll have a data key containing an old & new flight, listing all keys that have changed because of the schedule change event.

As each flight can have up to three segments, each key will be prepended with segment_{index} with index ranging from 1 to 3. For instance, if the origin_airport key has changed for the first segment, it will be listed as segment_1_origin_airport. The only key that is specific for the whole trip is the need_apis key which can be either true or false.

Here are are the keys that can change for each segment:

Parameter Type Description
origin_airport string three letters IATA code (e.g CDG)
destination_airport string three letters IATA code
departure_date string YYYY-MM-DD HH:mm:ss formatted date
arrival_date string YYYY-MM-DD HH:mm:ss formatted date
flight_number string combination of two letters iata airline code and up to four digits (e.g AF1234)
origin_timezone string timezone of the origin airport, only present with the origin_airport (e.g Europe/Berlin)
destination_timezone string timezone of the origin airport, only present with the origin_airport (e.g Europe/Berlin)
airline_name string name of the arline, only present with airline_iata_code (e.g Air France)
airline_iata_code string two letters IATA code (e.g AF)
origin_terminal_label string corresponding terminal of the airport (e.g 2)
destination_terminal_label string corresponding terminal of the airport

Example request

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

Example response

{
  "bookings": [
    {
      "id": 253571,
      "flight_id": 4014831,
      "request_id": 244401,
      "cp_reference": "CPKVLF",
      "pnr_airline": null,
      "passenger_count": 1,
      "infant_count": 0,
      "type": "outward",
      "status": "AWAITING_PNR_AIRLINE",
      "passengers": [
        {
          "id": 426678,
          "booking_id": 253571,
          "gender": "male",
          "last_name": "doe",
          "first_name": "john",
          "is_infant": false,
          "date_of_birth": "01/01/2001",
          "nationality": null,
          "confirmed": false,
          "confirmed_at": null,
          "canceled": false,
          "canceled_at": null,
          "passport_number": null,
          "passport_expiry_date": null,
          "passport_country_of_issue": null,
          "created_at": "2025-06-28T00:34:21.461Z",
          "updated_at": "2025-06-28T00:34:21.317Z",
          "birth_country": null
        }
      ],
      "bags": {
        "checked": [
            {
                "weight": 20,
                "quantity": 1,
                "price": 36.00
            }
        ],
        "cabin": [
            {
                "dimensions": {
                  "width": 56,
                  "height": 45,
                  "length": 25
                },
                "weight": 10,
                "quantity": 1,
                "price": 0.00
            }
        ]
      },
      "created_at": "2025-06-28T00:34:21.416Z",
      "flight_changes": [
        {
          "status": "ACCEPTED",
          "data": {
                  "newFlight": {
                          "flight_id": 4086743,
                          "segment_1_departure_date": "2025-08-06 14:45:00",
                          "segment_1_arrival_date": "2025-08-06 17:05:00",
                          "segment_1_origin_timezone": "Europe/Paris",
                          "segment_1_destination_timezone": "Europe/Warsaw",
                  },
                  "oldFlight": {
                          "flight_id": 4014831,
                          "segment_1_departure_date": "2025-08-06 13:45:00",
                          "segment_1_arrival_date": "2025-08-06 16:05:00",
                          "segment_1_origin_timezone": "Europe/Paris",
                          "segment_1_destination_timezone": "Europe/Warsaw",
                  }
          },
          "created_at": "2023-10-23T11:09:32.721Z",
          "updated_at": "2023-10-25T12:00:03.088Z"
        }
      "flight": {
        "id": 4014831,
        "need_apis": true,
        "cabin_class": "economy",
        "booking_class": "Y",
        "included_airport_tax": 56.28,
        "duration": "07:55",
        "departure_date": "2025-08-06 13:45:00",
        "arrival_date": "2025-08-06 22:40:00",
        "origin": {
          "iata_code": "CDG",
          "city_name": "Paris",
          "country_name": "France",
          "timezone": "Europe/Paris"
        },
        "destination": {
          "iata_code": "AYT",
          "city_name": "Antalya",
          "country_name": "Turkey",
          "timezone": "Europe/Istanbul"
        },
        "segments": [
          {
            "via_airport": null,
            "origin": {
              "iata_code": "CDG",
              "city_name": "Paris",
              "country_name": "France",
              "timezone": "Europe/Paris"
            },
            "destination": {
              "iata_code": "WAW",
              "city_name": "Warsaw",
              "country_name": "Poland",
              "timezone": "Europe/Warsaw"
            },
            "operating_carrier_flight_number": 1346,
            "operating_carrier": {
                    "name": "Air France",
                    "iata_code": "AF"
            },
            "marketing_carrier_flight_number": 1346,
            "marketing_carrier": {
                    "name": "Air France",
                    "iata_code": "AF"
            },
            "departure_date": "2025-08-06 13:45:00",
            "arrival_date": "2025-08-06 16:05:00"
          },
          {
            "via_airport": null,
            "origin": {
              "iata_code": "WAW",
              "city_name": "Warsaw",
              "country_name": "Poland",
              "timezone": "Europe/Warsaw"
            },
            "destination": {
              "iata_code": "AYT",
              "city_name": "Antalya",
              "country_name": "Turkey",
              "timezone": "Europe/Istanbul"
            },
            "operating_carrier_flight_number": 421,
            "operating_carrier": {
                    "name": "Sunexpress",
                    "iata_code": "XQ"
            },
            "marketing_carrier_flight_number": 421,
            "marketing_carrier": {
                    "name": "Sunexpress",
                    "iata_code": "XQ"
            },
            "departure_date": "2025-08-06 18:40:00",
            "arrival_date": "2025-08-06 22:40:00"
          }
        ]
      },
      "final_flight": {
        "id": 4086743,
        "need_apis": true,
        "cabin_class": "economy",
        "booking_class": "Y",
        "included_airport_tax": 56.28,
        "duration": "07:55",
        "departure_date": "2025-08-06 14:45:00",
        "arrival_date": "2025-08-06 22:40:00",
        "origin": {
          "iata_code": "CDG",
          "city_name": "Paris",
          "country_name": "France",
          "timezone": "Europe/Paris"
        },
        "destination": {
          "iata_code": "AYT",
          "city_name": "Antalya",
          "country_name": "Turkey",
          "timezone": "Europe/Istanbul"
        },
        "segments": [
          {
            "via_airport": null,
            "origin": {
              "iata_code": "CDG",
              "city_name": "Paris",
              "country_name": "France",
              "timezone": "Europe/Paris"
            },
            "destination": {
              "iata_code": "WAW",
              "city_name": "Warsaw",
              "country_name": "Poland",
              "timezone": "Europe/Warsaw"
            },
            "operating_carrier_flight_number": 1346,
            "operating_carrier": {
                    "name": "Air France",
                    "iata_code": "AF"
            },
            "marketing_carrier_flight_number": 1346,
            "marketing_carrier": {
                    "name": "Air France",
                    "iata_code": "AF"
            },
            "departure_date": "2025-08-06 14:45:00",
            "arrival_date": "2025-08-06 17:05:00"
          },
          {
            "via_airport": null,
            "origin": {
              "iata_code": "WAW",
              "city_name": "Warsaw",
              "country_name": "Poland",
              "timezone": "Europe/Warsaw"
            },
            "destination": {
              "iata_code": "AYT",
              "city_name": "Antalya",
              "country_name": "Turkey",
              "timezone": "Europe/Istanbul"
            },
            "operating_carrier_flight_number": 421,
            "operating_carrier": {
                    "name": "Sunexpress",
                    "iata_code": "XQ"
            },
            "marketing_carrier_flight_number": 421,
            "marketing_carrier": {
                    "name": "Sunexpress",
                    "iata_code": "XQ"
            },
            "departure_date": "2025-08-06 18:40:00",
            "arrival_date": "2025-08-06 22:40:00"
          }
        ]
      }
    },
    {
      "id": 253572,
      "flight_id": 3795943,
      "request_id": 244402,
      "cp_reference": "CPKVLF",
      "pnr_airline": null,
      "passenger_count": 1,
      "infant_count": 0,
      "type": "return"
      "status": "AWAITING_PNR_AIRLINE",
      "passengers": [
        {
          "id": 426679,
          "booking_id": 253572,
          "gender": "male",
          "last_name": "doe",
          "first_name": "john",
          "is_infant": false,
          "date_of_birth": "01/01/2001",
          "nationality": null,
          "confirmed": false,
          "confirmed_at": null,
          "canceled": false,
          "canceled_at": null,
          "passport_number": null,
          "passport_expiry_date": null,
          "passport_country_of_issue": null,
          "created_at": "2025-06-28T00:34:21.706Z",
          "updated_at": "2025-06-28T00:34:21.659Z",
          "birth_country": null
        }
      ],
      "bags": {
        "checked": [
            {
                "weight": 20,
                "quantity": 1,
                "price": 36.00
            }
        ],
        "cabin": [
            {
                "dimensions": {
                  "width": 56,
                  "height": 45,
                  "length": 25
                },
                "weight": 10,
                "quantity": 1,
                "price": 0.00
            }
        ]
      },
      "created_at": "2025-06-28T00:34:21.695Z",
      "flight_changes": null,
      "flight": {
        "id": 3795943,
        "need_apis": false,
        "cabin_class": "economy",
        "booking_class": "Y",
        "included_airport_tax": 66.6,
        "duration": "04:20",
        "departure_date": "2025-08-13 13:35:00",
        "arrival_date": "2025-08-13 16:55:00",
        "origin": {
          "iata_code": "AYT",
          "city_name": "Antalya",
          "country_name": "Turkey",
          "timezone": "Europe/Istanbul"
        },
        "destination": {
          "iata_code": "CDG",
          "city_name": "Paris",
          "country_name": "France",
          "timezone": "Europe/Paris"
        },
        "segments": [
          {
            "via_airport": null,
            "origin": {
              "iata_code": "AYT",
              "city_name": "Antalya",
              "country_name": "Turkey",
              "timezone": "Europe/Istanbul"
            },
            "destination": {
              "iata_code": "CDG",
              "city_name": "Paris",
              "country_name": "France",
              "timezone": "Europe/Paris"
            },
            "operating_carrier_flight_number": 421,
            "operating_carrier": {
                    "name": "Sunexpress",
                    "iata_code": "XQ"
            },
            "marketing_carrier_flight_number": 421,
            "marketing_carrier": {
                    "name": "Sunexpress",
                    "iata_code": "XQ"
            },
            "departure_date": "2025-08-13 13:35:00",
            "arrival_date": "2025-08-13 16:55:00"
          }
        ]
      },
      "flight": {
        "id": 3795943,
        "need_apis": false,
        "cabin_class": "economy",
        "booking_class": "Y",
        "included_airport_tax": 66.6,
        "duration": "04:20",
        "departure_date": "2025-08-13 13:35:00",
        "arrival_date": "2025-08-13 16:55:00",
        "origin": {
          "iata_code": "AYT",
          "city_name": "Antalya",
          "country_name": "Turkey",
          "timezone": "Europe/Istanbul"
        },
        "destination": {
          "iata_code": "CDG",
          "city_name": "Paris",
          "country_name": "France",
          "timezone": "Europe/Paris"
        },
        "segments": [
          {
            "via_airport": null,
            "origin": {
              "iata_code": "AYT",
              "city_name": "Antalya",
              "country_name": "Turkey",
              "timezone": "Europe/Istanbul"
            },
            "destination": {
              "iata_code": "CDG",
              "city_name": "Paris",
              "country_name": "France",
              "timezone": "Europe/Paris"
            },
            "operating_carrier_flight_number": 421,
            "operating_carrier": {
                    "name": "Sunexpress",
                    "iata_code": "XQ"
            },
            "marketing_carrier_flight_number": 421,
            "marketing_carrier": {
                    "name": "Sunexpress",
                    "iata_code": "XQ"
            },
            "departure_date": "2025-08-13 13:35:00",
            "arrival_date": "2025-08-13 16:55:00"
          }
        ]
      }
    }
  ]
}

# Update PNR (suppliers only)

The patchPNR endpoint is designed to update the pnr_airline field of a specific booking. If the airline PNR is not returned at booking time, then you should call this endpoint as soon as possible, once the PNR is available.

For suppliers only

This endpoint is reserved for suppliers only and should not be used by distribution partners. Distribution partners should only use the retrieve booking and flight information endpoint to get up-to-date flight & booking information.

The updated booking will be returned in the response.

PATCH

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

# Parameters

Parameter Type Status Description
pnr string required The internal CP pnr reference of the booking to be updated (ie starting with CP).

# Rules for PNR Identification

The PNR is not a unique identifier. To manage different travel segments, we follow these rules:

  • One-way: CPPNR
  • Outward: CPPNR-1
  • Return: CPPNR-2
# Examples:
  • A one-way trip will be identified as CP1234.
  • An outward trip will be identified as CP1234-1.
  • A return trip will be identified as CP1234-2.

# Payload

Parameter Type Status Description
pnr_airline string required The new PNR to update the booking with.

Example request

curl 'https://booking-api.citizenplane.com/v3/bookings/ABCDEF/pnr' \
-H 'Accept: application/json' \
-H 'Authorization: {your_api_token}'
-d '{
	"pnr_airline": "XXXXXX"
}'

Example response

{
  "id": 860451,
  "flight_id": 122649828,
  "request_id": 1533287,
  "cp_reference": "CP9I3P",
  "first_name": "John",
  "last_name": "Doe",
  "gender": "male",
  "email": "john.doe@citizenplane.com",
  "phonenumber": "610433851033",
  "address": "n/a",
  "country_code": "en",
  "postal_code": "n/a",
  "passenger_count": 0,
  "infant_count": 0,
  "pnr_airline": "XXXXXX"
}