Skip to content

Wallet component

<govifi-wallet> is a framework-agnostic web component for managing a customer’s saved payment methods — list, add, remove, and set a default. It is a sibling of <govifi-payment> and shares its PCI posture: raw card data only ever lives in the origin-isolated card iframe.

It is management only — add, delete, and set-default. There is no editing or nicknaming a method, and the autopay badge is display-only (the component never changes autopay enrollment).

The wallet rides a wallet-scoped hosted session — a hosted session created with scope: "wallet". It carries the same browser credential (client_secret) as a payment session, but the scope gates it to saved-method management: payment endpoints (confirm/quote-fee) reject a wallet credential, and these wallet endpoints reject a payment credential (insufficient_scope). Create one server-side, then hand the client_secret to the component.

POST /v1/hosted-sessions
{ "scope": "wallet", "customer_id": "cus_…", "amount": 0, "currency": "USD" }

A wallet session needs no payable amount or redirect URLs. Optionally attach display badges and delete-locks to specific saved methods (see Badges & delete locks):

{
"scope": "wallet",
"customer_id": "cus_…",
"method_badges": [
{ "label": "Autopay", "color": "#1A7F4B", "payment_method_uids": ["SPM_…"] }
],
"locked_payment_methods": [
{ "payment_method_uid": "SPM_…", "reason": "Used for Autopay" }
]
}

Response (same shape as any hosted session):

{
"session_id": "cs_…",
"client_secret": "cs_…_secret_…",
"expires_at": "2026-01-01T00:00:00.000Z"
}

Browser calls authenticate with Authorization: Bearer <client_secret>, are origin-allowlisted, and require the wallet scope. The component drives these for you:

MethodEndpointResult
GET/v1/hosted-sessions/{id}/payment-methods{ methods: SavedMethodSummary[], allowed_methods: string[] }
POST/v1/hosted-sessions/{id}/payment-methodsSavedMethodSummary (the saved method)
DELETE/v1/hosted-sessions/{id}/payment-methods/{uid}204 — the default and any locked method can’t be deleted (rejected)
PUT/v1/hosted-sessions/{id}/default-payment-methodrefreshed SavedMethodSummary[]

The add body matches the save-a-method shape:

{
"payment_method": {
"payment_method_type": "credit",
"credit": { "fingerprint": "", "last4": "4242", "exp_month": 12, "exp_year": 2027, "card_brand": "VISA" }
}
}

For ACH, use "payment_method_type": "ach" with an ach object (bank_name, fingerprint, routing_number, account_number_suffix, account_type). The set-default body is { "payment_method_uid": "…" }.

AttributeDescription
session-idWallet-scoped session id from POST /v1/hosted-sessions (scope: "wallet")
client-secretThe wallet session’s client_secret (sent as Authorization: Bearer)
api-baseOverride the API origin (sandbox/staging)
elements-baseOverride the secure card-fields iframe origin
themelight (default) · dark · auto
accentHex accent color, e.g. #0B5FFF (hover/tint shades are derived)
fontFont token (inter · system · roboto) or a literal font-family stack
layoutcard (default, full chrome) · embedded (flush, no shadow)

The methods shown in the add form are server-driven — the savable subset (card/ach) of the session’s allowed_methods — so there’s no methods attribute. The wallet never offers a method the account/session can’t save.

Badges and delete-locks are host-supplied at session creation (not component attributes) — the API resolves them per-method onto each SavedMethodSummary:

badges?: { label: string; color: string }[] // display-only chips, label + hex color
deletable?: boolean // false = locked (Remove disabled + server-rejected)
lock_reason?: string // shown as the disabled-Remove hint

The component is purely a viewer for these — it assigns no meaning (PaymentApi doesn’t own concepts like “autopay”). A lock is enforced server-side: the DELETE is rejected (403 operation_not_allowed) even if called directly, and the UI disables Remove with lock_reason as the hint. To badge a method as “Autopay” and prevent its deletion, pass method_badges + locked_payment_methods when creating the session (see Create).

const el = document.querySelector('govifi-wallet');
el.methods // SavedMethodSummary[] — the current saved methods
el.strings // host-injected i18n string map (transloco-compatible)
el.achTokenizer // (ach) => Promise<{ token, last4? }> — tokenize ACH bank details

achTokenizer is required for the ACH add path: the host supplies the processor token (the component never sends raw bank details). Card details come from the card iframe, so no card tokenizer is needed on the host.

All events are CustomEvents that bubble and compose across the shadow boundary; payloads live on event.detail.

EventdetailWhen
wallet.ready{ methods }Methods loaded
wallet.method-added{ method }A method was saved
wallet.method-deleted{ method }A method was removed
wallet.default-changed{ method, methods }The default changed (list refreshed)
wallet.error{ code, message }A load or mutation failed

error.detail.code is one of the shared payment error codes (e.g. validation_error, processing_error, network_error, session_expired).