Getting Started
Get up and running with the Oobit Plug & Pay SDK in your React Web application
The Oobit React Web SDK embeds the Plug & Pay widget in your React web app, enabling crypto-to-card payment experiences for your users.
Installation
Latest version: 1.3.3
npm install @oobit/react-webOr with yarn:
yarn add @oobit/react-webChoose Your Integration
Plug & Pay supports two integration modes for funding the card. Which one you use is configured on your partner account — if you're not sure, check with your Oobit account manager.
| Widget-Managed Flow (default) | Standalone Flow | |
|---|---|---|
| Who builds the deposit transaction | The widget — your app receives a ready-to-sign TransactionRequest and broadcasts it | Your app — using Oobit's Partner API to fetch the user's deposit address |
| What you pass the SDK | userWalletAddress + onTransactionRequested | onDepositRequested (+ optional email / externalUserId) |
| Deep dive | Widget-Managed Deposits | API-Managed Deposits |
Basic Usage
import { WidgetSDK } from "@oobit/react-web";
function MyPage() {
return (
<WidgetSDK
accessToken={accessToken}
userWalletAddress="0x1234567890abcdef..."
onTransactionRequested={(transaction) => {
// Navigate to your transaction confirmation screen
router.push("/confirm-transaction");
}}
/>
);
}import { WidgetSDK, type StandaloneConfig } from "@oobit/react-web";
function MyPage() {
return (
<WidgetSDK
accessToken={accessToken}
email="[email protected]" // optional - prefills onboarding
externalUserId="your-internal-user-id" // optional
onDepositRequested={(email) => {
// `email` is the user's verified email — pass it to your backend
// so it can call Oobit's Partner API on their behalf.
router.push(`/deposit?email=${encodeURIComponent(email)}`);
}}
/>
);
}Props Reference
Shared
| Prop | Type | Required | Description |
|---|---|---|---|
accessToken | string | Yes | JWT token from your backend (Authentication Guide) |
onClose | () => void | No | Called when the user requests to close the widget. Required to show back/close buttons — if omitted, the widget's navigation buttons are hidden and users have no in-widget way to dismiss it. |
Widget-Managed Flow (WidgetSDKConfig)
WidgetSDKConfig)| Prop | Type | Required | Description |
|---|---|---|---|
userWalletAddress | string | Yes | The user's crypto wallet address — the widget uses it to build the deposit transaction |
onTransactionRequested | (transaction: ``TransactionRequest``) => void | Yes | Called when the user initiates a transaction. See Widget-Managed Deposits |
Standalone Flow (StandaloneConfig)
StandaloneConfig)| Prop | Type | Required | Description |
|---|---|---|---|
email | string | No | The user's email. If provided, the widget skips email entry. If omitted, the user enters and verifies it inside the widget's onboarding flow |
externalUserId | string | No | Your internal user ID. Alternative identifier for Partner API calls |
onDepositRequested | (email: string) => void | Yes | Called when the user taps "Add Funds". Receives the user's verified email so your backend can identify them (API-Managed Deposits) |
Styling & Customization
| Prop | Type | Required | Description |
|---|---|---|---|
style | CSSProperties | No | Style applied to the SDK's outer container <div>. Useful for setting border radius, overflow, background, etc. |
className | string | No | Class name applied to the SDK's outer container <div>. |
iframeProps | Omit<IframeHTMLAttributes, …managed> | No | Escape hatch: extra props forwarded to the underlying <iframe>. src, ref and the security-critical sandbox / allow attributes are managed by the SDK and cannot be overridden. Passing your own onLoad suppresses the SDK's built-in loading overlay so you can render your own. |
<WidgetSDK
accessToken={accessToken}
userWalletAddress={walletAddress}
onTransactionRequested={handleTransaction}
style={{ borderRadius: 12, overflow: "hidden" }}
iframeProps={{ scrolling: "no" }}
/>Custom loading indicator
Pass onLoad through iframeProps to drive your own loader. The SDK's built-in spinner is suppressed whenever this callback is present.
const [isLoading, setIsLoading] = useState(true);
<div className="relative h-full w-full">
<WidgetSDK
accessToken={accessToken}
onTransactionRequested={handleTransaction}
iframeProps={{
onLoad: () => setIsLoading(false),
}}
/>
{isLoading && (
<div className="absolute inset-0 flex items-center justify-center bg-white/95 pointer-events-none">
<div className="h-12 w-12 rounded-full border-4 border-orange-200 border-t-orange-500 animate-spin" />
</div>
)}
</div>Reset isLoading to true each time you open the widget so the loader appears again on reopen.
See Also
- Deposit Flow — Overview of both integration modes
- Widget-Managed Deposits — Handling
onTransactionRequested - API-Managed Deposits — Deep dive on the standalone flow
