The Apple Wallet .pkpass Format

A .pkpass file is an Apple Wallet pass: a ZIP archive whose pass.json describes a pass, whose manifest.json records a SHA-1 digest per member, and whose signature carries a detached PKCS#7 signature over the manifest. This document is the format reference for the readers in this project, and its findings were checked on 2026-10-10 against the sources at the end. It states what the format is; documents/10-pkpass-knowns-and-unknowns.md is its companion, and states how far each statement here can be trusted — which parts Apple documents, which were observed, which are only convention, and which are unknown. Every example uses the repository’s synthetic fixture in dataflow.in/pkpass/sample/ or an invented neutral value; no value from a real person’s pass appears here.

The Container

A .pkpass Is a ZIP

Apple’s Building a Pass says to create a PKCS #7 detached signature for the manifest, zip the resulting directory, and change the archive’s extension from .zip to .pkpass; the archived Package Structure chapter states the same.

Required Members

Member Status Purpose
pass.json required UTF-8 JSON object that defines the pass
manifest.json required maps each member path to a SHA-1 digest
signature required detached PKCS#7/CMS signature over manifest.json
icon.png required in practice Apple writes “All passes require an icon”; used in notifications, Mail attachments, and the lock screen

An archive missing pass.json is not a pass at all, whatever else it contains.

Optional Image Members

Apple loads pass images with the standard UIImage rules, so each family accepts an unsuffixed file plus @2x and @3x variants.

Family Typical role
logo drawn beside logoText in the header
strip a banner behind the primary fields
thumbnail a small image to the left of the primary fields
background a full-bleed image behind the pass
footer a narrow image at the bottom of a boarding pass

The optional families are exactly logo, strip, thumbnail, background, and footer; the icon is not optional, and Apple’s Pass Design and Creation restricts which styles may carry which families, as the style table below records.

Localization Directories and Personalization

A pass may carry one directory per language at its root, named <language>[-<region>].lproj/, each holding a pass.strings catalog and possibly localized copies of the images. Each localization folder must contain the same number of resolutions for an image, and an image of the same name in the top-level folder overrides every localized version. Apple’s Rewards Enrollment documentation adds an optional personalization.json for NFC reward cards, with personalizationLogo@2x.png and personalizationLogo@3x.png; a reader that does not implement enrollment can list the member and ignore it.

Compression

ZIP entries may be stored (method 0) or deflated (method 8), and both occur in real passes. A reader must honour each entry’s own compression method and must not assume that the first entry is pass.json.

manifest.json

manifest.json is a JSON object whose keys are member paths relative to the pass root and whose values are the SHA-1 digests of those members’ raw bytes, written as lowercase hexadecimal. Apple’s archived Package Structure says every file in the bundle appears in the manifest except the manifest itself and the signature.

The fixture’s manifest is short enough to show whole:

{
        "pass.json": "9d8e6778ee0d0d141e96641012225aa43e04b3f4",
        "icon.png": "2b7e4e13fe9603e28bb5ee5dbc31db8c882a98c3",
        "logo.png": "3c2bb1b8bac5e7f48f812e54cd711b344053ba84"
    }

The Signature

signature is a detached PKCS#7/CMS SignedData structure, DER-encoded, whose signed content is the raw byte sequence of manifest.json.

openssl smime -verify -inform DER -in signature -content manifest.json -binary -noverify

pass.json

pass.json is a single UTF-8 JSON object; Apple’s current documentation calls it the Pass object, and the archived reference calls the top level a dictionary.

Required Top-Level Keys

Key Type Notes
formatVersion number must be 1
passTypeIdentifier string must equal the pass type ID in the signing certificate
serialNumber string unique within the pass type identifier
teamIdentifier string the Apple Developer team ID, and it must match the certificate
organizationName localizable string display name of the issuing organization
description localizable string accessibility description, read by VoiceOver

Apple’s Common Problems checklist confirms the certificate pairings, and it treats organizationName and description as required, so both appear above rather than among the optional keys.

Optional Top-Level Keys

Key Type Notes
logoText localizable string text beside the logo; not used by poster event tickets
relevantDate ISO 8601 date string deprecated in favour of relevantDates
expirationDate ISO 8601 date string must include hours and minutes, seconds optional
voided boolean default false; marks the pass void
groupingIdentifier string event tickets and boarding passes only; groups passes of one style and type
sharingProhibited boolean default false; true hides the Share button
suppressStripShine boolean suppresses the strip’s shine; current documentation gives the default as true
maxDistance number relevance radius in metres; the system uses the smaller of this and its own default
associatedStoreIdentifiers array of numbers App Store IDs; Wallet uses the first compatible one
appLaunchURL string requires associatedStoreIdentifiers; not honoured on watchOS
userInfo any JSON opaque to Wallet and intended for a companion app
webServiceURL string must be HTTPS
authenticationToken string required with webServiceURL, and at least 16 characters
nfc object a pass.json key and not an archive member; message of at most 64 bytes, an encryptionPublicKey, and an optional requiresAuthentication
semantics object machine-readable tags for the pass and its fields
locations array of objects relevance locations, at most ten
beacons array of objects iBeacon relevance: proximityUUID required, major and minor are 16-bit unsigned integers

