Passes
A pass is one instance of a template for one end-user โ a customer's loyalty card, an attendee's event ticket, a traveller's boarding pass.
Intents
The intent field determines how the worker maps your data to
Apple Wallet and Google Wallet object types.
| intent | Google Type | Apple PassStyle |
|---|---|---|
| generic | GenericObject | Generic |
| loyalty_card | LoyaltyObject | StoreCard |
| coupon | OfferObject | Coupon |
| event_ticket | EventTicketObject | EventTicket |
| boarding_pass | FlightObject | BoardingPass |
Create a Pass
/api/v1/passes
Returns 202 Accepted. The pass is created asynchronously per provider.
Headers
| Header | Description | |
|---|---|---|
| Authorization | required | Bearer {token} |
| Idempotency-Key | optional | Any client-generated key. Same key + tenant returns the original pass. |
Body
| Field | Type | Description | |
|---|---|---|---|
| template_id | UUID | required | Must reference a Template the tenant owns or a system template. |
| external_ref | string | required | Your customer-side id. Unique per (tenant, external_ref); idempotent re-POST. |
| intent | enum | optional | Defaults to generic. Must match the template's template_type (Generic is the wildcard). |
| data | object | optional | Free-form key/value bag the worker uses to fill template placeholders. |
| meta | object | optional | Pass-through metadata. Stored on the pass; not sent upstream by default. |
| google_grouping_id | string | optional | Google groupingInfo.groupingId (max 64). Groups passes โ even of different
types โ in Google Wallet. Wins over the id derived from linked_to_external_ref.
On update, an empty string "" removes the grouping. |
| google_sort_index | integer | optional | Google groupingInfo.sortIndex (≥ 0). Only takes effect together with a
google_grouping_id. |
| apple_grouping_identifier | string | optional | Apple groupingIdentifier (max 64). On update, "" removes it.
Applied ONLY to event_ticket and boarding_pass passes (see note). |
apple_grouping_identifier supplied for any other pass style is ignored, and the response
carries a warnings entry to say so. Google groups all pass types via
google_grouping_id. All three fields are also accepted on PATCH (update) and
on PUT /passes/by-external-ref/{externalRef}; an empty string clears the stored value.
When it reaches the wallet: grouping is written to the Google object and the Apple pass at creation. An
update that sets or changes a Google grouping field
(google_grouping_id/google_sort_index) now also pushes groupingInfo
to the already-issued Google object (v3-139). Removing a Google grouping
(google_grouping_id: "") is applied via the update and takes effect on the object
(device-verified); Google does not formally guarantee it, so a warnings entry is returned.
A plain data-only update and auto-updates/template-updates never touch groupingInfo (an
existing grouping is never lost). Apple applies apple_grouping_identifier
only when the pass is added to Wallet: an update reaches already-installed tickets/boarding
passes but does not regroup them until the pass is removed and added again โ so an update that
changes apple_grouping_identifier on a ticket/boarding pass returns a warnings
entry saying so.
Linked passes vs. grouping (v3-139): a pass created with
linked_to_external_ref is an auto-linked pass โ it appears inside the primary's
stack in Google Wallet, and if the primary is already saved on the device Google delivers the linked
pass automatically (best effort, possibly delayed; the user can turn this off). The link
(linkedObjectIds) never overwrites a grouping: the linked secondary inherits the primary's
effective groupingId (unless it supplies its own), and the primary keeps its own. Apple has
no equivalent โ linking is Google-only.
Apple auto-stacking: Apple stacks coupons and store cards automatically by their certificate (
passTypeIdentifier), independently of apple_grouping_identifier
(which only affects event tickets and boarding passes). Passes issued under the same Apple certificate
may therefore appear stacked on the device even without an explicit grouping.
| Grouping | Apple | |
|---|---|---|
| On create | All pass types, also mixed (google_grouping_id). |
Only event tickets & boarding passes (apple_grouping_identifier). |
| Change / remove | Applied immediately via the update (device-verified). | Reaches installed passes, but regroups only after the pass is removed & re-added. |
| Coupons / store cards | Grouped by google_grouping_id like any type. |
Auto-stacked by certificate (passTypeIdentifier); grouping identifier has no effect. |
Linking (linked_to_external_ref) |
Google-only; also after the fact โ the linked pass appears automatically in the primary's stack (best effort). | No equivalent. |
Example
/api/v1/passes
{
"template_id": "3f2a1b4c-...",
"intent": "loyalty_card",
"external_ref": "cust-42",
"data": {
"member_name": "Maria Schmidt",
"member_id": "MBR-042",
"points": "2400"
}
}
{
"id": "57725a27-...",
"tenant_id": "...",
"template_id": "3f2a1b4c-...",
"external_ref": "cust-42",
"status": "pending",
"version": 1,
"providers": {
"google": { "status": "queued" },
"apple": { "status": "queued" }
},
"job_id": "...",
"created_at": "2026-05-18T10:00:00Z"
}
Get a Pass
/api/v1/passes/{id}
The response includes per-provider state โ poll this endpoint until status stabilises.
Pass status values
| status | Meaning |
|---|---|
| pending | No provider has completed yet. |
| active | Every provider job is completed. |
| partial | At least one provider completed, others still in-flight or failed. |
| failed | All provider jobs failed terminally. |
| updating | An UpdatePass job is in-flight. |
| revoked | The pass has been revoked. |
| expired | Time-based expiry reached. |
| deleted | Soft-deleted; hidden from list/get. |
Provider status object
"providers": {
"google": {
"status": "completed",
"save_link": "https://pay.google.com/gp/v/save/...",
"object_id": "3388000000023021962.tenant1234_cust42"
},
"apple": {
"status": "completed",
"download_url": "https://api.walletplatform.io/api/v1/passes/57725a27-.../pkpass",
"serial_number": "57725a27-2093-42d0-8cb9-d4f1a5e9b3c7"
}
}
List Passes
/api/v1/passes?page=1&page_size=20&status=active&external_ref=cust-42
Update a Pass
/api/v1/passes/{id}
Updates the pass data. Each active provider gets its own UpdatePass
job; Apple devices receive an APNs push notification so they pull the new
.pkpass on the next sync.
Revoke a Pass
/api/v1/passes/{id}
Marks the pass revoked and notifies every active provider. Apple
devices flip the pass to expired on the next pull; Google's upstream object
is patched to EXPIRED.
Version history
/api/v1/passes/{id}/versions
Returns every version row (Create / Update / Revoke), newest first.
Download pkpass
/api/v1/passes/{id}/pkpass
Apple-specific. Authenticates via the per-pass auth token in
Authorization: ApplePass {token} (the same token embedded in the
.pkpass file). Returns application/vnd.apple.pkpass.