How Wallet Pass Updates and Push Notifications Work
By Michael Chora · Published · Last updated
A wallet pass is not a static file. After a customer adds it, you can change what it shows (a points balance, a status, an expiry date) and send a message that appears on the lock screen, without the customer doing anything. The two wallets do this differently. Apple Wallet uses a web service you host plus an Apple push that carries no data, only a nudge to go and fetch the new pass. Google Wallet stores the pass on Google's servers and you change it by calling Google's REST API. This guide explains both flows, what a notification actually is, and the limits to design around.
The short version
| Apple Wallet | Google Wallet | |
|---|---|---|
| Where the pass lives | A signed file on the device | An object on Google's servers |
| How you change it | Update the pass on your server, then send a push | PATCH the pass object through the REST API |
| What the push carries | Nothing. It tells the device to check for updates | Not applicable. Google syncs the change |
| Lock-screen message | A field with a change message changes | You add a message to the pass object |
| What you must run | A web service and a push sender (or a platform that does) | API calls with a service account |
How Apple Wallet pass updates work
Apple's design is described in Adding a web service to update passes. The moving parts:
- The pass declares a web service. The
pass.jsoninside the.pkpassincludes awebServiceURL(it must be HTTPS) and anauthenticationToken, a secret the device sends back with every request. - The device registers. When the customer adds the pass, their device calls your server to say it has this pass and where to reach it. The request is
POST /v1/devices/{deviceLibraryIdentifier}/registrations/{passTypeIdentifier}/{serialNumber}, with apushTokenin the body (Apple: register a pass for update notifications). Your server stores the pair. - You change the pass and send a push. When something changes, your server sends a push through the Apple Push Notification service to each registered
pushToken. The push has no payload. It only means "check for updates". - The device asks what changed. It calls
GET /v1/devices/{deviceLibraryIdentifier}/registrations/{passTypeIdentifier}?passesUpdatedSince={tag}and receives the serial numbers that changed. - The device downloads the new pass. It calls
GET /v1/passes/{passTypeIdentifier}/{serialNumber}with anIf-Modified-Sinceheader. You return304 Not Modifiedif nothing has changed, otherwise the new signed.pkpass. - Every request is authenticated. The device sends
Authorization: ApplePass {authenticationToken}; your server rejects anything that does not match.
If the customer removes the pass, the device unregisters with a DELETE to the registration URL, so you stop sending pushes to it.
Two things follow from this design. First, the push is only a nudge, so a lost or delayed push is not data loss: the next time the device refreshes, it will pick up the change. Second, the signing certificate matters for every update, because each new .pkpass you serve must be signed. That is why certificate expiry is the most common cause of updates silently stopping.
How a lock-screen message appears on Apple Wallet
A push does not show a banner by itself. Apple shows a notification when a field on the pass changes and that field has a change message defined in pass.json (the changeMessage key, which uses a %@ placeholder for the new value). For example, a balance field with the change message "Your balance is now %@" produces that sentence on the lock screen when the balance changes. If no field with a change message changes, the pass updates quietly.
Customers can switch notifications off per pass from the back of the pass, so treat the lock screen as a privilege, not a guaranteed channel.
How Google Wallet pass updates work
Google keeps the pass on its own servers, so there is no web service to host. You create a pass class (the shared design) and a pass object (one customer's pass), then change the object when something happens:
- Update fields: call
PATCHon the object, for examplePATCH /loyaltyObject/{id}, with only the fields that changed (Google: LoyaltyObject). The change syncs to the customer's saved pass. - Send a message: call the object's
addMessagemethod (Google: addMessage). A message can be shown on the pass and, depending on its type, trigger a notification. Google limits how often notifications fire, so check the current rules in the docs before building a campaign around them. - Change the design for everyone: patch the class instead of each object.
The Laravel tutorial shows a working PATCH for a stamp count.
What a "push notification" really is on a pass
It is a lock-screen message tied to a pass the customer chose to keep. It is not an SMS and not an app notification. That has practical consequences:
- It only reaches installed passes. A pass that was issued but never added cannot receive anything.
- It is private to the device and can be disabled by the customer.
- Content should be short and tied to the pass: a reward is ready, a membership expires soon, a ticket time changed.
- It is not guaranteed instant. Delivery depends on the device being online and the wallet's own scheduling.
Doing this without running the infrastructure
Running the Apple web service, keeping the push sender healthy and renewing the certificate are real, ongoing jobs. A platform removes them. On Shakewell Wallet:
- Edit a template and installed passes receive the new design. Update one customer's pass from the dashboard or with
PUT /wallet-passes/{passId}(Passes API). - Send a message to one pass or many with the push notifications API. The message is capped at 1,000 characters. A pass that is not installed returns
PASS_NOT_INSTALLED, and a send to every pass on a template is queued rather than delivered instantly. - React to loyalty events (points earned, reward redeemed, tier changes) with webhooks.
The help article on updating a pass after install covers the dashboard side.
Design rules that save you trouble
- Put volatile data in changeable fields, not in the barcode or the image. A barcode that encodes a balance goes stale; a barcode that encodes an ID does not.
- Make updates idempotent. Sending the same state twice should be harmless.
- Expect partial installs. Some customers will never add the pass; do not count them in notification reach.
- Test the whole loop on devices: change a field, confirm the pass updates, confirm the message appears.
- Keep messages rare. Customers who turn notifications off for a pass rarely turn them back on.
Common questions
Do customers need to open an app to see an update? No. The wallet refreshes the pass in the background; on Apple Wallet, pulling down on the back of the pass also refreshes it.
Can I update a pass that was already installed years ago? Yes, as long as the pass is still valid and, for Apple, you still have a valid certificate for its Pass Type ID.
What happens if the customer is offline? The update applies the next time the device can reach the wallet's servers.