PKPASS File Documentation


Summary

A Passbook Pass File (now called an Apple Wallet pass) is a digitally signed bundle holding a boarding pass, event ticket, loyalty card or coupon. It is a ZIP archive, so the file starts with the bytes 50 4B 03 04 (“PK”), and its MIME type is application/vnd.apple.pkpass. Inside are pass.json, image assets, a manifest.json of file hashes and a PKCS#7 signature. On iPhone a .pkpass opens in the built-in Wallet app; Android needs a third-party app such as PassWallet; on a PC you can rename it to .zip to look inside.

Technical details

FeatureValue
Full nameApple Wallet Pass (formerly Passbook)
File extension.pkpass (bundle of several: .pkpasses)
MIME typeapplication/vnd.apple.pkpass
Format typeZIP-based, digitally signed pass bundle (JSON + images + PKCS#7)
DeveloperApple Inc.
Introduced2012 (iOS 6, as Passbook); app renamed Wallet in iOS 9 (2015)
SpecificationApple Wallet Passes documentation
Open standardPartial — ZIP + JSON are open; signing needs an Apple certificate
Container / base formatZIP
Magic number (hex)50 4B 03 04 (“PK\x03\x04”, ZIP local file header)
Signature schemeDetached PKCS#7 over manifest.json
Pass data filepass.json
Integrity filemanifest.json (SHA-1 hash of every file)
Pass stylesBoarding pass, coupon, event ticket, store card, generic
Barcode typesQR, Aztec, PDF417, Code 128
UpdatesPush via the issuer’s web service; location/time triggers
Related extensions.pkpasses, .zip, .order
Specification URLdeveloper.apple.com/documentation/walletpasses
File signature (magic bytes)
50 4B 03 04

Offset 0, 4 bytes, ASCII PK\x03\x04 — the standard ZIP local file header, named after ZIP’s creator Phil Katz. A .pkpass is a ZIP archive, so it has no unique magic of its own; a reader distinguishes it from an ordinary ZIP by its contents, specifically the presence of pass.json, manifest.json and a signature file at the archive root. That is why renaming a .pkpass to .zip lets any archiver open it.

What is a PKPASS file?

A .pkpass file is a single pass for Apple Wallet: a boarding pass, event ticket, store loyalty card or coupon. Apple introduced the format with the Passbook app in iOS 6 in September 2012 and renamed the app to Wallet in iOS 9 in 2015; the file extension stayed .pkpass. Airlines, cinemas and retailers deliver these files by e-mail or through “Add to Apple Wallet” buttons.

Technically a PKPASS is a ZIP archive with a fixed internal layout and a cryptographic signature. The ZIP holds a JSON file describing the pass, a set of image assets, a manifest of file hashes, and a detached signature produced with a certificate that Apple issues to the pass creator. Wallet verifies that signature before it installs anything, so a hand-edited pass will not load. Everything below is about that bundle layout and how the signature binds it together.

The bundle layout inside the ZIP

Unzip a .pkpass and you find a flat set of files at the archive root. The required members are pass.json, manifest.json, a signature file and the icon images; the rest are optional artwork and localisations.

example.pkpass  (a ZIP archive)
 ├─ pass.json          all pass data: style, fields, barcode, colors
 ├─ manifest.json      SHA-1 hash of every other file in the bundle
 ├─ signature          detached PKCS#7 signature over manifest.json
 ├─ icon.png           required; shown in notifications and Mail
 ├─ icon@2x.png        Retina variants (2x, 3x)
 ├─ logo.png           header logo
 ├─ strip.png          optional style-specific artwork
 ├─ background.png     optional (event tickets)
 └─ en.lproj/          optional localized strings and images
     └─ pass.strings

The two files that make a PKPASS more than a plain ZIP are manifest.json and signature. Together they let Wallet prove that not one byte of the bundle has changed since the issuer signed it.

pass.json: styles, fields and the barcode payload

The heart of the bundle is pass.json, a UTF-8 JSON document. A few top-level keys are mandatory: formatVersion (currently 1), passTypeIdentifier (the reverse-DNS ID tied to the signing certificate, for example pass.com.airline.boarding), teamIdentifier (the issuer’s Apple Developer team), serialNumber and organizationName. Exactly one style key then selects the pass type and its field layout.

Style key in pass.jsonPass type
boardingPassAirline, train or bus boarding pass (has a transitType)
eventTicketConcert, cinema or sports ticket
couponDiscount or offer
storeCardLoyalty or membership card
genericAnything else (gym pass, ID)

Inside the style object, fields are grouped as headerFields, primaryFields, secondaryFields, auxiliaryFields and backFields, each an array of { key, label, value } objects that Wallet renders in fixed positions on the card. The scannable code lives in a barcodes array: each entry sets format (PKBarcodeFormatQR, PKBarcodeFormatAztec, PKBarcodeFormatPDF417 or PKBarcodeFormatCode128), a message string (the payload a scanner reads) and a messageEncoding (usually iso-8859-1). Optional relevantDate and locations keys are what make a pass surface on the lock screen near a venue or before a departure.

manifest.json and the PKCS#7 signature chain

Integrity is enforced in two steps. First, manifest.json is a flat JSON object mapping every filename in the bundle to the hex SHA-1 hash of that file’s bytes:

{
  "pass.json":  "e4f7c1...c9",
  "icon.png":   "a1b2c3...ff",
  "logo.png":   "9d8e7f...12"
}

Second, the signature file is a detached PKCS#7 signature computed over the bytes of manifest.json, using the issuer’s Pass Type ID certificate together with the Apple Worldwide Developer Relations intermediate certificate. When Wallet opens a pass it recomputes the SHA-1 of every file, checks each against manifest.json, then verifies the PKCS#7 signature over the manifest and confirms the certificate chains back to Apple. Change any file and its hash no longer matches the manifest; change the manifest and the signature no longer verifies. This is why editing pass.json after unzipping produces a pass that silently refuses to install: only the original issuer, holding the private key, can re-sign it.

Why a PKPASS is a ZIP but not just a ZIP

A PKPASS begins with the ZIP local-file-header signature 50 4B 03 04, so any archiver treats it as a normal archive; renaming .pkpass to .zip and extracting is the standard way to inspect one on a desktop. What distinguishes it is the required trio of pass.json, manifest.json and signature at the root, plus the reserved icon assets. The same “ZIP with a required member set” pattern is how many modern bundle formats work, including APK, DOCX and EPUB; the ZIP magic bytes are shared, and the contents tell the two apart.

Grouped passes: the .pkpasses container

A related extension, .pkpasses (note the plural), bundles several individual passes into one download, for example a family’s four boarding passes issued together. It too is a ZIP; inside are multiple .pkpass files plus a small manifest.json listing them. Wallet unpacks the group and adds each pass separately, verifying each one’s own signature.

Frequently asked questions

Why won’t an edited PKPASS install?

Because Wallet verifies the signature. manifest.json stores a SHA-1 hash of every file, and the signature file is a PKCS#7 signature over that manifest. Editing pass.json changes its hash, which breaks the manifest match, and you cannot re-sign the manifest without the issuer’s private certificate. Only the original issuer can produce an installable pass.

How can I see what is inside a PKPASS on a PC?

Copy the file, rename it from .pkpass to .zip, and open it with any archiver. You can read pass.json for the ticket details and open the barcode and logo images directly, since they are ordinary PNG files stored in the archive.

References