Skip to main content
Your iOS app presents the Vault’s links in a Safari view: the add-a-card page and the approval page open inside your app, and the user’s passkey works there.

Open the Vault in a Safari view

Create a vault session on your server, hand the url to the app, and present it with SFSafariViewController.
Use SFSafariViewController rather than WKWebView. The Vault saves the user’s card behind a passkey, and a Safari view shares Safari’s passkeys, so a returning user unlocks with Face ID inside your app. Inside a WKWebView the page cannot complete the passkey prompt and asks the user to open the link in Safari instead. Create the session on your server and hand the app only the url. Your client_secret never ships in the app binary. Open the approval link the same way. When your agent reaches the payment form, onApprovalUrl fires with a link; present it in the same Safari view, or send it by push notification if the user is not in the app. When the user finishes, you receive vault.session_linked with their user_id, then vault.card_stored. Store the user_id: it is what you pass as user on every checkout. Without webhooks, poll the session instead.

Confirm with webhooks

The user dismissing the Safari view is a claim. Your server should act on webhooks, because the view can close before your app hears anything:
  • vault.card_stored when a card lands in the vault.
  • checkout_authorization.approved and the other checkout_authorization.* events when purchases are approved or declined.

Test it

A sandbox token creates a sandbox session. Present the link on your own device, store any of Stripe’s published test cards, any future expiry, any CVC. Rehearse a purchase against shop.agentcard.sh, a demo store on Stripe test mode. Next: Create a cart.