Apple Wallet Silent Push Notification not triggering GET /passes endpoint

Hello,

We’re developing a loyalty program using Apple Wallet passes, and everything works except the silent push update flow.

Context PassTypeIdentifier: pass.order.com.lealtad.xxxx

Device is physical (not simulator)

Pass is installed and visible in Wallet

Correct pushToken is stored in our backend

Push response from APNs:

StatusCode: 200 OK apns-id: DBFF9693-D053-AA20-D737-3B24414105F3 WebServiceURL is reachable: https://xxxxx.net

GET /passes/{passTypeIdentifier}/{serialNumber} endpoint is implemented and logs all calls

No call is received from Apple to GET /passes/... after the push

.pkpass is signed and installs correctly

push payload json Copiar Editar { "aps": { "content-available": 1 }, "serialNumbers": ["9a4c9376d4"], "updated": true } pass.json json Copiar Editar { "formatVersion": 1, "passTypeIdentifier": "pass.order.com.lealtad.xxxxx", "teamIdentifier": "xxxxxxxx", "serialNumber": "9a4c9376d4xxxxxx", "webServiceURL": "https://xxxxxx.net", "authenticationToken": "xxxxxxxxxxxxxxxxx", ... } We have verified: Pass is installed and contains the correct authentication token.

Pass registration via POST /devices/... happens and is logged.

Push notifications are sent successfully and received (APNs 200 OK).

Our endpoint GET /passes/... responds properly with Authorization: Bearer {{token}}.

Certificate used to send the push is the same type as the one used to sign the .pkpass.

What could cause Apple Wallet to ignore the push? We would appreciate guidance on what might be preventing Wallet from calling the webServiceURL after a valid push. Is there a way to trace why Apple is not triggering the request?

Thanks in advance for your help.

Best regards, José Ruiz

Answered by DTS Engineer in 893620022

Hi @jruizr,

You wrote:

[...] What could cause Apple Wallet to ignore the push? We would appreciate guidance on what might be preventing Wallet from calling the webServiceURL after a valid push. [...] Is there a way to trace why Apple is not triggering the request? [...]

It appears there are multiple issues with the approach you describe here, and some things to verify:

  • Issue 1: Wrong push payload format
  • Issue 2: Missing intermediate endpoint
  • Issue 3: Missing apes-topic header
  • Issue 4: Serial number mismatch

Issue 1: Wrong push payload format

Your current payload is incorrect. Apple Wallet passes use a completely empty app body. Wallet does not read serialNumbers, updated or content-available from the push payload. Those fields are ignored or may confuse the process.

Your payload (incorrect):

{
  "aps": {
    "content-available": 1
  },
  "serialNumbers": ["9a4c9376d4"],
  "updated": true
}

Correct payload:

{
  "aps": {}
}

The push token itself tells Wallet which device to wake up. That's all the payload needs to do.

Issue 2: Missing intermediate endpoint

This is very likely the root case of why GET /passes is never called. After receiving the push, Wallet doesn't directly call this endpoint—first it calls your device registrations endpoint to ask "which passes need updating?" See this post for more information:

Clarification on Secure Handling of authenticationToken for Wallet Pass Updates

https://developer.apple.com/forums/thread/814731?answerId=893576022#893576022

If GET /v1/devices/{deviceLibraryIdentifier}/registrations/{passTypeIdentifier} is not implemented, or returns an empty serialNumbers array or a malformed response, then Wallet silently stops and never calls GET /passes.

The required response format for the registrations endpoint is below:

{
  "lastUpdated": "1749823600",
  "serialNumbers": ["9a4c9376d4xxxxxx"]
}

Note: lastUpdated is a string tag (e.g., a Unix timestamp). Wallet send this back as passesUpdatedSince on subsequent calls so you only return passes updated since that moment.

Issue 3: Missing apes-topic header

When sending a push for a Wallet pass, the apes-topic header must be sent to your passTypeIdentifier, not your app's bundle ID.

apns-topic: pass.order.com.lealtad.xxx
apns-push-type: background (optional, but recommended)

Without this, APNs may route the push incorrectly even if it returns 200 OK. A 200 from APNs only confirms delivery acceptance, not correct routing.

Issue 4: Serial number mismatch

In your pass.json, a full value for the serial number is provided:

"serialNumber: 9a4c9376d4xxxxxx 

However, in your push payload's serialNumbers array, the serial number value is truncated:

"serialNumbers": ["9a4c9376d4"]

