Documentation Archive


Wallet Developer Guide

On This Page

Interacting with Passes in Your App

There are two main reasons apps interact with passes: to provide an integrated user experience or to serve as a conduit for passes. An event venue’s app is an example of an integrated user experience. This app can show the performance schedule, play short video clips, and let users buy tickets. After buying a ticket, it can add a pass for that ticket to Wallet and create an event in the user’s calendar. It can also include UI for managing the tickets that users have purchased. An email or instant messaging client is an example of an app serving as a conduit. Just as it supports attachments such as images, it can also support passes attached to a message like Mail does. The app can display UI that indicates that the message has a pass attached and allow users to add the pass to their library. Supporting passes in your app should add value for the user; avoid trying to duplicate functionality of the Wallet app.

Enabling Passbook Capabilities

Your app must have the appropriate entitlements before it can read, update, or delete passes. Use the Xcode Capabilities tab to turn on entitlements. If your provisioning profile is associated with multiple pass type identifiers, you can specify which of the identifiers your app can interact with. For more information, see Configuring Passbook for iOS Apps.

Accessing Passes

The PassKit framework provides model-level access to pass data. The PKPassLibrary class represents the pass library, and the PKPass class represents individual passes. The framework also provides a view controller, the PKAddPassesViewController class, which displays a pass and lets users add it to their pass library. Your app is responsible for the views it needs to display passes. To present a pass, use the passURL property of a pass to show it in Wallet.

  1. [[UIApplication sharedApplication] openURL:[pass passURL]]

A pass should not depend on your app to be useful. Passes need to be self-contained and useful by themselves, even if your app is not installed.

Checking Whether the Pass Library Is Available

The presence of the PassKit framework and its classes doesn’t mean that the pass library is available. To check for its availability, call the isPassLibraryAvailable method of the PKPassLibrary class.

Checking Whether a Pass Is in the Library

You can determine whether a pass is in the library even if you don’t have the entitlement to read the pass. This feature allows apps to act as a conduit for passes that they did not create. When you receive a new pass, check to see if it is in Wallet, and present the correct UI. If the pass is already in Wallet, indicate that the pass already exists. If the pass is not present, let users add it to Wallet.

To check whether a pass is in the library:

  1. Create an instance of the PKPass class for the pass.

  2. Create an instance of the PKPassLibrary class.

  3. Call the containsPass: method of the PKPassLibrary class with the pass you just created.

Getting Passes

Use the passes method of the PKPassLibrary class to get all passes that your app is entitled to access. Passes are returned in an arbitrary order. If your app displays a list of passes, it should sort them in some meaningful way such as by date.

To receive notifications when the pass library changes, register for the PKPassLibraryDidChangeNotification notification. Pass the instance of PKPassLibrary as the object. The pass library isn’t a singleton; each instance sends its own notifications, and you want the notifications from this particular instance. Use the addObserverForName:object:queue:usingBlock: method to specify that you want to respond on the main queue and provide a block to handle the notification. The user info dictionary of the notification describes what changed. Alternatively, use the dispatch_async and dispatch_get_main_queue functions to respond on the main thread.

Reading a Pass

Use the passWithPassTypeIdentifier:serialNumber: method of the PKPassLibrary class to read a particular pass from the pass library.

You can access certain common bits of data, such as the organization name and description, using the properties of the PKPass class. You can access the description using the localizedDescription method. These properties are useful if your app is acting as a conduit passes that you didn’t create, so you don’t know their fields’ keys.

You can access specific fields of a pass using the their key with the localizedValueForFieldKey: method. This method is useful if you created the pass, because then you know the keys for specific fields.

Adding a New Pass

To add a pass to the library:

  1. Create an instance of the PKPass class for the pass, initializing it with the pass’s data.

  2. Use the containsPass: method of the PKPassLibrary class to check whether the pass is in the library. Your app can use this method to detect the presence of a pass even if it doesn’t have the entitlements to read passes in the library.

  3. If the pass isn’t in the library, use an instance of the PKAddPassesViewController class to let the user add it.

    Present the add passes view controller modally, with animation.

Changing a Pass

Passes cannot be changed directly on the device. Changing the contents of a pass would invalidate its signature. An updated pass needs to be signed using your private key, and distributing your private key as part of your app would be a particularly poor security practice.

To change a pass, coordinate with your server:

  1. Your app connects to your server. It identifies the pass by serial number and pass type identifier and describes the change to your server.

  2. Your server updates your business records as needed, creates a new version of the pass, and signs it.

  3. Your app downloads the new pass from your server and uses the replacePassWithPass: method of the PKPassLibrary class to install it.

After creating a new version of the pass, your server should also send a push notification so that other devices with this pass installed will get the latest copy.

Removing a Pass

Use the removePass: method of the PKPassLibrary class to remove a pass.

Remember that passes belong to the user, not to your app. Passes should be removed only in response to a direct user action. Never remove a pass without the user’s consent, even if the pass has expired or is outdated.