# Google Wallet API

The Google Wallet API lets you create, update, list, and manage [Google Wallet passes](/product/messaging-channels/google-wallet-passes/) programmatically. It supports the same operations the [pass builder](/product/messaging-channels/google-wallet-passes/pass-builder/) in the Control Panel performs.

Use it to issue loyalty cards, offers, gift cards, event tickets, flight boarding passes, transit tickets, and generic passes, and to push live updates to passes already saved on your users' devices.

<Aside type="note" title="Prerequisite: Google Wallet configuration">
Before you can create passes for an application, a Google Wallet **Issuer ID** and **service account key** must be configured for that application in the Pushwoosh Control Panel. Without them, `create` and `update` requests fail. See [Google Wallet pass configuration for Android](/developer/first-steps/connect-messaging-services/android-configuration/android-google-wallet-configuration/).
</Aside>


## Base URL

```
https://apple-passkit.svc-nue.pushwoosh.com
```

All endpoints are served over HTTPS. Requests and responses use `application/json` unless noted otherwise.

## Authentication

Every request must include an `Authorization` header with your [Pushwoosh API access token](/developer/api-reference/api-access-token/):

```
Authorization: Token <api-token>
```

The account that owns the token must own the application referenced by `applicationCode`. A request for an application that belongs to another account returns `403 Forbidden`.

## Conventions

* **Field naming:** JSON fields use `lowerCamelCase` (for example, `serialNumber`, `hexBackgroundColor`, `logoUrl`).
* **Unpopulated fields:** responses include all fields, even when empty or zero-valued.
* **Identity:** the `serialNumber` is always assigned by the server when a pass is created. Any value you send on create is ignored. The full Google Wallet object id is `{issuerId}.{serialNumber}`.
* **Images:** `logoUrl` and `heroImageUrl` are public HTTPS URLs to images Google fetches—not uploaded files.
* **Pass style:** exactly one style object (`generic`, `offer`, `loyalty`, `eventTicket`, `giftCard`, `flight`, or `transit`) must be set on a pass. The style cannot change after creation.

### Error responses

| HTTP status | Meaning |
| :---- | :---- |
| `400 Bad Request` | Invalid argument—a required field is missing or malformed. |
| `401 Unauthorized` | Missing or invalid `Authorization` header. |
| `403 Forbidden` | The application does not belong to the caller's account. |
| `404 Not Found` | The pass, template, or application was not found. |
| `503 Service Unavailable` | The service is at capacity or temporarily unavailable. |

## Endpoints

| Method | Path | Description |
| :---- | :---- | :---- |
| `POST` | `/api/google/pass/validate` | Validate a pass configuration |
| `POST` | `/api/google/pass/create` | Create a new pass object and get a save link |
| `POST` | `/api/google/pass/update/{serialNumber}` | Update an existing pass; Google delivers the change |
| `GET` | `/api/google/pass/{applicationCode}/{serialNumber}/save-link` | Get an "Add to Google Wallet" save link |
| `GET` | `/api/google/pass/{applicationCode}/{serialNumber}` | Get a single pass |
| `GET` | `/api/google/passes` | List all passes for an application |
| `POST` | `/api/google/pass/{applicationCode}/{serialNumber}/state` | Activate or invalidate a pass |
| `DELETE` | `/api/google/pass/{applicationCode}/{serialNumber}` | Delete a pass |
| `GET` | `/api/google/config` | Get the application's Google Wallet configuration |
| `GET` | `/api/google/templates` | List available pass templates |
| `GET` | `/api/google/templates/{filename}` | Get a single template |

## Create a pass

Creates the pass class and object in Google Wallet, then returns the server-assigned serial number, the full object id, and an "Add to Google Wallet" save link.

`POST` `/api/google/pass/create`

### Request body