Pass Styles

A pass provides exactly one style key, and that key’s value is the pass structure dictionary holding the fields; the five styles are generic, storeCard, coupon, eventTicket, and boardingPass.

Style Front layout Images allowed
generic primary fields prominent logo, icon, thumbnail
storeCard primary fields prominent, with the strip behind them logo, icon, strip
coupon primary fields prominent, with the strip behind them logo, icon, strip
eventTicket primary fields render in the header row; secondary and auxiliary fields below logo, icon, strip, background, thumbnail
boardingPass header, then an origin/destination pair of primary fields, then secondary and auxiliary fields logo, icon, footer

The Field Model

The style dictionary holds up to six groups of field objects.

Group Role
headerFields a small row of labels above the primary fields
primaryFields the one field the pass is about
secondaryFields supporting values below the primary field
auxiliaryFields further values, usually on one or two rows
backFields the reverse of the pass
additionalInfoFields an “Additional Info” section on poster event tickets only

Per-Field Keys

Key Type Notes
key string required, and unique across the whole pass
value localizable string, date string, or number required; a date value must carry a time zone
label localizable string the caption drawn above or beside the value
attributedValue localizable string, date, or number overrides value; only an HTML <a href="…"> link is supported
changeMessage localizable format string must contain %@, replaced by the new value; it drives update notifications
textAlignment string PKTextAlignmentLeft, Center, Right, or Natural; not valid on primary or back fields
dateStyle string PKDateStyleNone, Short, Medium, Long, or Full
timeStyle string the same enumeration as dateStyle
currencyCode string ISO 4217 code; only when the value is a number
numberStyle string PKNumberStyleDecimal, Percent, Scientific, or SpellOut; only for numeric values
dataDetectorTypes array of strings back fields only; PKDataDetectorTypePhoneNumber, Link, Address, or CalendarEvent
semantics object semantic tags for this field
row number event-ticket auxiliary fields only
"generic": {
        "primaryFields": [ { "key": "holder", "value": "Ada Lovelace" } ],
        "secondaryFields": [ { "key": "event_name", "label": "EVENT", "value": "Example Event" } ],
        "backFields": [ { "key": "description", "label": "How to Use Your Barcode", "value": "Show your barcode to the event staff." } ]
    }

Colours

Apple documents four colour keys, all optional strings, all described as a CSS-style RGB triple.

Key Role
backgroundColor the pass background
foregroundColor the value text
labelColor the label text; when omitted the system chooses one
footerBackgroundColor the footer band of a poster event ticket

Barcodes

A pass may carry the legacy singular barcode object, the barcodes array, or both.

"barcode": {
        "format": "PKBarcodeFormatQR",
        "message": "example-payload-0001",
        "messageEncoding": "utf-8",
        "altText": "ID: 0000000001"
    }
Key Required Notes
format yes one of the format constants below
message yes the payload; it may itself be a JSON string
messageEncoding yes an IANA character set name such as iso-8859-1 or utf-8
altText no human-readable text drawn near the barcode; not shown on watchOS

Boarding Passes and Event Tickets

A boardingPass dictionary carries transitType, which Apple documents as required there and not allowed elsewhere; its values are PKTransitTypeAir, PKTransitTypeBoat, PKTransitTypeBus, PKTransitTypeGeneric, and PKTransitTypeTrain. Wallet uses the value for iconography, and a reader may map each to its own icon while rejecting the key on other styles. An eventTicket has no structural key beyond the field groups: its primary fields render in the header row, its groupingIdentifier groups related passes, and its auxiliary fields are the only place where row applies.

Localization

Localization is an indirection, not an overlay of the JSON tree: to localize a string, the pass.json value becomes a key, and that key is defined in every pass.strings catalog.

"primaryFields": [
        { "key": "offer", "value": "OfferAmount", "label": "OfferAmountLabel" }
    ]
/* en.lproj/pass.strings */
    "OfferAmount" = "100% off";
    "OfferAmountLabel" = "Anything you want!";

What This Project Does With the Format

The reader in this repository implements the following parts of the format, and nothing more.

The reference above describes more of the format than the code currently uses.

Sources

Apple, current documentation:

Apple, archived documentation:

Open-source readers and platform definitions: