Apple Wallet Integration for Boarding Passes in Mobile Apps
A boarding pass in Apple Wallet is a boardingPass-type .pkpass archive with strict field requirements: transitType is mandatory, and the structure of primaryFields/auxiliaryFields determines what users see on the lock screen. An error in transitType or missing required fields will cause Apple Wallet to display an "Invalid Pass Format" message.
Boarding Pass Structure
{
"formatVersion": 1,
"passTypeIdentifier": "pass.com.yourairline.boarding",
"serialNumber": "FLIGHT-SU123-20240615-IVANOV",
"teamIdentifier": "ABCDE12345",
"organizationName": "YourAirline",
"description": "Boarding Pass SU 123",
"foregroundColor": "rgb(255,255,255)",
"backgroundColor": "rgb(0,60,130)",
"boardingPass": {
"transitType": "PKTransitTypeAir",
"primaryFields": [
{ "key": "origin", "value": "SVO", "label": "From" },
{ "key": "destination", "value": "LED", "label": "To" }
],
"auxiliaryFields": [
{ "key": "flight", "value": "SU 123", "label": "Flight" },
{ "key": "seat", "value": "14A", "label": "Seat" },
{ "key": "date", "value": "2024-06-15T07:30+03:00", "label": "Departure",
"dateStyle": "PKDateStyleShort", "timeStyle": "PKDateStyleShort" }
],
"backFields": [
{ "key": "terms", "label": "Conditions", "value": "23 kg baggage included" }
],
"barcode": {
"message": "M1IVANOV/IVAN ABCDEF SVO LED SU 0123 165Y014A0047 100",
"format": "PKBarcodeFormatAztec",
"messageEncoding": "iso-8859-1"
}
},
"relevantDate": "2024-06-15T07:00+03:00"
}
transitType values: PKTransitTypeAir, PKTransitTypeTrain, PKTransitTypeBus, PKTransitTypeBoat, PKTransitTypeGeneric. The type affects the transport icon in the pass header.
For aviation, the barcode format is PKBarcodeFormatAztec (IATA 2D Barcode standard). QR codes also work, but Aztec codes read faster in poor lighting.
relevantDate and Geolocation
relevantDate displays the pass on the lock screen 15–30 minutes before the event. For airports, add locations:
"locations": [
{
"latitude": 55.9729,
"longitude": 37.4146,
"relevantText": "Check in for flight SU 123"
}
]
Wallet will notify users when they're near the airport.
Dynamic Fields: Real-time Flight Status Updates
The primary need for airlines is to update fields in real time. Wallet supports this via APN push:
- When a pass is added, the device registers itself via
POST /v1/devices/{deviceLibraryIdentifier}/registrations/{passTypeIdentifier}/{serialNumber} - When data changes (flight delay, gate change), the server sends a push to the
pushTokenfrom the registration request - The device requests the updated
.pkpassand replaces the old one
APN push payload for Wallet is minimal:
{
"aps": {}
}
An empty aps object tells Wallet to handle it. No notification text is needed.
Server-Side Generation and Signing
The archive is built on-the-fly for each passenger. Each pass is unique: serialNumber should identify the specific flight and passenger. After changing any file in the archive, recalculate manifest.json and regenerate signature.
On Node.js, use passkit-generator:
import { PKPass } from "passkit-generator";
const pass = await PKPass.from({
model: "./models/boarding-pass.pass",
certificates: {
wwdr: fs.readFileSync("./certs/wwdr.pem"),
signerCert: fs.readFileSync("./certs/pass.pem"),
signerKey: fs.readFileSync("./certs/pass.key"),
},
overrides: {
serialNumber: `FLIGHT-SU123-${passengerId}`,
description: `Boarding Pass ${flightNumber}`,
},
});
pass.setBarcodes({
message: bcbpData,
format: "PKBarcodeFormatAztec",
messageEncoding: "iso-8859-1",
});
const buffer = pass.getAsBuffer();
Timeline
2–3 days for server-side generation, signing, device registration, and push-based flight status updates. Pricing is calculated individually.







