> For the complete documentation index, see [llms.txt](https://docs.webtonative.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.webtonative.com/javascript-apis/wallet/wallet-creating-passes/wallet-creating-passes-android.md).

# Wallet Creating Passes - Android

This page covers the part that happens **before** you ever call `Wallet.addPasses` — building and signing the pass JWT itself. WebToNative never creates, edits, or signs a pass; it only hands whatever JWT (or save link) you give it to Google Wallet. See [Google Wallet / Apple Wallet](/javascript-apis/wallet.md) for the JS API this feeds into.

***

## 1. Create a Google Wallet Console Account

Sign up at the [Google Wallet Business Console](https://pay.google.com/business/console) and get your **Issuer ID** — every pass class/object you create is scoped to it.

## 2. Add Testers

New Issuer accounts start in **demo mode** — passes only work for Gmail accounts you've explicitly added as testers. Add every account you'll use for testing under the Console's tester list.

{% hint style="warning" %}
Once you've finished testing, move your Issuer account from demo mode to **production** in the Console — passes won't work for real users until you do.
{% endhint %}

## 3. Create a Pass Class

A **class** is the reusable template for a pass type — the loyalty program, the event, the offer. Create it in the Google Wallet Console, picking the type that matches what you're issuing (Generic, Loyalty, Offer, Event Ticket, Gift Card, Flight, Transit).

Once the class exists, you also need a **pass object** — one instance of that class holding one user's actual data (their points balance, their seat, their gift card value). You can draft the object's JSON by hand against the [Google Wallet objects reference](https://developers.google.com/wallet/generic/rest/v1/genericobject), or use an AI assistant to generate a sample object matching your class's schema as a starting point.

## 4. Get Your Service Account Key

In Google Cloud Console, enable the **Google Wallet API** for your project, create a service account, and download its **JSON key**. This key's private key is what signs the JWT in the next step — keep it off the client and out of version control.

## 5. Generate the Save JWT

The pass object isn't handed to `Wallet.addPasses` directly — it's wrapped in a signed JWT. Build the claims below, then sign them:

| Claim     | Value                                                                                                                                                                                                                                                                                                                                                                               |
| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `iss`     | Your service account's email address.                                                                                                                                                                                                                                                                                                                                               |
| `aud`     | Always `"google"`.                                                                                                                                                                                                                                                                                                                                                                  |
| `typ`     | Always `"savetowallet"`.                                                                                                                                                                                                                                                                                                                                                            |
| `iat`     | Issued-at timestamp.                                                                                                                                                                                                                                                                                                                                                                |
| `payload` | An object keyed by the class/object type, e.g. `{ "loyaltyObjects": [{ "id": "...", "classId": "..." }] }`. Accepted keys: `genericClasses`/`genericObjects`, `loyaltyClasses`/`loyaltyObjects`, `offerClasses`/`offerObjects`, `eventTicketClasses`/`eventTicketObjects`, `flightClasses`/`flightObjects`, `giftCardClasses`/`giftCardObjects`, `transitClasses`/`transitObjects`. |

**For quick testing**, sign it at [jwt.io](https://www.jwt.io/): select algorithm **RS256**, paste the claims JSON above into the payload editor, and paste your service account's private key into the signature panel. jwt.io's encoder runs entirely in your browser — it never sends the key anywhere — but it's still meant for testing, not a production pipeline.

{% hint style="danger" %}
When you register the pass object, also register your **app's package name and SHA-1 signing key** in the Google Wallet Console. A pass will fail to save if the app requesting it isn't registered against your Issuer account.
{% endhint %}

**For a production backend**, sign the same claims programmatically instead of pasting the key into a browser tool each time:

{% tabs %}
{% tab title="Node.js" %}

```javascript
const jwt = require("jsonwebtoken");
const serviceAccount = require("./service-account.json");

function buildSaveJwt(loyaltyObject) {
  const claims = {
    iss: serviceAccount.client_email,
    aud: "google",
    typ: "savetowallet",
    iat: Math.floor(Date.now() / 1000),
    payload: {
      loyaltyObjects: [loyaltyObject],
    },
  };

  return jwt.sign(claims, serviceAccount.private_key, { algorithm: "RS256" });
}
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php
use Firebase\JWT\JWT;

function buildSaveJwt(array $loyaltyObject, array $serviceAccount): string
{
    $claims = [
        'iss' => $serviceAccount['client_email'],
        'aud' => 'google',
        'typ' => 'savetowallet',
        'iat' => time(),
        'payload' => [
            'loyaltyObjects' => [$loyaltyObject],
        ],
    ];

    return JWT::encode($claims, $serviceAccount['private_key'], 'RS256');
}
```

Requires `firebase/php-jwt` (`composer require firebase/php-jwt`).
{% endtab %}
{% endtabs %}

***

## Handing It to WebToNative

The signed JWT is exactly what `Wallet.addPasses` expects in `passes`:

```javascript
window.WTN.Wallet.addPasses({
  passes: [savedJwtFromYourBackend],
});
```

You can also wrap it as `https://pay.google.com/gp/v/save/<jwt>` and pass that string instead — both are accepted.

***

## See Also

* [Google Wallet / Apple Wallet](/javascript-apis/wallet.md) — the `Wallet.*` JavaScript API this feeds into.
* [Apple Wallet (iOS)](/javascript-apis/wallet/wallet-creating-passes/wallet-creating-passes-ios.md) — the iOS side of pass creation.
* [Google Wallet API documentation](https://developers.google.com/wallet)
