Skip to main content
Questions that come up most often when integrating App2App. For the full step-by-step, see setup.
Check for the Coinbase app with canOpenCoinbaseOnramp() before showing your buy button (see Detect the Coinbase app). If it isn’t installed, fall back to Coinbase-hosted Onramp so the user can still complete a purchase.
They need the Coinbase app installed, since that’s what makes the deep-link handoff possible. They don’t need an account beforehand: if they’re not already signed in, Coinbase handles sign-in or account creation (including KYC for new users) inline, inside the Coinbase app, before the purchase continues. You don’t need to build or trigger any of that yourself.Redirecting back into the App2App flow after onboarding isn’t supported yet. If a user signs up for the first time mid-purchase, they land on the Coinbase home screen after onboarding, not back in your in-progress purchase. They’ll need to start the purchase again from your app.
No. They’ll be prompted to update to the latest version if they’re below the minimum acceptable build.
Whatever the signed-in user’s own Coinbase account already supports. App2App doesn’t maintain a separate list of supported payment methods, countries, or limits; it hands off to the same eligibility and payment-method logic every other Coinbase purchase uses. paymentMethod and paymentCurrency on the purchase challenge are prefill hints, not restrictions. For a quick lookup by region, see the Onramp Asset Availability tool or query Buy Config / Buy Options directly.
They’re UX hints, not restrictions. paymentMethod and paymentCurrency prefill the Coinbase app’s funding-source selection; if you omit them, Coinbase lets the signed-in user pick from their own available sources instead. country and subdivision are accepted on the request but aren’t currently used for anything: they’re not validated, not forwarded to the Coinbase app, and don’t gate eligibility. Actual eligibility, payment methods, and limits are always determined from the signed-in user’s own Coinbase account after handoff, not from anything you send on the challenge.
paymentAmount is how much fiat the user spends (for example, "25.00" to spend $25). purchaseAmount is how much crypto the user receives (for example, "0.01" to receive 0.01 ETH). Send exactly one; Coinbase computes the other side of the trade at purchase time.
Only before the Coinbase app opens it, and only within its 15-minute lifetime. Once opened, the session is consumed, so create a new challenge and session for any retry.
Not yet. Use Coinbase-hosted Onramp for Android users.
It’s a native module, and Expo Go only bundles native modules that ship with the Expo SDK itself. Build a custom development client (expo run:ios, expo prebuild, or EAS Build) instead. See Prerequisites in setup.
Partially. @coinbase/cdp-app-attest handles the on-device App Attest ceremony directly and works from React Native or native iOS. @coinbase/cdp-react-native adds canOpenCoinbaseOnramp() for detection and handleOnrampReturn() for the redirect. Neither one wraps the full challenge/session exchange end to end: that function (openCoinbaseOnramp()) exists but doesn’t support the CDP API key your backend now needs to mint challenges, so it isn’t part of the setup guide. See setup for the client + backend pattern to build instead, or onramp-v2-mobile-demo for a full reference implementation. Flutter isn’t supported yet.
Subscribe to onramp transaction webhooks and watch for onramp.transaction.success, the primary way to know a purchase settled. You can also query the transactions API directly if you’d rather pull. Either way, don’t rely on the redirect alone: it’s for updating your UI, not for confirming that funds moved.
No. Sandbox (dry-run) sessions never move funds, so they never create a transaction record: no webhook fires and no row appears when you query the transactions API. The redirect (with its synthetic transactionId) is the only confirmation signal you get in sandbox. See Sandbox testing.
Yes, but only on your backend. Minting the attestation challenge and the purchase challenge both require a CDP API-key JWT; the device never sees the key, only the challenge your backend mints. Registration and session creation stay unauthenticated and can be called directly from the device. You also need a CDP API key to set up a webhook subscription, and a CDP API key JWT if you query the transactions API directly. See setup for which of the four calls need what.
Your registered attestation key may no longer be valid. Clear your local registration with clearOnrampAttestation(), register a new key (Register each device), and retry the purchase once. See the self-heal pattern in setup for the retry logic to wrap this in.