A virtual card is great online. But your users also want to buy coffee, pay for a taxi and shop in stores. They do not carry a card number around on paper. They carry a phone.
That is where Apple Pay and Google Pay come in. Once a crypto card sits in a phone wallet, the user can tap their phone at a card terminal and pay with the stablecoins they loaded. No plastic card is needed.
This guide explains how adding a crypto card to a phone wallet works, where the verification code comes from, how to build the setup screen in your app, and the mistakes that leave users stuck halfway.
#Why phone wallets matter for crypto cards
Our crypto cards are virtual Visa cards. A virtual card has a number, an expiry date and a security code, but nothing to put in a card reader. For online shopping, that is all you need. For shops, it is not.
A phone wallet closes that gap. It turns the virtual card into something you can tap. For most users, this is the moment the card stops feeling like a "crypto thing" and starts feeling like a normal payment card.
There is a second benefit: safety. When a user pays with a phone wallet, the shop never sees the real card number. The phone sends a separate device number and a one-time code for each payment. If a shop's system is ever breached, the user's real card details are not in it.
#What the user needs before they start
Before a user can add their card, a few things must be true:
- The card is issued and active. Set the card up only once its status is active. A frozen card cannot spend, so unfreeze it first.
- The phone supports the wallet. Apple Pay needs an iPhone or Apple Watch. Google Pay needs an Android phone with tap-to-pay support.
- The phone has a screen lock. Both wallets require a passcode, fingerprint or face unlock. Without one, the wallet will refuse the card.
- The card program supports phone wallets. On our current card program, cards can be added to Apple Pay, Google Pay and Samsung Pay. Wallet support belongs to the card program, so check the cards guide when a new program is added.
- The user can open your app. As you will see below, the verification code arrives in your app, not by text message.
#How adding the card works, step by step
Here is the full flow, from the user's first tap to their first payment:
- The user opens Apple Wallet or Google Wallet and chooses to add a card.
- They type in the card number, expiry date and security code. Your app can show these on the card screen so they can copy them.
- The wallet asks the card program to approve the card for this phone.
- The card program asks the user to verify that they own the card. It creates a one-time code.
- Our platform receives that code and holds it for a short time.
- Your server receives a signed
card.wallet_otpwebhook. It tells you a code is waiting. It does not contain the code. - Your app calls
GET /v1/cards/{id}/otpwith the user's id. The response haskind: "wallet_provisioning"and the code. - Your app shows the code. The user types it into the wallet screen.
- The card appears in the wallet. The user can now tap to pay.
The same endpoint also returns 3-D Secure codes for online checkouts. The kind field tells you which is which. Our guide on how 3-D Secure works on a crypto debit card covers the checkout side.
#Where the code does NOT come from
This is the single most common point of confusion.
With a bank card, the wallet usually says "We sent a code to your phone number." Users then wait for a text message. With our card program, no text message is sent and no email is sent. The code only reaches your platform, through the API, and you show it to your user.
The phone wallet's own screen may still say something generic like "verify your card." Your users will not know where to look unless you tell them. So the first job of your setup screen is a clear sentence: "Your code will appear here, in this app."
#Building a good setup screen
A good wallet setup flow feels like one smooth task, not a puzzle split across two apps. These tips help:
- Add a guide on the card screen. A short "Add to Apple Pay / Google Pay" section with three or four steps. Many users do not know a virtual card can live in a phone wallet at all.
- Make the card details easy to copy. Show the number, expiry and security code with copy buttons, behind the same unlock you use for any sensitive screen.
- Push, then pull. When the
card.wallet_otpwebhook arrives, send a push notification: "Your wallet code is ready." Fetch the code only when the user opens the screen. - Offer a manual button. Some users switch back to your app before the webhook lands. A "Get my wallet code" button lets them fetch it themselves.
- Say what the code is for. Use
kindto show "Code to add your card to your phone wallet" instead of a bare number. People trust a code more when they know why they see it. - Keep the code on screen. The code can be read only once. Show it clearly with a copy button and leave it visible while the user switches apps.
- Never store it. Do not write the code to your database, logs, analytics or crash reports. Treat it like a password.
#Common mistakes
| Mistake | What happens | The fix |
|---|---|---|
| Help page says "wait for an SMS" | Users wait for a code that never comes | Point users to your app |
| A background job fetches the code | The code is used up and the user sees nothing | Fetch only when the user is looking |
| Full API responses are logged | A live code ends up on disk | Remove the code field before logging |
| Webhook signature is not checked | Anyone could fake an event | Verify x-cryptoinfra-signature on the raw body |
| User sets up a frozen card | Taps fail at the shop | Show the card status and unfreeze first |
| No screen lock on the phone | The wallet will not accept any card | Mention it in your guide |
The webhooks guide shows exactly how to check the signature header.
#What happens after the card is in the wallet
Once added, the card in the wallet is the same card your user holds in your app. A few things are worth explaining to users:
- The balance is shared. A tap in a shop spends the same balance the user loaded with USDT. There is no separate wallet balance to top up.
- Freezing works everywhere. If a user loses their phone, they can freeze the card in your app. Your server calls
POST /v1/cards/{id}/freeze, and spending stops, including taps from the phone./unfreezeturns it back on. - Card events still arrive. Every payment, tap or online, produces the usual
card.*webhooks, so your transaction list stays complete. - Closing the card ends it. A closed card can no longer pay, in the wallet or anywhere else. The remaining balance goes back on-chain to the user.
Card fees for payments are listed with every other card fee. The live schedule is on the pricing page, so show users real numbers from there instead of guessing.
#A quick checklist before launch
- [ ] Your card screen has a short "add to phone wallet" guide.
- [ ] Card details can be revealed and copied safely.
- [ ] Your webhook endpoint accepts and verifies
card.wallet_otp. - [ ] Your app fetches codes with
GET /v1/cards/{id}/otponly when the user is looking. - [ ] The screen uses
kindto say the code is for a phone wallet. - [ ] Codes are never logged, cached or saved.
- [ ] Your help pages say the code appears in your app, not by text message.
- [ ] Users know how to freeze the card if they lose their phone.
#Give your users a card they can tap
A phone wallet is what turns a virtual crypto card into an everyday card. The work on your side is small: one webhook, one endpoint and a clear screen. Get it right once, and your users can pay in shops from their first day. Sign up for a merchant account and start building your card program today.