Stay organized with collections
Save and categorize content based on your preferences.
This guide explains how to use callbacks with the Google Wallet API. When a
pass is created or deleted, Google can perform a callback to an HTTPS
endpoint of your choosing.
This callback is class-specific, and includes data
about the event such as the class, object, and event type.
This can be used to
keep track of the number of user adds and deletions that occur. For
example, callbacks can be configured to send events to an analytics
application to track customer engagement during promotional events.
Prerequisites
Before you start, review the following prerequisites:
Stand up an HTTPS endpoint that handles POST requests. This endpoint needs
to be publicly available.
Programmatically update the callback endpoint for each class. See the
callbackOptions
property by class in the REST API.
Recommended: Use the Tink library to verify the signatures.
Implement callbacks
For every add or delete performed by the user on an
an object
, Google makes callbacks to the merchants with details about the add or delete on a
per-class
URL. Merchants need to first use the Public Keys to verify the authenticity of
the message. After the callbacks verify the message, the callbacks can be used
for downstream operations.
Verify the signature
We recommend that you use the Tink library to verify the message signature
when you implement your HTTPS endpoint. The
Tink library
provides PaymentMethodTokenRecipient, a utility that
automatically verifies the signature and returns the actual message upon
successful verification.
The following example shows how to use the Tink library to implement
PaymentMethodTokenRecipient:
The message format is JSON that's serialized into a string with the following
properties:
Identifier
Description
classId
Fully qualified class ID. Uses the following format:
<issuer_id.class_id>
objectId
Fully qualified object ID. Uses the following format:
<issuer_id.object_id>
expTimeMillis
Expiration time in milliseconds since EPOCH. After the expiration time,
the message needs to be deemed invalid.
eventType
Can be either del or save for
DELETE and SAVE.
nonce
Nonce to track any duplicate deliveries.
Handle the request from a Google server
The following is a list of the key fields in the header of the request that's
sent to your callback endpoint:
User-Agent: Googlebot
Content-Type: application/json
Configure your server so that it doesn't reject the request. To do so, you can
set the following in robots.txt:
User-agent: Googlebot
Disallow:
Retries
Callbacks are on a best-effort basis. Google will use common retry strategies
to be resilient in cases where the callback endpoint is not responding or has an
intermittent outage and will gracefully back off attempts.
Duplicate deliveries
There might be duplicate deliveries in some cases. We recommend that you use
nonce to dedupe them.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-09-04 UTC."],[[["\u003cp\u003eGoogle Wallet API callbacks provide real-time updates when passes are created or deleted, allowing you to track user engagement and perform custom actions.\u003c/p\u003e\n"],["\u003cp\u003eYou need to set up a publicly available HTTPS endpoint to receive these callbacks and programmatically update the callback endpoint for each class.\u003c/p\u003e\n"],["\u003cp\u003eGoogle signs these callbacks, and it's recommended to use the Tink library to verify the signature for security.\u003c/p\u003e\n"],["\u003cp\u003eThe callback message contains details like class ID, object ID, event type, and a nonce to handle duplicate deliveries.\u003c/p\u003e\n"],["\u003cp\u003eCallbacks are on a best-effort basis with retry mechanisms, but you should be prepared for potential duplicate deliveries using the provided nonce.\u003c/p\u003e\n"]]],["Google Wallet API callbacks notify merchants via HTTPS endpoints when passes are added or deleted. These class-specific callbacks include data on the class, object, and event type. Merchants must set up a public HTTPS endpoint and programmatically update callback endpoints per class. The Tink library is recommended to verify message signatures for authenticity. The message, in JSON format, contains the class ID, object ID, expiration time, event type (`del` or `save`), and a nonce for deduplication. Google uses retry strategies for endpoint outages.\n"],null,["# Add and delete callbacks\n\nThis guide explains how to use callbacks with the Google Wallet API. When a\npass is created or deleted, Google can perform a callback to an HTTPS\nendpoint of your choosing.\n\nThis callback is class-specific, and includes data\nabout the event such as the class, object, and event type.\n\nThis can be used to\nkeep track of the number of user adds and deletions that occur. For\nexample, callbacks can be configured to send events to an analytics\napplication to track customer engagement during promotional events.\n\nPrerequisites\n-------------\n\nBefore you start, review the following prerequisites:\n\n- Stand up an HTTPS endpoint that handles POST requests. This endpoint needs to be publicly available.\n- Programmatically update the callback endpoint for each class. See the [`callbackOptions`](/wallet/tickets/boarding-passes/rest/v1/CallbackOptions) property by class in the REST API.\n- Recommended: Use the [Tink](https://developers.google.com/tink) library to verify the signatures.\n\nImplement callbacks\n-------------------\n\n\nFor every add or delete performed by the user on an\n\nan object\n\n, Google makes callbacks to the merchants with details about the add or delete on a\n\nper-class\n\nURL. Merchants need to first use the Public Keys to verify the authenticity of\nthe message. After the callbacks verify the message, the callbacks can be used\nfor downstream operations.\n\nVerify the signature\n--------------------\n\n\nWe recommend that you use the Tink library to verify the message signature\nwhen you implement your HTTPS endpoint. The\n[Tink library](https://github.com/google/tink)\nprovides `PaymentMethodTokenRecipient`, a utility that\nautomatically verifies the signature and returns the actual message upon\nsuccessful verification.\n\n\nThe following example shows how to use the Tink library to implement\n`PaymentMethodTokenRecipient`: \n\n```python\nimport java.io.IOException;\nimport javax.servlet.http.*;\nimport com.google.common.io.CharStreams;\nimport com.google.crypto.tink.apps.paymentmethodtoken.*;\n\n// Replace ISSUER_ID with your issuer id\nprivate static final String RECIPIENT_ID = \"\u003cvar translate=\"no\"\u003eISSUER_ID\u003c/var\u003e\";\n\nprivate static final String PUBLIC_KEY_URL = \"https://pay.google.com/gp/m/issuer/keys\";\nprivate static final String SENDER_ID = \"GooglePayPasses\";\nprivate static final String PROTOCOL = \"ECv2SigningOnly\";\n\nprivate static final GooglePaymentsPublicKeysManager keysManager = new GooglePaymentsPublicKeysManager.Builder()\n .setKeysUrl(PUBLIC_KEY_URL)\n .build();\n\npublic void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {\n try {\n // Extract signed message with signature from POST request body.\n String signedMessage = CharStreams.toString(request.getReader());\n PaymentMethodTokenRecipient recipient =\n new PaymentMethodTokenRecipient.Builder()\n .protocolVersion(PROTOCOL)\n .fetchSenderVerifyingKeysWith(keysManager)\n .senderId(SENDER_ID)\n .recipientId(RECIPIENT_ID)\n .build();\n\n String serializedJsonMessage = recipient.unseal(signedMessage);\n\n // Use serializedJsonMessage to extract the details\n } catch (Exception e) {\n // Handle the error\n }\n}\n```\n\nExpected message format\n-----------------------\n\n\nThe message format is JSON that's serialized into a string with the following\nproperties:\n\n| Identifier | Description |\n|-----------------|-----------------------------------------------------------------------------------------------------------------|\n| `classId` | Fully qualified class ID. Uses the following format: ``` \u003cissuer_id.class_id\u003e ``` |\n| `objectId` | Fully qualified object ID. Uses the following format: ``` \u003cissuer_id.object_id\u003e ``` |\n| `expTimeMillis` | Expiration time in milliseconds since EPOCH. After the expiration time, the message needs to be deemed invalid. |\n| `eventType` | Can be either `del` or `save` for `DELETE` and `SAVE`. |\n| `nonce` | Nonce to track any duplicate deliveries. |\n\n### Handle the request from a Google server\n\n\nThe following is a list of the key fields in the header of the request that's\nsent to your callback endpoint:\n\n- User-Agent: `Googlebot`\n- Content-Type: `application/json`\n\n\nConfigure your server so that it doesn't reject the request. To do so, you can\nset the following in `robots.txt`: \n\n```\nUser-agent: Googlebot\nDisallow:\n```\n\n### Retries\n\n\nCallbacks are on a best-effort basis. Google will use common retry strategies\nto be resilient in cases where the callback endpoint is not responding or has an\nintermittent outage and will gracefully back off attempts.\n\n### Duplicate deliveries\n\n\nThere might be duplicate deliveries in some cases. We recommend that you use\n`nonce` to dedupe them."]]