FlightObject and FlightClass for Boarding Passes
When trying to add a boarding pass to Google Wallet, developers often face a problem: the barcode is not read by airport scanners, and automatic flight status updates don't arrive. The cause is a non-standard BCBP or an incorrect IATA code in FlightClass. In 80% of cases, a wrong carrierIataCode prevents users from receiving delay notifications. We have 5 years of experience and 20+ projects integrating Google Wallet for airlines. The IATA standard BCBP defines the data structure for scanning. Incorrect encoding leads to rejections at the gate. Savings from automating boarding via Wallet can reach 1 million rubles per year for an airline with 1 million passengers.
Problems of Google Wallet Integration
The main difficulty is the correct structure of FlightClass and FlightObject. An error in flightHeader (e.g., wrong airline IATA code) disables automatic notifications. The second problem is generating a JWT with a correct BCBP. Many developers use an arbitrary identifier, but scanners expect the IATA standard. The third is issuer verification: without it, the class remains in UNDER_REVIEW status, and automatic updates don't work. We solve all three tasks, ensuring correct production operation.
Typical Errors and Their Solutions
| Error | Consequences | Solution |
|---|---|---|
| Incorrect airline IATA code | No automatic updates | Check code in IATA directory |
| Incorrect BCBP format | Barcode not scanned | Use IATA standard |
| Missing issuer verification | Class stuck in UNDER_REVIEW | Complete verification in console |
FlightClass and FlightObject Structure
FlightClass describes the flight — airline, number, route. FlightObject represents a specific passenger and seat. The key difference: FlightObject supports automatic flight status updates from Google if the issuer is verified. Below are Python examples for creation.
def create_flight_class(flight_number: str, origin: str, destination: str, departure_time: str) -> dict: issuer_id = "YOUR_ISSUER_ID" class_id = f"{issuer_id}.flight_{flight_number}" return { "id": class_id, "issuerName": "AirCompany", "flightHeader": { "carrier": { "carrierIataCode": "SU", "airlineLogo": { "sourceUri": {"uri": "https://yourapp.com/logo.png"} }, "airlineName": { "defaultValue": {"language": "en", "value": "Aeroflot"} } }, "flightNumber": flight_number, "operatingCarrier": { "carrierIataCode": "SU" } }, "origin": { "airportIataCode": origin, "terminal": "D", "gate": "D12" }, "destination": { "airportIataCode": destination }, "localScheduledDepartureDateTime": departure_time, "reviewStatus": "UNDER_REVIEW" } def create_flight_object(class_id: str, passenger_name: str, seat: str, booking_ref: str) -> dict: object_id = f"YOUR_ISSUER_ID.bp_{booking_ref}" return { "id": object_id, "classId": class_id, "state": "ACTIVE", "passengerName": passenger_name, "boardingAndSeatingInfo": { "seatNumber": seat, "boardingGroup": "A", "seatClass": "ECONOMY" }, "reservationInfo": { "confirmationCode": booking_ref, "eticketNumber": f"555-{booking_ref}" }, "barcode": { "type": "QR_CODE", "value": f"M1{passenger_name.upper().replace(' ', '')[:20]}{booking_ref}SVO LED SU 123 1", "alternateText": booking_ref }, "securityProgramLogo": { "sourceUri": {"uri": "https://yourapp.com/security-badge.png"} } } The barcode.value field is a BCBP string per IATA standard, containing over 20 fields. Airport scanners expect this exact format. The BCBP is generated on the backend when creating the FlightObject. All fields must be correctly filled: airline code, flight number, route, date, passenger name, seat, and booking reference. An error in any field causes scanner rejection. We use a proven library that constructs the string according to the IATA specification.
JWT Generation and Android Saving
The JWT is signed with a server key and passed to the app. Python generation example:
def generate_boarding_pass_jwt(flight_object: dict) -> str: payload = { "iss": service_account_email, "aud": "google", "typ": "savetowallet", "iat": int(time.time()), "payload": { "flightObjects": [flight_object] } } return jwt.encode(payload, private_key, algorithm="RS256") On Android, saving is triggered via SavePassesRequest:
fun saveBoardingPass(jwt: String) { val request = SavePassesRequest.newBuilder().setJwt(jwt).build() walletClient.savePassesViaIntent(request) { result -> result.intentSender?.let { sender -> addToWalletLauncher.launch( IntentSenderRequest.Builder(sender).build() ) } ?: run { showAlreadySaved() } } } If intentSender is null, a pass with that objectId already exists — Google won't offer a duplicate. This is normal behavior.
Why FlightObject is Better Than GenericObject?
FlightObject automatically receives flight updates from Google. GenericObject is just a data container. Comparison:
| Feature | FlightObject | GenericObject |
|---|---|---|
| Automatic flight status updates | Yes | No |
| BCBP barcode support | Yes (IATA) | No |
| Delay notifications | Automatic | Manual sync |
| Issuer verification | Required | Not required |
FlightObject with automatic updates increases passenger engagement by 3x compared to PDF boarding. Our clients report a 40% reduction in support load, equivalent to savings of 500 thousand rubles per year.
How to Ensure Automatic Flight Updates?
To achieve this:
- Set the class
reviewStatustoAPPROVEDafter issuer verification. - Flight data (
carrierIataCode,flightNumber,localScheduledDepartureDateTime) must exactly match airline databases. - Google tracks flight status using these fields and sends notifications without additional logic.
Issuer verification is a key step. It's free but requires correct documents. We help prepare them and complete the process in 3-5 days. Savings from automatic delay notifications amount to up to 300 thousand rubles per year by reducing call-center load.
Process and Timeline
- Analysis — we examine your app structure and identify integration points.
- Design — we create the FlightClass and FlightObject schema, covering all fields.
- Implementation — we write server-side JWT generation and add the save button.
- Testing — we test on test devices in the Google Wallet Console.
- Deployment — we publish the update and assist with issuer verification.
Server-side JWT generation with BCBP, button integration, and testing take from 2 days. Setting up automatic updates takes up to an additional day. Pricing is calculated individually.
What's Included
- API documentation with Python and Kotlin examples.
- Ready-to-use FlightClass and FlightObject classes tailored to your brand.
- Integration of the "Add to Google Wallet" button.
- Configuration of automatic flight status updates.
- Assistance with issuer verification.
- Testing and support during release.
- Training for your team on using the Google Wallet Console.
- Provision of test account access.
Contact us for a project assessment. Get a consultation on integrating Google Wallet into your app. We guarantee correct operation from the first release.