While the payload field itself is irrelevant (Issue 1), this suggests there may be a truncation bug in your backend when storing/retrieving serial numbers. This could also just be a manual truncation for the forums post. Nevertheless, please verify your database stores and returns the full serial number in the registrations endpoint response.

Quick validation test

To isolate whether the registrations endpoint is the source of the issue, temporarily hardcode it to always return your serial number regardless of passesUpdatedSince:

{
  "lastUpdated": "9999999999",
  "serialNumbers": ["9a4c9376d4xxxxxx"]
}

Send a push and check if GET /passes is now called. If it is, your registrations endpoint logic (filtering by update time) is the bug.

Cheers,

Paris X Pinkney |  WWDR | DTS Engineer

Maybe I'm a little late to join the party, but it sounds like the endpoint you are listening to might wrong.

The endpoint is: /v1/passes/{passTypeIdentifier}/{serialNumber}

And the endpoint is appended after your webServiceURL.

Another thing, that endpoint is called only when the list endpoint returns some changes. For each change returned from the response of the list endpoint, Wallet will perform an HTTP request to your update endpoint to ask for a new pass.

Hi @jruizr,

You wrote:

[...] What could cause Apple Wallet to ignore the push? We would appreciate guidance on what might be preventing Wallet from calling the webServiceURL after a valid push. [...] Is there a way to trace why Apple is not triggering the request? [...]

It appears there are multiple issues with the approach you describe here, and some things to verify:

  • Issue 1: Wrong push payload format
  • Issue 2: Missing intermediate endpoint
  • Issue 3: Missing apes-topic header
  • Issue 4: Serial number mismatch

Issue 1: Wrong push payload format

Your current payload is incorrect. Apple Wallet passes use a completely empty app body. Wallet does not read serialNumbers, updated or content-available from the push payload. Those fields are ignored or may confuse the process.

Your payload (incorrect):

{
  "aps": {
    "content-available": 1
  },
  "serialNumbers": ["9a4c9376d4"],
  "updated": true
}

Correct payload:

{
  "aps": {}
}

The push token itself tells Wallet which device to wake up. That's all the payload needs to do.

Issue 2: Missing intermediate endpoint

This is very likely the root case of why GET /passes is never called. After receiving the push, Wallet doesn't directly call this endpoint—first it calls your device registrations endpoint to ask "which passes need updating?" See this post for more information:

Clarification on Secure Handling of authenticationToken for Wallet Pass Updates

https://developer.apple.com/forums/thread/814731?answerId=893576022#893576022

If GET /v1/devices/{deviceLibraryIdentifier}/registrations/{passTypeIdentifier} is not implemented, or returns an empty serialNumbers array or a malformed response, then Wallet silently stops and never calls GET /passes.

The required response format for the registrations endpoint is below:

{
  "lastUpdated": "1749823600",
  "serialNumbers": ["9a4c9376d4xxxxxx"]
}

Note: lastUpdated is a string tag (e.g., a Unix timestamp). Wallet send this back as passesUpdatedSince on subsequent calls so you only return passes updated since that moment.

Issue 3: Missing apes-topic header

When sending a push for a Wallet pass, the apes-topic header must be sent to your passTypeIdentifier, not your app's bundle ID.

apns-topic: pass.order.com.lealtad.xxx
apns-push-type: background (optional, but recommended)

Without this, APNs may route the push incorrectly even if it returns 200 OK. A 200 from APNs only confirms delivery acceptance, not correct routing.

Issue 4: Serial number mismatch

In your pass.json, a full value for the serial number is provided:

"serialNumber: 9a4c9376d4xxxxxx 

However, in your push payload's serialNumbers array, the serial number value is truncated:

"serialNumbers": ["9a4c9376d4"]

While the payload field itself is irrelevant (Issue 1), this suggests there may be a truncation bug in your backend when storing/retrieving serial numbers. This could also just be a manual truncation for the forums post. Nevertheless, please verify your database stores and returns the full serial number in the registrations endpoint response.

Quick validation test

To isolate whether the registrations endpoint is the source of the issue, temporarily hardcode it to always return your serial number regardless of passesUpdatedSince:

{
  "lastUpdated": "9999999999",
  "serialNumbers": ["9a4c9376d4xxxxxx"]
}

Send a push and check if GET /passes is now called. If it is, your registrations endpoint logic (filtering by update time) is the bug.

Cheers,

Paris X Pinkney |  WWDR | DTS Engineer

Apple Wallet Silent Push Notification not triggering GET /passes endpoint
 
 
Q