Wallet Passes
A member holds one QR token that resolves to a live-updating pass in whichever of Apple Wallet, Google Wallet, or Samsung Wallet they use — balance and tier changes push an update to every pass they’ve saved, debounced to at most once a minute per member. Which wallet providers actually work for a given tenant comes down to one thing: whose certificates sign the pass.
Two ways a tenant gets working passes
Signing a wallet pass needs real provider credentials — an Apple Pass Type ID certificate, a Google Wallet service account, a Samsung Wallet Partner/Card ID and signing key. There are two ways a tenant ends up with a working provider:
| Who configures it | Where the credentials live | Who it covers | |
|---|---|---|---|
| Platform default | The operator running this platform, once | Three optional worker secrets | Every tenant, automatically |
| Bring your own keys (enterprise) | The individual tenant | A wallet_configs row, encrypted at rest |
Just that tenant |
Both can be true for the same provider at once — a tenant’s own row always wins. The platform default only ever fills in for a provider a tenant hasn’t connected themselves.
Platform default
The operator can configure Apple/Google/Samsung Wallet credentials once, platform-wide, as
three optional deploy-time secrets: APPLE_WALLET_PLATFORM_JSON, GOOGLE_WALLET_PLATFORM_JSON,
SAMSUNG_WALLET_PLATFORM_JSON (see the repo’s infra/DEPLOY.md §6 for the exact JSON shape and
setup steps — same class of operator-owned config as the platform-level Square/Clover/Lightspeed
OAuth app credentials). Any tenant that hasn’t connected their own credentials for a
provider automatically gets passes issued under that provider’s platform default the moment it’s
set — no per-tenant action, no migration, nothing to turn on in the dashboard.
This is a genuine fallback, not a demo mode: passes issued under the platform default are real, live-updating passes, pushed through the same signing and push-update code path a tenant’s own credentials use.
The Samsung caveat, stated honestly. Samsung Wallet ties a card’s visual template — layout, branding, colors — to the Partner ID / Card ID registered with Samsung, not to anything set per-pass at issue time. Every tenant riding the Samsung platform default therefore shares the same Samsung card template, registered under the operator’s own Partner/Card ID. That’s an inherent property of how Samsung Wallet works, not a gap in this platform — there’s no per-tenant visual override to build here. A tenant that needs its own Samsung card look has exactly one path: bring their own Samsung Wallet Partner ID, Card ID, and signing keys (below), which registers a card template under their own identity instead.
Bring your own keys (enterprise)
A tenant can connect their own provider credentials any time, from Settings → Wallets in the
merchant dashboard — the same per-tenant wallet_configs row this platform has always supported,
encrypted at rest and never echoed back once saved. When a provider already has a platform
default, the dashboard doesn’t hide this option: it’s offered as a collapsed “Use your own keys
(enterprise)” section under the platform-default card, so it’s available without competing with
the zero-setup default as the primary call to action.
Once a tenant’s own row exists for a provider, it always takes over — every pass for that tenant, on that provider, signs and pushes with the tenant’s own credentials, even if a platform default is also configured. This is the main reason an enterprise tenant would bring their own keys: full control over branding (their own Apple Pass Type ID, their own Samsung card template, their own Google issuer identity) instead of sharing the platform’s.
Deleting your own keys returns you to the platform default — it does not disable the provider, as long as the operator still has that provider’s platform secret configured. If the platform default isn’t available for that provider, deleting really does disable it until you reconnect. The dashboard’s delete confirmation says exactly which of the two will happen before you confirm.
Checking what’s active: GET /v1/wallet-configs
Every provider’s status is visible from one endpoint. items lists only the tenant’s own rows
(unchanged from before this feature existed); the additive providers map always reports all
three keys regardless of whether a row exists:
{
"items": [ /* ...this tenant's own connected providers, if any... */ ],
"providers": {
"apple": { "source": "tenant", "platform_available": true },
"google": { "source": "platform", "platform_available": true },
"samsung": { "source": "none", "platform_available": false }
}
}
source—"tenant"when this tenant has their own row for that provider (always reported this way even if a platform default also exists — the row is what’s actually signing passes);"platform"when there’s no tenant row but the platform default covers it;"none"when neither exists, so that provider doesn’t work for this tenant yet.platform_available— independent ofsource: true only when that provider’s platform secret is both present and valid. This is what tells you, before deleting a tenant row, whether doing so lands on the platform default or disables the provider.
Connecting your own keys
Each provider’s card in Settings → Wallets lists exactly what you need before connecting, and the connect form asks for exactly these fields (write-only — never shown again once saved):
| Provider | You’ll need | Credential fields |
|---|---|---|
| Apple | An active Apple Developer Program membership; a registered Pass Type ID and its signing certificate (PEM); the Apple WWDR intermediate certificate (PEM); an APNs auth key (.p8) with its Key ID and your Team ID, for push updates. |
cert_pem, key_pem, wwdr_pem, apns_key_p8, apns_key_id, apns_team_id, pass_type_id |
| A Google Wallet API issuer account (Google Pay & Wallet Console) and issuer ID; a service account with the Wallet Object Issuer role and its downloaded JSON key. | service_account_json, issuer_id |
|
| Samsung | Onboarding on the Samsung Wallet Partners Portal — partner ID, card ID, and signing key material. Samsung’s partner approval can take significant lead time end to end; start it well before you need live Samsung passes. Passes ship fully against test credentials in the meantime. | partner_id, card_id, certificate_id, private_key_pem, samsung_public_key_pem |
Member-facing wallet buttons
Once a provider works for a tenant — platform default or their own keys, doesn’t matter which — members see an “Add to Wallet” button for it wherever the platform surfaces wallet links: the public per-member wallet page, and the member portal’s Wallet tab. Both read from the same one-token-per-member, one-builder link response, so a provider that just started working under the platform default appears there immediately, with no separate step.
Related
- Member portal — the member-facing Wallet tab and its lazily-issued wallet-link token.
- API reference — full request/response shapes for
/v1/wallet-configsand/v1/wallet/links/:token.