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 uses callbacks to notify you when a pass is created or deleted, sending data to your HTTPS endpoint.\u003c/p\u003e\n"],["\u003cp\u003eYou need to set up an HTTPS endpoint, update the callback endpoint for each class, and ideally use the Tink library for signature verification.\u003c/p\u003e\n"],["\u003cp\u003eGoogle sends a JSON message to your endpoint containing details about the event, including class ID, object ID, event type, and more.\u003c/p\u003e\n"],["\u003cp\u003eEnsure your server accepts requests from Googlebot by configuring \u003ccode\u003erobots.txt\u003c/code\u003e and handle potential duplicate deliveries using the \u003ccode\u003enonce\u003c/code\u003e.\u003c/p\u003e\n"],["\u003cp\u003eCallbacks are on a best-effort basis, with Google employing retry strategies for resilience but not guaranteeing delivery in all cases.\u003c/p\u003e\n"]]],["Google Wallet API uses callbacks to notify merchants of pass creation or deletion events. These class-specific callbacks, sent to a merchant's HTTPS endpoint, include details like `classId`, `objectId`, `eventType`, and `nonce`. Merchants must verify message authenticity using public keys, preferably with the Tink library. Callbacks are best-effort and retried if needed; duplicate deliveries are possible. The message format is a serialized JSON string. Merchant servers must allow requests from `Googlebot`.\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/retail/loyalty-cards/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."]]