Skip to main content
The Deposit SDK (@swype-org/deposit) opens Blink’s hosted deposit flow in a cross-origin iframe. Use the default overlay for a standalone deposit action, or render Blink inline inside a payment-method aggregator with the embedded presentation. The SDK handles the signer call, iframe lifecycle, passkey/WebAuthn delegation, adaptive sizing, and completion detection via postMessage.

Embedding Blink in an aggregator

Add Blink inside your own desktop payment panel, follow its reported size, and match your brand colors.

Install

JavaScript

React hook

The hook returns reactive status, result, error, displayMessage, and isActive values, plus requestDeposit, focus, and close actions. It manages the Deposit lifecycle and cleans up on unmount.

Prebuilt deposit button

You don’t have to design your own button. The SDK ships BlinkDepositButton, a prebuilt Blink-branded button — a black pill with a “Deposit stablecoins / In a Blink” label and USDC/USDT coin marks. It is self-contained (inline styles, data-URI icons, no CSS imports) and fills the width of its container.
The button is presentation-only — wire onClick to requestDeposit yourself, and pass disabled or loading to reflect your app’s state. Its branding is intentionally fixed; if you need a custom look, keep building your own button as shown above. See the BlinkDepositButton reference for the full props table.

Configuration

Full widget vs. one tap

By default the hosted flow can open with the full widget — a deposit options entry screen that offers deposit addresses (pay from an exchange or any wallet) alongside Blink’s one-tap deposit. Set enableFullWidget: false to skip it and send every user straight to the Blink one-tap flow. The full widget only appears when both your SDK config and your Blink merchant account have it enabled. If it is disabled on your merchant account, the hosted flow stays in one-tap mode regardless of this option — contact Blink to change your account configuration.

Dark and light mode

The hosted deposit flow ships both a light and a dark palette. Pick one with the appearance.theme config:
The theme applies to the whole flow, not just the modal: it is carried through every Blink surface the flow opens, including the top-level setup tab and wallet authorization pages.

Automatic detection from your page

When you pass no theme, the SDK reads the computed color-scheme of your page’s <html> element and matches it: So if your site already declares its color scheme, the modal matches it with zero configuration:
Only declared color schemes are detectable. A page that paints dark colors — for example a .dark class that swaps CSS variables — but never sets color-scheme reads as light, and the modal renders light on your dark page. Either declare color-scheme or pass an explicit theme.
An explicit theme always wins over detection. appearance: { theme: 'light' } pins the light palette even on a page that declares itself dark.

Switching theme at runtime

The theme is read when the instance builds its hosted-flow URLs — including the warm-up iframe created at construction — so it is fixed for the life of a Deposit instance. To change it, destroy the instance and create a new one:
With the React hook, the Deposit instance is created once on first render, so changing the appearance prop has no effect. Remount the component with a key instead:
If your app simply follows the OS theme, prefer theme: 'system' over toggling between 'light' and 'dark'. The hosted flow subscribes to prefers-color-scheme itself, so it tracks the device theme with no remount and no warm-up iframe thrown away.

What theming does not cover

  • The modal’s dim backdrop behind the payment card is the same in both themes.
  • BlinkDepositButton is intentionally fixed Blink branding — a black pill — in both themes. Build your own trigger button if you need it to change with your theme.

Brand colors

appearance.variables accepts colorPrimary, colorBackground, colorText, colorDanger, and colorBorder. Use opaque #rgb or #rrggbb values. Blink derives the rest of its palette and enforces contrast for derived text colors. The variables theme Blink’s UI inside the cross-origin iframe. For an embedded aggregator integration, your CSS still owns the outer panel’s size, radius, background, border, and shadow.

Deposit titles

Set appearance.hideDepositTitle: true when your container already supplies a deposit heading. This hides the Deposit title on entry, progress, and completion screens for both Blink One Tap and manual/QR deposits. Selecting Settings still opens More with its title. Navigation controls, balances, status messages, and action labels remain visible. The default is false; omitting the property keeps the deposit titles visible.

Custom signer function

If you need full control over the HTTP call to your signer (custom headers, auth tokens, different HTTP method), pass a function instead of a URL:

Deposit request fields

The destination chainId, address, and token are not static merchant configuration. They are set dynamically per transaction, typically based on the user’s embedded wallet.
Choose destination values from Blink’s active routing catalog. See Supported Networks and Wallets for the current wallet, chain, token, and fee model details.

Minimum deposit

Pass minimumDeposit to requestDeposit, not to the constructor or appearance. The same request property works with the web SDK, mobile SDK, and their React hooks.
Blink uses the higher of your minimum and the chosen route’s minimum. For example, passing 2 cannot lower a route minimum of 5.Passing‘10‘raisesitto5. Passing `10` raises it to 10. The Deposit button stays disabled below that amount, and the manual/QR deposit terms show the same minimum. Use a finite number greater than 0 and less than 1,000,000. Values round up to whole cents: 9.991 becomes 10.00. Omit the property or pass null to use Blink’s route minimum. The web SDK logs and ignores invalid values; the mobile SDK rejects them with INVALID_REQUEST. minimumDeposit is unsigned and is not sent to your signer. Enforce any required crediting minimum on your backend as well.

Multiple destinations

If a user can be credited at more than one (chain, token, address) — say USDT on Tron, USDT on Ethereum and USDC on Polygon, each at its own wallet — pass them all:
Every deposit still settles on one of them. Blink picks the entry from the asset the user sends: a chain-and-token match settles directly with no bridge and no fee; otherwise the same asset on another chain, then the same chain, then anything else, with an Ethereum entry chosen last. Your order breaks ties, so list the destinations you would rather receive first. Tron entries are reachable through the send-to-address flow only. The completed DepositResult.transfer.destinations names the entry that was used. Your signer receives the menu as destinations and must verify ownership of every address in it — see Build Your Signer Endpoint. No two entries may share a chain and token, and destinations replaces chainId/address/token rather than accompanying them.

Deposit result

When the payment completes, the SDK returns a DepositResult:

Status flow

Error handling

See Error Codes for the full reference. Every error is a DepositError with a machine-readable code:

Lifecycle

Metadata and order reference

Pass merchant-specific data through the flow for reconciliation:
The reference and metadata are forwarded to your signer endpoint so you can correlate the payment with your internal records.

Security

The deposit UI loads live from https://pay.blink.cash. Before going live, lock the iframe origin with a Content-Security-Policy on your page and learn how to verify the build:
See Security & Content Integrity for the full model, including passkey delegation and build-manifest verification.

Mobile browser considerations

  • Mobile overlay: On phone-sized devices, the transfer uses Blink’s full-screen overlay. A requested embedded presentation also resolves to this overlay so the flow has enough room.
  • Passkey / WebAuthn: The SDK transparently handles WebAuthn ceremonies between the cross-origin iframe and the parent page. No additional configuration is needed.
  • callbackScheme: Always pass null (or omit) for browser integrations. Reserved for native app deep-link flows.
  • Viewport meta tag: Ensure your page includes a proper viewport meta tag: