# API Reference

The CitizenPlane v4 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/v4.

This API implements an NDC-inspired layer, providing a standardized interface for distributors to search, offer, order and book flights through CitizenPlane's inventory.

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

# Authentication

The CitizenPlane v4 API uses API Key authentication. All requests must include a valid API key. Requests made without authentication will fail, as well as requests made over plain HTTP rather than HTTPS.

To get your API key, 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. Codes in the 5xx range indicate an internal error, which is rare.

All error responses include a message and a type field to help identify the issue.

# Error Types

Type Description
OFFER_NOT_AVAILABLE The requested offer is no longer available or has expired
OFFER_NOT_FOUND The specified offer could not be found
INVALID_REQUEST_PARAMETERS The request payload is invalid or missing required fields
INTERNAL_ERROR An internal server error has occurred
AUTHENTICATION_ERROR Authentication failed
ORDER_NOT_FOUND The specified order could not be found
RESERVATION_NOT_FOUND The specified reservation could not be found
CRITERIA_NOT_ALLOWED The search criteria is not supported (e.g. unsupported travel class)
ROUTE_NOT_OPERATED The requested route is not operated

# HTTP Status Codes Summary

Code Status Meaning
400 Bad Request Your request is invalid (e.g. payload doesn't match expected schema)
401 Unauthorized Your API key is wrong
404 Not Found The specified resource could not be found (e.g. offer, order, reservation)
500 Internal Server Error Error on CitizenPlane's end. Try again later and contact us if the issue remains

# Key concepts

The v4 API follows a structured booking flow:

  1. Search - Find available offers matching travel criteria
  2. Get Offer - Get detailed pricing for a specific flight combination
  3. Get Baggage - Retrieve available baggage options for an offer
  4. Get Fares - Retrieve all available fares for an offer
  5. Create Order - Create an order with passenger details and selected baggage
  6. Confirm Order - Confirm the order and trigger the booking
  7. Get Reservation - Retrieve the final reservation details including PNR

# Offers

An offer represents a flight itinerary with pricing. Offers are stored for 30 minutes after being retrieved via the Get Offer endpoint. Any order using an expired offer will fail.

# Orders

An order is created once passengers and baggage are selected. An order must be confirmed to trigger the actual booking. Once confirmed, a reservation is created. Orders must be confirmed within 15 minutes of creation.

# Reservations

A reservation is the final booking record. It contains the PNR, passenger details, and flight information.

# Connectivity Standard

All offers returned by this API are marked with connectivityStandard: "NDC", indicating NDC-inspired connectivity.

# Supported values

# Trip types

Value Description
ONE_WAY One-way trip
ROUND_TRIP Round trip

# Travel classes

Value Description
ECONOMY Economy class (currently the only supported class)

# Passenger types

Value Description
ADULT Adult passenger
CHILD Child passenger
INFANT Infant passenger (under 2 years old)

# Baggage types

Value Description
CHECK_IN Checked baggage
CABIN Cabin baggage

# Location types

Value Description
AIRPORT IATA airport code (e.g. CDG)
CITY IATA city code (e.g. PAR)

# Endpoints

# Search Offers

Search for available flight offers matching the given travel criteria. Returns a list of offers with pricing for one-way or round-trip itineraries. This endpoint supports both airport and city codes for origin/destination.

POST

https://booking-api.citizenplane.com/v4/search

WARNING

Only ECONOMY travel class is currently supported. Searching with any other travel class will return an empty result.

# Body parameters

Parameter Type Status Description
adults integer required Number of adults (min 1, max 9)
children integer required Number of children (min 0, max 9)
infants integer required Number of infants (min 0, max = adults)
tripType string required ONE_WAY or ROUND_TRIP
travelClass string optional Travel class. Defaults to ECONOMY
outboundSegment object required Outbound segment details. See segment parameters
inboundSegment object required if round trip Inbound segment details (required when tripType is ROUND_TRIP). See segment parameters

# Search segment parameters

Parameter Type Status Description
origin object required Origin location with code (3-letter IATA code) and type (AIRPORT or CITY)
destination object required Destination location with code (3-letter IATA code) and type (AIRPORT or CITY)
departureDate string required Departure date. Expected format: YYYY-MM-DD

Example request

curl 'https://booking-api.citizenplane.com/v4/search' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: {your_api_key}' \
-d '{
  "adults": 1,
  "children": 0,
  "infants": 0,
  "tripType": "ONE_WAY",
  "travelClass": "ECONOMY",
  "outboundSegment": {
    "origin": {
      "code": "CDG",
      "type": "AIRPORT"
    },
    "destination": {
      "code": "AYT",
      "type": "AIRPORT"
    },
    "departureDate": "2025-08-06"
  },
  "inboundSegment": null
}'

Example response

{
  "offers": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "outboundSegment": {
        "sections": [
          {
            "origin": "CDG",
            "destination": "AYT",
            "departureDate": "2025-08-06T17:45:00",
            "arrivalDate": "2025-08-06T22:40:00",
            "travelClass": "ECONOMY",
            "availableSeats": 10,
            "flightNumber": "511",
            "operatingCarrierCode": "XQ",
            "marketingCarrierCode": "XQ",
            "technicalStops": []
          }
        ]
      },
      "fare": {
        "hasPriorityBoardingIncluded": false,
        "hasFastTrackIncluded": false,
        "hasFreeSeatsAvailable": false,
        "passengerPricingByPassengerType": {
          "ADULT": {
            "fareAmount": {
              "amount": 627.27,
              "currency": "EUR"
            },
            "taxAmount": {
              "amount": 0,
              "currency": "EUR"
            },
            "numberOfPassengers": 1
          }
        },
        "includedBaggage": {
          "checkedBaggageQuantity": 1,
          "cabinBaggageQuantity": 1
        },
        "price": {
          "totalAmount": 627.27,
          "sourceAmount": 627.27,
          "currency": "EUR"
        }
      },
      "paymentOptions": [
        {
          "type": "cash",
          "fee": {
            "amount": 0,
            "currency": "EUR"
          }
        }
      ],
      "connectivityStandard": "NDC"
    }
  ]
}

# Get Offer

Retrieve detailed offer information for a specific flight combination. This endpoint verifies availability and pricing with the supplier and returns a complete offer with fare details, passenger information requirements, and an offer ID that can be used to create an order.

The offer is stored in cache for 30 minutes.

POST

https://booking-api.citizenplane.com/v4/offer

# Body parameters

Parameter Type Status Description
adults integer required Number of adults (min 1, max 9)
children integer required Number of children (min 0, max 9)
infants integer required Number of infants (min 0, max = adults)
tripType string required ONE_WAY or ROUND_TRIP
travelClass string optional Travel class. Defaults to ECONOMY
isResidentDiscountEligible boolean required Whether the passenger is eligible for resident discount (must be false)
outboundSegment object required Outbound segment with sections. See offer segment parameters
inboundSegment object required if round trip Inbound segment with sections (required when tripType is ROUND_TRIP)

# Offer segment parameters

Each segment contains an array of sections:

Parameter Type Status Description
origin string required 3-letter IATA airport code
destination string required 3-letter IATA airport code
departureDate string required Departure date. Format: YYYY-MM-DDTHH:mm:ss
arrivalDate string required Arrival date. Format: YYYY-MM-DDTHH:mm:ss
flightNumber string required Flight number (1-4 digits)
operatingCarrierCode string required 2-letter IATA operating carrier code
marketingCarrierCode string required 2-letter IATA marketing carrier code
travelClass string optional Travel class. Defaults to ECONOMY

Example request

curl 'https://booking-api.citizenplane.com/v4/offer' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: {your_api_key}' \
-d '{
  "adults": 1,
  "children": 0,
  "infants": 0,
  "tripType": "ONE_WAY",
  "travelClass": "ECONOMY",
  "isResidentDiscountEligible": false,
  "outboundSegment": {
    "sections": [
      {
        "origin": "CDG",
        "destination": "AYT",
        "departureDate": "2025-08-06T17:45:00",
        "arrivalDate": "2025-08-06T22:40:00",
        "flightNumber": "511",
        "operatingCarrierCode": "XQ",
        "marketingCarrierCode": "XQ"
      }
    ]
  },
  "inboundSegment": null
}'

Example response

{
  "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
  "outboundSegment": {
    "sections": [
      {
        "origin": "CDG",
        "destination": "AYT",
        "departureDate": "2025-08-06T17:45:00",
        "arrivalDate": "2025-08-06T22:40:00",
        "travelClass": "ECONOMY",
        "flightNumber": "511",
        "departureTerminal": "1",
        "arrivalTerminal": "1",
        "operatingCarrierCode": "XQ",
        "marketingCarrierCode": "XQ",
        "technicalStops": []
      }
    ]
  },
  "cheapestFare": {
    "id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
    "hasPriorityBoardingIncluded": false,
    "hasFastTrackIncluded": false,
    "hasFreeSeatsAvailable": false,
    "passengerPricingByPassengerType": {
      "ADULT": {
        "fareAmount": {
          "amount": 627.27,
          "currency": "EUR"
        },
        "taxAmount": {
          "amount": 0,
          "currency": "EUR"
        },
        "numberOfPassengers": 1
      }
    },
    "includedBaggage": [
      {
        "quantity": 1,
        "descriptor": { "weight": 20 },
        "type": "CHECK_IN"
      },
      {
        "quantity": 1,
        "descriptor": {
          "weight": 10,
          "dimensions": { "width": 56, "height": 45, "depth": 25 }
        },
        "type": "CABIN"
      }
    ],
    "totalPrice": {
      "amount": 627.27,
      "currency": "EUR"
    }
  },
  "providerAdditionalPassengerInformationByPassengerType": {
    "ADULT": {
      "providerIdentificationTypeOptions": ["PASSPORT"],
      "providerRequiredAdditionalFields": ["BIRTH_DATE"]
    }
  },
  "paymentOptions": [
    {
      "type": "cash",
      "fee": {
        "amount": 0,
        "currency": "EUR"
      }
    }
  ],
  "connectivityStandard": "NDC",
  "validatingCarrier": "XQ"
}

# Get All Fares

Retrieve all available fare options for a given offer.

GET

https://booking-api.citizenplane.com/v4/offer/{offerId}/fares

# Path parameters

Parameter Type Status Description
offerId string required UUID of the offer

Example request

curl 'https://booking-api.citizenplane.com/v4/offer/b2c3d4e5-f6a7-8901-bcde-f12345678901/fares' \
-H 'Accept: application/json' \
-H 'Authorization: {your_api_key}'

# Get Baggage

Retrieve available baggage options (checked and cabin) for a given offer. This returns paid baggage options that are not included in the base fare.

GET

https://booking-api.citizenplane.com/v4/offer/{offerId}/baggage

# Path parameters

Parameter Type Status Description
offerId string required UUID of the offer

Example request

curl 'https://booking-api.citizenplane.com/v4/offer/b2c3d4e5-f6a7-8901-bcde-f12345678901/baggage' \
-H 'Accept: application/json' \
-H 'Authorization: {your_api_key}'

Example response

{
  "fareBaggageOptions": [
    {
      "fareId": "c3d4e5f6-a7b8-9012-cdef-123456789012",
      "itineraryOptions": [],
      "outboundSegmentOptions": [
        {
          "type": "CHECK_IN",
          "maxPiecesPerPassenger": 1,
          "maxKilosPerPiece": 20,
          "pricePerPiece": {
            "amount": 36.05,
            "currency": "EUR"
          }
        },
        {
          "type": "CABIN",
          "maxPiecesPerPassenger": 1,
          "maxKilosPerPiece": 10,
          "pricePerPiece": {
            "amount": 15.00,
            "currency": "EUR"
          }
        }
      ],
      "inboundSegmentOptions": null
    }
  ]
}

# Create Order

Create an order for a previously retrieved offer. This step validates the offer, creates internal booking requests, and returns an order with pricing and passenger details.

POST

https://booking-api.citizenplane.com/v4/order?offerId={offerId}&fareId={fareId}

Offer expiration

The offer must still be valid (within 30 minutes of retrieval). If the offer has expired, a new one must be obtained via the Get Offer endpoint.

# Query parameters

Parameter Type Status Description
offerId string required UUID of the offer
fareId string required UUID of the fare within the offer

# Body parameters

Parameter Type Status Description
passengers array required Array of passenger objects. See passenger parameters
selectedBaggage array required Array of baggage selections per passenger. See baggage parameters
selectedSeats array required Array of seat selections (currently empty)
customerContact object required Contact information. See customer contact parameters
paymentMethod object required Payment method. Must be { "cash": true }

# Order passenger parameters

Parameter Type Status Description
number integer required Passenger number (sequential)
type string required ADULT, CHILD, or INFANT
title string required MR, MRS, or MS
name string required Passenger's first name
firstLastName string required Passenger's first last name
secondLastName string optional Passenger's second last name
gender string required MALE or FEMALE
birthDate string optional Date of birth. Format: YYYY-MM-DD. Required for children and infants. Required for adults unless the supplier allows optional DOB.
nationalityCountryCode string optional 2-letter country code
identification object optional Identification document. See identification parameters
phone object optional Phone number with number and countryCode fields

# Identification parameters

Parameter Type Status Description
type string required PASSPORT, NIE, NIF, NATIONAL_ID_CARD, or BIRTH_DATE
identificationNumber string required The identification document number
expirationDate string required Expiration date. Format: YYYY-MM-DD. Must be in the future
issueCountryCode string required 2-letter country code of issue

# Order baggage parameters

Parameter Type Status Description
passengerNumber integer required The passenger number this baggage selection applies to
itineraryBaggageSelection array required Baggage for the whole itinerary (usually empty)
outboundSegmentBaggageSelection array required Baggage for outbound segment
inboundSegmentBaggageSelection array optional Baggage for inbound segment (for round trips)

Each baggage selection item:

Parameter Type Status Description
type string required CHECK_IN or CABIN
numberOfPieces integer required Number of bags
kilosPerPiece integer required Weight per bag in kg

# Customer contact parameters

Parameter Type Status Description
name string required Contact first name
lastNames string required Contact last names
email string required Contact email
countryCode string required 2-letter country code
phone object required Phone with number and countryCode fields
address string required Contact address
cityName string required Contact city
zipCode string required Contact postal code

Example request

curl 'https://booking-api.citizenplane.com/v4/order?offerId=b2c3d4e5-f6a7-8901-bcde-f12345678901&fareId=c3d4e5f6-a7b8-9012-cdef-123456789012' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: {your_api_key}' \
-d '{
  "passengers": [
    {
      "number": 1,
      "type": "ADULT",
      "title": "MR",
      "name": "John",
      "firstLastName": "Doe",
      "secondLastName": null,
      "gender": "MALE",
      "birthDate": "1990-01-15",
      "nationalityCountryCode": "FR",
      "identification": {
        "type": "PASSPORT",
        "identificationNumber": "ABCDE123",
        "expirationDate": "2030-01-01",
        "issueCountryCode": "FR"
      },
      "phone": {
        "number": "+33600000000",
        "countryCode": "FR"
      }
    }
  ],
  "selectedBaggage": [
    {
      "passengerNumber": 1,
      "itineraryBaggageSelection": [],
      "outboundSegmentBaggageSelection": [
        {
          "type": "CHECK_IN",
          "numberOfPieces": 1,
          "kilosPerPiece": 20
        }
      ],
      "inboundSegmentBaggageSelection": null
    }
  ],
  "selectedSeats": [],
  "customerContact": {
    "name": "John",
    "lastNames": "Doe",
    "email": "john.doe@example.com",
    "countryCode": "FR",
    "phone": {
      "number": "+33600000000",
      "countryCode": "FR"
    },
    "address": "123 Rue de Paris",
    "cityName": "Paris",
    "zipCode": "75001"
  },
  "paymentMethod": {
    "cash": true
  }
}'

Example response

{
  "id": "d4e5f6a7-b8c9-0123-defg-234567890123",
  "offer": {
    "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
    "outboundSegment": {
      "sections": [
        {
          "origin": "CDG",
          "destination": "AYT",
          "departureDate": "2025-08-06T17:45:00",
          "arrivalDate": "2025-08-06T22:40:00",
          "travelClass": "ECONOMY",
          "flightNumber": "511",
          "departureTerminal": "1",
          "arrivalTerminal": "1",
          "operatingCarrierCode": "XQ",
          "marketingCarrierCode": "XQ",
          "technicalStops": []
        }
      ]
    },
    "fare": {
      "id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
      "hasPriorityBoardingIncluded": false,
      "hasFastTrackIncluded": false,
      "hasFreeSeatsAvailable": false,
      "passengerPricingByPassengerType": {
        "ADULT": {
          "fareAmount": {
            "amount": 627.27,
            "currency": "EUR"
          },
          "taxAmount": {
            "amount": 0,
            "currency": "EUR"
          },
          "numberOfPassengers": 1
        }
      },
      "includedBaggage": [
        {
          "quantity": 1,
          "descriptor": { "weight": 20 },
          "type": "CHECK_IN"
        }
      ],
      "totalPrice": {
        "amount": 627.27,
        "currency": "EUR"
      }
    },
    "connectivityStandard": "NDC"
  },
  "passengers": [
    {
      "number": 1,
      "type": "ADULT",
      "title": "MR",
      "name": "John",
      "firstLastName": "Doe",
      "gender": "MALE",
      "birthDate": "1990-01-15",
      "nationalityCountryCode": "FR",
      "identification": {
        "type": "PASSPORT",
        "identificationNumber": "ABCDE123",
        "expirationDate": "2030-01-01",
        "issueCountryCode": "FR"
      }
    }
  ],
  "selectedBaggage": [
    {
      "passengerNumber": 1,
      "itineraryBaggageSelection": [],
      "outboundSegmentBaggageSelection": [
        {
          "type": "CHECK_IN",
          "numberOfPieces": 1,
          "kilosPerPiece": 20,
          "pricePerPiece": {
            "amount": 36.05,
            "currency": "EUR"
          }
        }
      ],
      "inboundSegmentBaggageSelection": []
    }
  ],
  "selectedSeats": [],
  "customerContact": {
    "name": "John",
    "lastNames": "Doe",
    "email": "john.doe@example.com",
    "countryCode": "FR",
    "phone": {
      "number": "+33600000000",
      "countryCode": "FR"
    },
    "address": "123 Rue de Paris",
    "cityName": "Paris",
    "zipCode": "75001"
  },
  "status": "OPEN",
  "totalPrice": {
    "amount": 663.32,
    "currency": "EUR"
  }
}

# Confirm Order

Confirm a previously created order. This triggers the actual booking process. The order status will change to CONFIRMING and a reservation ID will be generated.

POST

https://booking-api.citizenplane.com/v4/order/{orderId}/confirm

WARNING

An order can only be confirmed once. Duplicate confirmation requests will be rejected.

# Path parameters

Parameter Type Status Description
orderId string required UUID of the order to confirm

Example request

curl -X POST 'https://booking-api.citizenplane.com/v4/order/d4e5f6a7-b8c9-0123-defg-234567890123/confirm' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: {your_api_key}'

Example response

{
  "id": "d4e5f6a7-b8c9-0123-defg-234567890123",
  "offer": {
    "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
    "outboundSegment": { "sections": [...] },
    "fare": { ... },
    "connectivityStandard": "NDC"
  },
  "passengers": [...],
  "selectedBaggage": [...],
  "selectedSeats": [],
  "customerContact": { ... },
  "status": "CONFIRMING",
  "reservationId": "e5f6a7b8-c9d0-1234-efgh-345678901234",
  "totalPrice": {
    "amount": 663.32,
    "currency": "EUR"
  }
}

# Get Order

Retrieve the current status and details of an order.

GET

https://booking-api.citizenplane.com/v4/order/{orderId}

# Path parameters

Parameter Type Status Description
orderId string required UUID of the order

Example request

curl 'https://booking-api.citizenplane.com/v4/order/d4e5f6a7-b8c9-0123-defg-234567890123' \
-H 'Accept: application/json' \
-H 'Authorization: {your_api_key}'

# Get Reservation by ID

Retrieve reservation details using the reservation ID. The reservation contains the PNR, passenger details, flight segments, baggage, and fare information.

GET

https://booking-api.citizenplane.com/v4/reservation/{reservationId}

# Path parameters

Parameter Type Status Description
reservationId string required UUID of the reservation

Example request

curl 'https://booking-api.citizenplane.com/v4/reservation/e5f6a7b8-c9d0-1234-efgh-345678901234' \
-H 'Accept: application/json' \
-H 'Authorization: {your_api_key}'

Example response

{
  "id": "e5f6a7b8-c9d0-1234-efgh-345678901234",
  "orderId": "d4e5f6a7-b8c9-0123-defg-234567890123",
  "pnr": "CPABCD",
  "email": "john.doe@example.com",
  "outboundSegment": {
    "sections": [
      {
        "origin": "CDG",
        "destination": "AYT",
        "departureDate": "2025-08-06T17:45:00",
        "arrivalDate": "2025-08-06T22:40:00",
        "travelClass": "ECONOMY",
        "flightNumber": "511",
        "departureTerminal": "1",
        "arrivalTerminal": "1",
        "operatingCarrierCode": "XQ",
        "marketingCarrierCode": "XQ",
        "technicalStops": []
      }
    ]
  },
  "passengers": [
    {
      "number": 1,
      "type": "ADULT",
      "title": "MR",
      "name": "John",
      "firstLastName": "Doe",
      "gender": "MALE",
      "birthDate": "1990-01-15",
      "nationalityCountryCode": "FR"
    }
  ],
  "selectedBaggage": [...],
  "selectedSeats": [],
  "customerContact": { ... },
  "fare": { ... }
}

# Get Reservation by Order ID

Retrieve reservation details using the order ID instead of the reservation ID.

GET

https://booking-api.citizenplane.com/v4/reservation?orderId={orderId}

# Query parameters

Parameter Type Status Description
orderId string required UUID of the order

Example request

curl 'https://booking-api.citizenplane.com/v4/reservation?orderId=d4e5f6a7-b8c9-0123-defg-234567890123' \
-H 'Accept: application/json' \
-H 'Authorization: {your_api_key}'

The response format is the same as the Get Reservation by ID endpoint.