Get started with the Web API

Before you start with the Web API, make sure to complete the prerequisites. To continue with the Web API, you must have a service account and a service account key, and you must grant access to your service account to call the Google Wallet API.

Download the sample code on GitHub to run the code snippets referenced in the steps below.

Authentication and authorization

Requests to the Google Wallet API must be authenticated so that the Google Wallet API can identify that the request is being made by your application. This is achieved by using the service account key to obtain an access token.

First, perform the necessary library imports and define some variables for the service account JSON, and IDs for the issuer, class, unique user and object that will be saved.

Java

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import okhttp3.*;

import java.io.FileInputStream;
import java.security.interfaces.RSAPrivateKey;
import java.util.*;

public class DemoLoyalty {
  public static void main(String[] args) throws Exception {

    // Path to service account key file obtained from Google CLoud Console.
    String serviceAccountFile = System.getenv("GOOGLE_APPLICATION_CREDENTIALS");

    // Issuer ID obtained from Google Pay Business Console.
    String issuerId = System.getenv("WALLET_ISSUER_ID");

    // Developer defined ID for the wallet class.
    String classId = System.getenv("WALLET_CLASS_ID");

    // Developer defined ID for the user, eg an email address.
    String userId = System.getenv("WALLET_USER_ID");

    // ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric.
    String objectId = String.format("%s.%s-%s", issuerId, userId.replaceAll("[^\\w.-]", "_"), classId);

PHP

use Firebase\JWT\JWT;
use Google\Auth\Credentials\ServiceAccountCredentials;
use Google\Auth\Middleware\AuthTokenMiddleware;
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Exception\ClientException;

// Path to service account key file obtained from Google CLoud Console.
$serviceAccountFile = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json';

// Issuer ID obtained from Google Pay Business Console.
$issuerId = getenv('WALLET_ISSUER_ID') ?: '<issuer ID>';

// Developer defined ID for the wallet class.
$classId = getenv('WALLET_CLASS_ID') ?: "test-loyalty-class-id";

// Developer defined ID for the user, eg an email address.
$userId = getenv('WALLET_USER_ID') ?: 'test@example.com';

// ID for the wallet object, must be in the form `issuer_id.user_id` where user_id is alphanumeric.
$objectId = "{$issuerId}." . preg_replace('/[^\w.-]/i', '_', $userId) . "-{$classId}";

Python

import os, re, datetime

from google.auth.transport.requests import AuthorizedSession
from google.oauth2 import service_account
from google.auth import jwt, crypt

# Path to service account key file obtained from Google CLoud Console.
service_account_file = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", "/path/to/key.json")

# Issuer ID obtained from Google Pay Business Console.
issuer_id = os.environ.get("WALLET_ISSUER_ID", "<issuer ID>")

# Developer defined ID for the wallet class.
class_id = os.environ.get("WALLET_CLASS_ID", "test-loyalty-class-id")

# Developer defined ID for the user, eg an email address.
user_id = os.environ.get("WALLET_USER_ID", "test@example.com")

# ID for the wallet object, must be in the form `issuer_id.user_id` where user_id is alphanumeric.
object_id = "%s.%s-%s" % (issuer_id, re.sub(r"[^\w.-]", "_", user_id), class_id)

C#

using Google.Apis.Auth.OAuth2;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http.Json;
using System.Net.Http.Headers;
using System.Text.RegularExpressions;

// Path to service account key file obtained from Google CLoud Console.
var serviceAccountJson = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json";

// Issuer ID obtained from Google Pay Business Console.
var issuerId = Environment.GetEnvironmentVariable("WALLET_ISSUER_ID") ?? "<issuer ID>";

// Developer defined ID for the wallet class.
var classId = Environment.GetEnvironmentVariable("WALLET_CLASS_ID") ?? "test-loyalty-class-id";

// Developer defined ID for the user, eg an email address.
var userId = Environment.GetEnvironmentVariable("WALLET_USER_ID") ?? "test@example.com";

// ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric.
var objectId = String.Format("{0}.{1}-{2}", issuerId, new Regex(@"[^\w.-]", RegexOptions.Compiled).Replace(userId, "_"), classId);

Node.js

const { GoogleAuth } = require('google-auth-library');
const jwt = require('jsonwebtoken');

// Path to service account key file obtained from Google CLoud Console.
const serviceAccountFile = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json';

// Issuer ID obtained from Google Pay Business Console.
const issuerId = process.env.WALLET_ISSUER_ID || '<issuer ID>';

// Developer defined ID for the wallet class.
const classId = process.env.WALLET_CLASS_ID || 'test-loyalty-class-id';

// Developer defined ID for the user, eg an email address.
const userId = process.env.WALLET_USER_ID || 'test@example.com';

// ID for the wallet object, must be in the form `issuerId.userId` where userId is alphanumeric.
const objectId = `${issuerId}.${userId.replace(/[^\w.-]/g, '_')}-${classId}`;

Next, use one of the framework libraries to retrieve the necessary credentials to call the { api_name }.

Java

GoogleCredential credential =
    GoogleCredential.fromStream(new FileInputStream(serviceAccountFile))
        .createScoped(Collections.singleton("https://www.googleapis.com/auth/wallet_object.issuer"));
credential.refreshToken();
OkHttpClient httpClient = new OkHttpClient();

PHP

$credentials = new ServiceAccountCredentials('https://www.googleapis.com/auth/wallet_object.issuer', $serviceAccountFile);
$middleware = new AuthTokenMiddleware($credentials); 
$stack = HandlerStack::create();
$stack->push($middleware);
$httpClient = new Client(['handler' => $stack, 'auth' => 'google_auth']);

Python

credentials = service_account.Credentials.from_service_account_file(service_account_file, 
  scopes=["https://www.googleapis.com/auth/wallet_object.issuer"])
http_client = AuthorizedSession(credentials)

C#

var credentials = (ServiceAccountCredential) GoogleCredential
    .FromFile(serviceAccountJson)
    .CreateScoped(new[] { "https://www.googleapis.com/auth/wallet_object.issuer" })
    .UnderlyingCredential;

var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", await credentials.GetAccessTokenForRequestAsync());

Node.js

const credentials = require(serviceAccountFile);
const httpClient = new GoogleAuth({
  credentials: credentials,
  scopes: 'https://www.googleapis.com/auth/wallet_object.issuer'
});

Creating a Passes Object

A Passes Object is an instance of a Passes Class. In order to create a Passes object, you must provide the following attributes:

  • classId: The ID of the Passes Class
  • id: A unique loyalty membership ID for your customer
  • state: active for a new pass that's being created.

We also recommend that you include the following attributes:

  • accountId
  • accountName

Refer to the template guidelines for more information on how these attributes are represented in the Loyalty Pass.

Code sample to create a Passes Object:

HTTP

POST /walletobjects/v1/loyaltyObject HTTP/1.1
Host: walletobjects.googleapis.com
Content-Type: application/json
Authorization: Bearer <ACCESS_TOKEN>;
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: Keep-Alive

{
  "id": <ISSUER_ID>.<USER_ID>,
  "classId": <ISSUER_ID>.<CLASS_ID>,
  "heroImage": {
    "sourceUri": {
      "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg",
      "description": "Test heroImage description"
    }
  },
  "textModulesData": [
    {
      "header": "Test text module header",
      "body": "Test text module body"
    }
  ],
  "linksModuleData": {
    "uris": [
      {
        "kind": "walletobjects#uri",
        "uri": "http://maps.google.com/",
        "description": "Test link module uri description"
      },
      {
        "kind": "walletobjects#uri",
        "uri": "tel:6505555555",
        "description": "Test link module tel description"
      }
    ]
  },
  "imageModulesData": [
    {
      "mainImage": {
        "kind": "walletobjects#image",
        "sourceUri": {
          "kind": "walletobjects#uri",
          "uri": "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg",
          "description": "Test image module description"
        }
      }
    }
  ],
  "barcode": {
    "kind": "walletobjects#barcode",
    "type": "qrCode",
    "value": "Test QR Code"
  },
  "state": "active",
  "accountId": "Test account id",
  "accountName": "Test account name",
  "loyaltyPoints": {
    "balance": {
      "string": "800"
    },
    "label": "Points"
  },
  "locations": [
    {
      "kind": "walletobjects#latLongPoint",
      "latitude": 37.424015499999996,
      "longitude": -122.09259560000001
    }
  ]
}

Java

String objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/loyaltyObject/";
String objectPayload = String.format(
    "{"
  + "  \"id\": \"%s\","
  + "  \"classId\": \"%s.%s\","
  + "  \"heroImage\": {"
  + "    \"sourceUri\": {"
  + "      \"uri\": \"https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg\","
  + "      \"description\": \"Test heroImage description\""
  + "    }"
  + "  },"
  + "  \"textModulesData\": ["
  + "    {"
  + "      \"header\": \"Test text module header\","
  + "      \"body\": \"Test text module body\""
  + "    }"
  + "  ],"
  + "  \"linksModuleData\": {"
  + "    \"uris\": ["
  + "      {"
  + "        \"kind\": \"walletobjects#uri\","
  + "        \"uri\": \"http://maps.google.com/\","
  + "        \"description\": \"Test link module uri description\""
  + "      },"
  + "      {"
  + "        \"kind\": \"walletobjects#uri\","
  + "        \"uri\": \"tel:6505555555\","
  + "        \"description\": \"Test link module tel description\""
  + "      }"
  + "    ]"
  + "  },"
  + "  \"imageModulesData\": ["
  + "    {"
  + "      \"mainImage\": {"
  + "        \"kind\": \"walletobjects#image\","
  + "        \"sourceUri\": {"
  + "          \"kind\": \"walletobjects#uri\","
  + "          \"uri\": \"http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg\","
  + "          \"description\": \"Test image module description\""
  + "        }"
  + "      }"
  + "    }"
  + "  ],"
  + "  \"barcode\": {"
  + "    \"kind\": \"walletobjects#barcode\","
  + "    \"type\": \"qrCode\","
  + "    \"value\": \"Test QR Code\""
  + "  },"
  + "  \"state\": \"active\","
  + "  \"accountId\": \"Test account id\","
  + "  \"accountName\": \"Test account name\","
  + "  \"loyaltyPoints\": {"
  + "    \"balance\": {"
  + "      \"string\": \"800\""
  + "    },"
  + "    \"label\": \"Points\""
  + "  },"
  + "  \"locations\": ["
  + "    {"
  + "      \"kind\": \"walletobjects#latLongPoint\","
  + "      \"latitude\": 37.424015499999996,"
  + "      \"longitude\": -122.09259560000001"
  + "    }"
  + "  ]"
  + "}", objectId, issuerId, classId);
String output = null;

builder =
    new Request.Builder()
        .url(objectUrl + objectId)
        .addHeader("Authorization", "Bearer " + credential.getAccessToken())
        .get();
try (Response response = httpClient.newCall(builder.build()).execute()) {
    if (response.code() != 404) {
        output = Objects.requireNonNull(response.body()).string();
    }
}
if (output == null) {
    builder =
        new Request.Builder()
            .url(objectUrl)
            .addHeader("Authorization", "Bearer " + credential.getAccessToken());
    builder.method("POST", RequestBody.create(objectPayload, MediaType.get("application/json; charset=utf-8")));
    try (Response response = httpClient.newCall(builder.build()).execute()) {
      output = Objects.requireNonNull(response.body()).string();
    }
}
System.out.println("object GET or POST response: " + output);

PHP

$objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/loyaltyObject/";
$objectPayload = <<<EOD
{
  "id": "{$objectId}",
  "classId": "{$issuerId}.{$classId}",
  "heroImage": {
    "sourceUri": {
      "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg",
      "description": "Test heroImage description"
    }
  },
  "textModulesData": [
    {
      "header": "Test text module header",
      "body": "Test text module body"
    }
  ],
  "linksModuleData": {
    "uris": [
      {
        "kind": "walletobjects#uri",
        "uri": "http://maps.google.com/",
        "description": "Test link module uri description"
      },
      {
        "kind": "walletobjects#uri",
        "uri": "tel:6505555555",
        "description": "Test link module tel description"
      }
    ]
  },
  "imageModulesData": [
    {
      "mainImage": {
        "kind": "walletobjects#image",
        "sourceUri": {
          "kind": "walletobjects#uri",
          "uri": "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg",
          "description": "Test image module description"
        }
      }
    }
  ],
  "barcode": {
    "kind": "walletobjects#barcode",
    "type": "qrCode",
    "value": "Test QR Code"
  },
  "state": "active",
  "accountId": "Test account id",
  "accountName": "Test account name",
  "loyaltyPoints": {
    "balance": {
      "string": "800"
    },
    "label": "Points"
  },
  "locations": [
    {
      "kind": "walletobjects#latLongPoint",
      "latitude": 37.424015499999996,
      "longitude": -122.09259560000001
    }
  ]
}
EOD;

// Retrieve the object, or create it if it doesn't exist.
try {
  $objectResponse = $httpClient->get($objectUrl . $objectId);
} catch (ClientException $e) {
  $objectResponse = $e->getResponse();
  if ($objectResponse->getStatusCode() == 404) {
    $objectResponse = $httpClient->post($objectUrl, ['json' => json_decode($objectPayload)]);
  }
}
echo "object GET or POST response: " . $objectResponse->getBody();

Python

object_url = "https://walletobjects.googleapis.com/walletobjects/v1/loyaltyObject/"
object_payload = {
  "id": object_id,
  "classId": "%s.%s" % (issuer_id, class_id),
  "heroImage": {
    "sourceUri": {
      "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg",
      "description": "Test heroImage description"
    }
  },
  "textModulesData": [
    {
      "header": "Test text module header",
      "body": "Test text module body"
    }
  ],
  "linksModuleData": {
    "uris": [
      {
        "kind": "walletobjects#uri",
        "uri": "http://maps.google.com/",
        "description": "Test link module uri description"
      },
      {
        "kind": "walletobjects#uri",
        "uri": "tel:6505555555",
        "description": "Test link module tel description"
      }
    ]
  },
  "imageModulesData": [
    {
      "mainImage": {
        "kind": "walletobjects#image",
        "sourceUri": {
          "kind": "walletobjects#uri",
          "uri": "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg",
          "description": "Test image module description"
        }
      }
    }
  ],
  "barcode": {
    "kind": "walletobjects#barcode",
    "type": "qrCode",
    "value": "Test QR Code"
  },
  "state": "active",
  "accountId": "Test account id",
  "accountName": "Test account name",
  "loyaltyPoints": {
    "balance": {
      "string": "800"
    },
    "label": "Points"
  },
  "locations": [
    {
      "kind": "walletobjects#latLongPoint",
      "latitude": 37.424015499999996,
      "longitude": -122.09259560000001
    }
  ]
}

# Retrieve the object, or create it if it doesn't exist.
object_response = http_client.get(object_url + object_id)
if object_response.status_code == 404:
  object_response = http_client.post(object_url, json=object_payload)
print("object GET or POST response:", object_response.text)

C#

var objectUrl = "https://walletobjects.googleapis.com/walletobjects/v1/loyaltyObject/";
var objectPayload = new
{
    id = objectId,
    classId = $"{issuerId}.{classId}",
    heroImage = new
    {
        sourceUri = new
        {
            uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg",
            description = "Test heroImage description"
        }
    },
    textModulesData = new object[]
    {
        new
        {
            header = "Test text module header",
            body = "Test text module body"
        }
    },
    linksModuleData = new
    {
        uris = new object[]
        {
            new
            {
                kind = "walletobjects#uri",
                uri = "http://maps.google.com/",
                description = "Test link module uri description"
            },
            new
            {
                kind = "walletobjects#uri",
                uri = "tel:6505555555",
                description = "Test link module tel description"
            }
        }
    },
    imageModulesData = new object[]
    {
        new
        {
            mainImage = new
            {
                kind = "walletobjects#image",
                sourceUri = new
                {
                    kind = "walletobjects#uri",
                    uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg",
                    description = "Test image module description"
                }
            }
        }
    },
    barcode = new
    {
        kind = "walletobjects#barcode",
        type = "qrCode",
        value = "Test QR Code"
    },
    state = "active",
    accountId = "Test account id",
    accountName = "Test account name",
    loyaltyPoints = new
    {
        balance = new
        {
            @string = "800"
        },
        label = "Points"
    },
    locations = new object[]
    {
        new
        {
            kind = "walletobjects#latLongPoint",
            latitude = 37.424015499999996,
            longitude = -122.09259560000001
        }
    }
};

var objectResponse = await httpClient.GetAsync($"{objectUrl}{objectId}");
if ((int) objectResponse.StatusCode == 404) 
{
    objectResponse = await httpClient.PostAsJsonAsync(objectUrl, objectPayload);
}
var objectContent = await objectResponse.Content.ReadAsStringAsync();
Console.WriteLine("object GET or POST response: " + objectContent);

Node.js

const objectUrl = 'https://walletobjects.googleapis.com/walletobjects/v1/loyaltyObject/';
const objectPayload = {
  "id": objectId,
  "classId": `${issuerId}.${classId}`,
  "heroImage": {
    "sourceUri": {
      "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg",
      "description": "Test heroImage description"
    }
  },
  "textModulesData": [
    {
      "header": "Test text module header",
      "body": "Test text module body"
    }
  ],
  "linksModuleData": {
    "uris": [
      {
        "kind": "walletobjects#uri",
        "uri": "http://maps.google.com/",
        "description": "Test link module uri description"
      },
      {
        "kind": "walletobjects#uri",
        "uri": "tel:6505555555",
        "description": "Test link module tel description"
      }
    ]
  },
  "imageModulesData": [
    {
      "mainImage": {
        "kind": "walletobjects#image",
        "sourceUri": {
          "kind": "walletobjects#uri",
          "uri": "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg",
          "description": "Test image module description"
        }
      }
    }
  ],
  "barcode": {
    "kind": "walletobjects#barcode",
    "type": "qrCode",
    "value": "Test QR Code"
  },
  "state": "active",
  "accountId": "Test account id",
  "accountName": "Test account name",
  "loyaltyPoints": {
    "balance": {
      "string": "800"
    },
    "label": "Points"
  },
  "locations": [
    {
      "kind": "walletobjects#latLongPoint",
      "latitude": 37.424015499999996,
      "longitude": -122.09259560000001
    }
  ]
};

// Retrieve the object, or create it if it doesn't exist.
let objectResponse;
try {
  objectResponse = await httpClient.request({url: objectUrl + objectId, method: 'GET'});
} catch (err) {
  if (err.response && err.response.status === 404) {
    objectResponse = await httpClient.request({url: objectUrl, method: 'POST', data: objectPayload});
  } else {
    objectResponse = err;
  }
}
console.log('object GET or POST response:', objectResponse);

Once complete, your customer’s Object is created on the server. However, at this stage, the Passes object isn't linked to a Google user or their device. For the pass to be associated with a Google Wallet user, the user must first add the pass to Google Wallet.

Adding to Google Wallet

Adding a pass to Google Wallet links the Passes Object to a Google user and can only be initiated in the context of a logged-in Google identity. This can be achieved by directing the user to a Add to Google Wallet URL.

The Add to Google Wallet URL is a dynamically generated URL that contains the following information about the Passes Object ID created in the previous step. This information is encoded as a JSON Web Token (JWT).

JSON Web Token (JWT)

The JWT contains claims that you (the issuer) are making about the Passes Object that will be saved by the user. The JWT must be signed using the private_key from the service account key obtained from the Create Service Account step, and Google validates these claims by verifying the JWT signature.

The JWT claims need to have the following structure:

{
  "aud": "google",
  "origins": ["https://example.com"],
  "iss": "my-service-account@my-project-id.iam.gserviceaccount.com",
  "typ": "savetowallet",
  "payload": {
    "loyaltyObjects": [
      {
        "id": "PASSES_OBJECT_ID_1234567890"
      }
    ]
  }
}

Construct the JWT claims, and obtain the token by signing the claims with the service account key's private_key:

Java

Map<String, Object> claims = new HashMap();
claims.put("iss", credential.getServiceAccountId()); // `client_email` in service account file.
claims.put("aud", "google");
claims.put("origins", new ArrayList<>(Arrays.asList("www.example.com")));
claims.put("typ", "savetowallet");

Map<String, Object> payload = new HashMap();
Map<String, String> objectIdMap = new HashMap();
objectIdMap.put("id", objectId);
payload.put("loyaltyObjects", new ArrayList<>(Arrays.asList(objectIdMap)));
claims.put("payload", payload);

Algorithm algorithm = Algorithm.RSA256(null, (RSAPrivateKey) credential.getServiceAccountPrivateKey());
String token = JWT.create()
      .withPayload(claims)
      .sign(algorithm);
String saveUrl = "https://pay.google.com/gp/v/save/" + token;
System.out.println(saveUrl);

PHP

$serviceAccount = json_decode(file_get_contents($serviceAccountFile), true);
$claims = [
  'iss' => $serviceAccount['client_email'],
  'aud' => 'google',
  'origins' => ['www.example.com'],
  'typ' => 'savetowallet',
  'payload' => ['loyaltyObjects' => [['id' => $objectId]]]
];

$token = JWT::encode($claims, $serviceAccount['private_key'], 'RS256');
$saveUrl = "https://pay.google.com/gp/v/save/${token}";
echo $saveUrl;

Python

claims = {
  "iss": http_client.credentials.service_account_email, # `client_email` in service account file.
  "aud": "google",
  "origins": ["www.example.com"],
  "typ": "savetowallet",
  "payload": {
    "loyaltyObjects": [{"id": object_id}]
  }
}

signer = crypt.RSASigner.from_service_account_file(service_account_file)
token = jwt.encode(signer, claims).decode("utf-8")
save_url = "https://pay.google.com/gp/v/save/%s" % token
print(save_url)

C#

var claims = new JwtPayload();
claims.Add("iss", credentials.Id); // `client_email` in service account file.
claims.Add("aud", "google");
claims.Add("origins", new string[] { "www.example.com" });
claims.Add("typ", "savetowallet");
claims.Add("payload", new
{
    loyaltyObjects = new object[]
    {
        new
        {
            id = objectId,
        },
    },
});

var key = new RsaSecurityKey(credentials.Key);
var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha256);
var jwt = new JwtSecurityToken(new JwtHeader(signingCredentials), claims);
var token = new JwtSecurityTokenHandler().WriteToken(jwt);
var saveUrl = $"https://pay.google.com/gp/v/save/{token}";
Console.WriteLine(saveUrl);

Node.js

const claims = {
  iss: credentials.client_email, // `client_email` in service account file.
  aud: 'google',
  origins: ['www.example.com'],
  typ: 'savetowallet',
  payload: {
    loyaltyObjects: [{id: objectId}],
  },
};

const token = jwt.sign(claims, credentials.private_key, {algorithm: 'RS256'});
const saveUrl = `https://pay.google.com/gp/v/save/${token}`;
console.log(saveUrl);

After you’ve obtained a signed JWT, you can use this information to construct a Add to Google Wallet link.

The Add to Google Wallet link has the following format:

https://pay.google.com/gp/v/save/{token}

This link can be embedded into your web page or email as a hyperlink. It can also be sent to the customer using other channels like chat and SMS.

The safe length of an encoded JWT is 1800 characters. If your JWT is below this limit, the entire object can be included in the signed JWT. Your JWTs should remain below this limit. If the length is over 1800 characters, the Add to Google Wallet may not work due to truncation by web browsers.

Add to Google Wallet Button

For best results, leverage the Google Wallet button assets in your web page, email, or Android application.

The Google Wallet button can be rendered in two ways:

Next steps

  • Assess use cases of loyalty cards and implement any to suit the business need
  • Customize the appearance of your loyalty cards by following Brand guidelines
  • Still have questions? Please review our FAQ.