Overview
In-app 3DS push provisioning means the cardholder approves or declines a card transaction’s 3D Secure (3DS) challenge directly inside the app, in real time instead of being redirected to a bank page, sent an SMS one-time passcode, or otherwise taken out of the app for verification. While a transaction is in flight, the pending challenge is delivered to the app (by webhook or by polling the API), the cardholder reviews the merchant, amount, and expiry on screen, and approves or declines by signing with their connected wallet. There’s no redirect, no context switch, and no separate 3DS page.End-to-end flow
Discovering a pending challenge
A challenge can be discovered one of two ways. Both produce the samechallengeId, which drives the identical decision flow described below.
- Webhook (push)
- Polling the API (pull)
Subscribe to the Use
card.3ds.challenge.created event. It fires as soon as a challenge is created for a card no polling required.data.id directly as challengeId. data.notificationAttempt is a redelivery counter webhooks can be delivered more than once, so handle deliveries idempotently, keyed on data.id.The webhook and the list/detail endpoints don’t use identical field names for the same data: the webhook’s
merchant.name / merchant.mcc correspond to the REST endpoints’ merchant.displayName / merchant.categoryCode. Key off data.id (or id) and re-fetch via GET /3ds/challenges/{challengeId} if you need the canonical field names, don’t assume the two shapes match 1:1.Deciding a challenge
Approve and decline go through the identical signed flow, there is no unsigned decline shortcut.1
Show the verification prompt
Display the merchant, the amount (convert the minor-unit
amount using the challenge’s own decimals value, never assume 2 decimal places), currency, and optional country / MCC. Count down to expiresAt, adjusted for clock skew using serverTime. If the countdown reaches zero, treat the challenge as expired and move to the next pending one, if any.2
Request decision-bound typed data
3
Sign with the connected wallet
Pass the typed data to the wallet’s
signTypedData method and have the cardholder confirm in their wallet.4
Submit the signed decision
5
Poll for the outcome
pending or processing, keep polling. Stop as soon as a terminal status is returned and show it to the cardholder. If the poll itself errors, retry rather than declaring failure the decision may already be recorded server-side.