| Parameter | Type | Required | Description |
| :---- | :---- | :---- | :---- |
| `pass` | object | Yes | The [pass object](#pass-object) describing the pass. Exactly one style must be set. |
| `userId` | string | Yes | The [Pushwoosh User ID](/developer/api-reference/api-identifiers/#user-id) the pass is issued to. |
| `applicationCode` | string | Yes | The [Pushwoosh application code](/developer/api-reference/api-identifiers/#application-code). |

##### Request example

```json
{
  "applicationCode": "XXXXX-XXXXX",
  "userId": "user-123",
  "pass": {
    "hexBackgroundColor": "#3c414c",
    "logoUrl": "https://cdn.acme.com/logo.png",
    "loyalty": {
      "programName": "Acme Rewards",
      "accountName": "Jane Doe",
      "accountId": "1234567890",
      "pointsLabel": "Points",
      "pointsBalance": "1200",
      "rewardsTier": "Gold"
    },
    "barcode": {
      "format": "QR_CODE",
      "value": "1234567890"
    }
  }
}
```

### Response

| Field | Type | Description |
| :---- | :---- | :---- |
| `serialNumber` | string | Server-assigned unique identity of the created pass. |
| `objectId` | string | Full Google Wallet object id: `{issuerId}.{serialNumber}`. |
| `saveLink` | string | "Add to Google Wallet" link: `https://pay.google.com/gp/v/save/{jwt}`. |
| `message` | string | Result message. |

##### Response example

```json
{
  "serialNumber": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "objectId": "XXXXXXXXXXXXXXX.XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
  "saveLink": "https://pay.google.com/gp/v/save/{jwt}",
  "message": "Pass created successfully"
}
```

## Validate a pass

Checks a pass configuration against Google's requirements without creating it. Useful before calling create.

`POST` `/api/google/pass/validate`

### Request body

| Parameter | Type | Required | Description |
| :---- | :---- | :---- | :---- |
| `pass` | object | Yes | The [pass object](#pass-object) to validate. |

### Response

| Field | Type | Description |
| :---- | :---- | :---- |
| `valid` | boolean | Whether the pass passes validation. |
| `errors` | array of strings | Blocking problems that must be fixed. |
| `warnings` | array of strings | Non-blocking advisories. |

## Update a pass

Patches the pass object with new content. Google then delivers the updated version to every device that saved the pass. Optionally sends an Android notification with the update.

`POST` `/api/google/pass/update/{serialNumber}`

### Path parameters

| Parameter | Type | Description |
| :---- | :---- | :---- |
| `serialNumber` | string | The serial number returned when the pass was created. |

### Request body

| Parameter | Type | Required | Description |
| :---- | :---- | :---- | :---- |
| `updates` | object | Yes | The [pass object](#pass-object) with the new content. The style cannot change. |
| `applicationCode` | string | Yes | The [Pushwoosh application code](/developer/api-reference/api-identifiers/#application-code). |
| `notifyMessage` | string | No | When non-empty, push an Android notification with this text to everyone who saved the pass. Empty means a silent update. |
| `notifyOnUpdate` | boolean | No | Request a field-update notification. Only `loyalty`, `eventTicket`, and `flight` passes actually notify; other styles accept the flag but never send one. Notifications fire only within 3 hours of a relevant start time, and Google limits them to 3 notifications per pass per 24 hours. |

<Aside type="note" title="Two ways to notify on update">
`notifyMessage` sends a custom Android notification to everyone who saved the pass and works for any pass style. `notifyOnUpdate` asks Google to send its own field-update notification, which only fires for `loyalty`, `eventTicket`, and `flight` passes.
</Aside>

### Response

| Field | Type | Description |
| :---- | :---- | :---- |
| `success` | boolean | Whether the update succeeded. |
| `message` | string | Result message. |

## Get a save link

Returns an "Add to Google Wallet" save link for an already created pass. The pass object must already exist (created via [Create a pass](#create-a-pass)).

`GET` `/api/google/pass/{applicationCode}/{serialNumber}/save-link`

### Response

| Field | Type | Description |
| :---- | :---- | :---- |
| `saveLink` | string | `https://pay.google.com/gp/v/save/{jwt}`. |

<Aside type="tip" title="Share the link or render it as a QR code">
Put the `saveLink` behind an "Add to Google Wallet" button, or render it as a QR code with any QR library. When a user opens it, Google prompts them to save the pass and registers their device for updates.
</Aside>

## Get a pass

Returns a single stored pass, including its full pass object.

`GET` `/api/google/pass/{applicationCode}/{serialNumber}`

### Response

Returns `{ "pass": { ... } }`, a single [pass record](#pass-record-object).

## List passes

Returns a paginated, sorted list of the passes stored for an application.

`GET` `/api/google/passes?applicationCode=XXXXX-XXXXX&page=0&perPage=20`

### Query parameters

| Parameter | Type | Required | Description |
| :---- | :---- | :---- | :---- |
| `applicationCode` | string | Yes | The [Pushwoosh application code](/developer/api-reference/api-identifiers/#application-code). |
| `orderBy` | string | No | Sort field: `UPDATED` (default) or `CREATED`. |
| `orderDirection` | string | No | Sort direction: `DESC` (default, newest first) or `ASC`. |
| `page` | integer | No | Zero-based page index. Defaults to `0`. |
| `perPage` | integer | No | Page size. `0` or omitted uses the server default. |

### Response

| Field | Type | Description |
| :---- | :---- | :---- |
| `passes` | array of objects | The current page of [pass records](#pass-record-object). |
| `page` | integer | The returned page index. |
| `perPage` | integer | The page size used for this response. |
| `total` | integer | Total number of passes for the application across all pages. |

## Set pass state

Activates or invalidates a pass. An invalidated (inactive) pass moves to the user's **Expired passes** section in Google Wallet; the record is kept so it can be re-activated.

`POST` `/api/google/pass/{applicationCode}/{serialNumber}/state`

### Request body

| Parameter | Type | Required | Description |
| :---- | :---- | :---- | :---- |
| `active` | boolean | Yes | `true` sets the pass to `ACTIVE`; `false` invalidates it (`INACTIVE`). |

### Response

Returns an empty object `{}` on success.

## Delete a pass

Invalidates the pass in Google and removes its stored record in Pushwoosh.

`DELETE` `/api/google/pass/{applicationCode}/{serialNumber}`

<Aside type="caution" title="A saved pass cannot be force-removed">
Google does not allow removing a pass already saved on a user's device. Delete invalidates the pass (it moves to **Expired passes**) and drops the Pushwoosh record.
</Aside>

### Response

Returns an empty object `{}` on success.

## Get configuration

Returns the Google Wallet configuration state for an application.

`GET` `/api/google/config?applicationCode=XXXXX-XXXXX`

### Response

| Field | Type | Description |
| :---- | :---- | :---- |
| `hasServiceAccount` | boolean | Whether a service account key is configured. |
| `issuerId` | string | The configured [Google Pay & Wallet Console Issuer ID](/developer/first-steps/connect-messaging-services/android-configuration/android-google-wallet-configuration/#create-the-issuer-account). |
| `serviceAccountEmail` | string | The `client_email` of the configured [service account](/developer/first-steps/connect-messaging-services/android-configuration/android-google-wallet-configuration/#create-the-service-account-key). |

## Templates

List the available example pass templates, or fetch one as a [pass object](#pass-object) you can use as a starting point.

`GET` `/api/google/templates` — returns `{ "templates": [ { "filename", "name", "description", "style" } ] }`.

`GET` `/api/google/templates/{filename}` — returns `{ "template": { ...pass object... } }`.

## Object reference

### Pass object

| Field | Type | Description |
| :---- | :---- | :---- |
| `serialNumber` | string | Assigned by the server on create; identifies the pass. |
| `generic` / `offer` / `loyalty` / `eventTicket` / `giftCard` / `flight` / `transit` | object | The pass style. **Exactly one** must be set. See the style objects below. |
| `hexBackgroundColor` | string | Card background color, `#rrggbb`. |
| `logoUrl` | string | Public HTTPS URL of the logo image. Required for loyalty and transit. |
| `heroImageUrl` | string | Public HTTPS URL of a wide banner image. |
| `barcode` | object | [Barcode](#barcode-object) shown on the pass. |
| `textModules` | array | [Text modules](#text-module-object) shown in the details view. |
| `links` | array | [Link modules](#link-module-object) shown in the details view. |
| `expirationTime` | string | ISO 8601 time when Google auto-expires the pass. Empty means no expiry. |
| `appLink` | object | [App link](#app-link-object): a CTA button on the front of the pass. |
| `locations` | array | [Locations](#location-object) that trigger a geofenced notification (max 10). |
| `holdersPolicy` | string | Who may save the pass: `ONE_USER_ALL_DEVICES` (default), `ONE_USER_ONE_DEVICE`, or `MULTIPLE_HOLDERS`. |

### Generic object

| Field | Type | Description |
| :---- | :---- | :---- |
| `cardTitle` | string | Required. The issuer/program name at the top of the card. |
| `header` | string | Required. The main title of the card. |
| `subheader` | string | Secondary title. |
| `cardFields` | array | Up to 6 [text modules](#text-module-object) pinned to the front (up to 3 rows of 2). |

### Offer object

| Field | Type | Description |
| :---- | :---- | :---- |
| `title` | string | Required. For example, `20% off everything`. |
| `provider` | string | Required. The merchant name. |
| `details` | string | Offer details. |
| `finePrint` | string | Terms and conditions. |
| `redemptionChannel` | string | `ONLINE`, `INSTORE`, `BOTH` (default), or `TEMPORARY_PRICE_REDUCTION`. |
| `issuerName` | string | Shown on Google's "issued by" surfaces; defaults to `provider`. |

### Loyalty object

| Field | Type | Description |
| :---- | :---- | :---- |
| `programName` | string | Required. Requires `logoUrl` on the pass. |
| `accountName` | string | Member name shown on the card. |
| `accountId` | string | Member id shown on the card. |
| `pointsLabel` | string | For example, `Points`. Shown only with a balance. |
| `pointsBalance` | string | The points balance. |
| `rewardsTier` | string | For example, `Gold`. |
| `rewardsTierLabel` | string | Label next to the tier; defaults to `Tier`. |
| `issuerName` | string | Defaults to `programName`. |

### Event ticket object

| Field | Type | Description |
| :---- | :---- | :---- |
| `eventName` | string | Required. |
| `venueName` / `venueAddress` | string | Venue details. |
| `startDateTime` / `endDateTime` | string | ISO 8601 with offset (for example, `2026-07-01T19:30:00+02:00`). |
| `ticketHolderName` / `ticketNumber` / `ticketType` | string | Holder and ticket details. |
| `section` / `row` / `seat` / `gate` | string | Seating details. |
| `issuerName` | string | Defaults to `eventName`. |

### Gift card object

| Field | Type | Description |
| :---- | :---- | :---- |
| `merchantName` | string | Required. |
| `cardNumber` | string | Required. |
| `pin` | string | Card PIN. |
| `balance` | string | Decimal amount, for example `25.00`. Requires `balanceCurrency`. |
| `balanceCurrency` | string | ISO 4217 currency code, for example `USD`. |
| `issuerName` | string | Defaults to `merchantName`. |

### Flight object

| Field | Type | Description |
| :---- | :---- | :---- |
| `carrierIataCode` | string | Required. 2-letter IATA code, for example `LX`. |
| `airlineName` | string | Airline display name. |
| `flightNumber` | string | Required. Digits only, for example `113`. |
| `originAirportCode` / `destinationAirportCode` | string | Required. 3-letter IATA codes. |
| `originTerminal` / `originGate` / `destinationTerminal` | string | Terminal and gate details. |
| `departureDateTime` | string | Required. Origin airport **local** time, ISO 8601 **without** offset (for example, `2026-09-01T06:30:00`). |
| `boardingTime` / `arrivalDateTime` | string | Same local format. `arrivalDateTime` is destination local time. |
| `passengerName` | string | Required. |
| `confirmationCode` / `seatNumber` / `seatClass` / `boardingGroup` | string | Passenger details. |
| `issuerName` | string | Defaults to `airlineName`, then the carrier code. |

### Transit object

| Field | Type | Description |
| :---- | :---- | :---- |
| `transitType` | string | Required. `BUS`, `RAIL`, `TRAM`, `FERRY`, or `OTHER`. |
| `transitOperatorName` | string | Required. Requires `logoUrl` on the pass. |
| `passengerName` | string | Required. |
| `ticketNumber` | string | Ticket number. |
| `tripType` | string | `ONE_WAY` (default) or `ROUND_TRIP`. |
| `legs` | array | One or more [transit legs](#transit-leg-object) in travel order. |
| `issuerName` | string | Defaults to `transitOperatorName`. |

### Transit leg object

| Field | Type | Description |
| :---- | :---- | :---- |
| `originName` / `destinationName` | string | Required. |
| `departureDateTime` / `arrivalDateTime` | string | ISO 8601; offset optional (local time when omitted). |
| `platform` / `coach` / `seat` | string | Boarding details. |
| `fareName` | string | For example, `Anytime Single`. |

### Barcode object

| Field | Type | Description |
| :---- | :---- | :---- |
| `format` | string | `QR_CODE`, `PDF_417`, `AZTEC`, `CODE_128`, `EAN_13`, and other Google Wallet barcode types. |
| `value` | string | Data encoded in the barcode. |
| `altText` | string | Text shown below the barcode. |

### Text module object

| Field | Type | Description |
| :---- | :---- | :---- |
| `id` | string | Identifier of the module. |
| `header` | string | Module heading. |
| `body` | string | Module text. |

### Link module object

| Field | Type | Description |
| :---- | :---- | :---- |
| `uri` | string | External link URL. |
| `description` | string | Link label shown in the details view. |

### App link object

| Field | Type | Description |
| :---- | :---- | :---- |
| `uri` | string | Web URL or deep-link target URI. |
| `androidPackageName` | string | Optional. When set, opens the Android app. |
| `description` | string | Internal description of the target URI (not a visible button label); defaults to the URI. |

### Location object

| Field | Type | Description |
| :---- | :---- | :---- |
| `latitude` | number | `-90.0` to `+90.0`. |
| `longitude` | number | `-180.0` to `+180.0`. |

### Pass record object

Returned by list/get endpoints.

| Field | Type | Description |
| :---- | :---- | :---- |
| `serialNumber` | string | Pass serial number. |
| `objectId` | string | Full Google Wallet object id `{issuerId}.{serialNumber}`. |
| `cardTitle` | string | Display title/header for the pass. |
| `header` | string | Secondary display title. |
| `userId` | string | [Pushwoosh User ID](/developer/api-reference/api-identifiers/#user-id) the pass was issued to. |
| `createdAt` / `updatedAt` | string | Creation and last-update timestamps. |
| `state` | string | `ACTIVE` or `INACTIVE`. |
| `style` | string | `generic`, `offer`, `loyalty`, `eventTicket`, `giftCard`, `flight`, or `transit`. |
| `pass` | object | The full [pass object](#pass-object), for editing. |