Skip to main content
By the end of this guide, you’ll have a backup deposit flow that lets your users keep depositing even if meshconnect.com is unavailable.
Before you start
  • Your core Mesh deposit integration is working end-to-end (see Prepare for go-live)
  • You’re on the Web SDK 3.14.1 or later, or the React Native SDK 2.5.6 or later.
    • Please contact your Mesh representative if you need SDK backup mode support in the Mesh iOS, Android, or Flutter SDKs.
  • Your backend can return deposit addresses for your users, either up front or on demand

Overview

Mesh maintains a 99.99% uptime SLA. For the rare case of a full outage, SDK backup mode gives your users a self-contained, deposit-only path that doesn’t depend on Mesh being up. Normally, a session starts when your server calls POST /api/v1/linktoken and passes the Link token to the SDK. If that call fails because Mesh is down, the session can’t start. In backup mode, you skip the Link token entirely: you pass a backup configuration straight to the SDK, which opens a static deposit widget hosted on separate Mesh infrastructure (backup.meshconnect.com, served by a different provider from the core Mesh API). The user picks a token and network and sees a QR code and copyable deposit address. The deposit steps mirror a normal session (select token, select network, deposit address), without the option to connect accounts. You control the trigger. Mesh isn’t in the path during an outage, so your systems detect the failure and supply the deposit addresses. Backup mode assumes your own infrastructure is healthy and only Mesh is down.

How it works

Backup mode gives you two levels of redundancy from a single integration. You don’t build or trigger them separately: you open the SDK in backup mode, and it uses whichever level is reachable. The SDK tries Level 1 first. If the backup widget doesn’t load within a few seconds, it switches to Level 2 once for that session and emits a backupTierChanged event through onEvent, which you can log to monitor how often Level 2 is used.

Level 1: Alternate domain

The backup widget, the supported-pairs catalog, and logos load from backup.meshconnect.com, which runs on separate Mesh infrastructure with a different hosting provider from the core Mesh API, so it stays available when the core Mesh API is down. It shares DNS with meshconnect.com, so a DNS-level outage falls through to Level 2.

Level 2: No Mesh domain

If the alternate domain is also unreachable, the SDK falls back to a deposit experience bundled inside the SDK itself. It makes no network calls to any Mesh-owned domain. Users can still pick a token and network and get a deposit address, either from your backup configuration or from your own backend through the JIT callbacks.
Level 2 limitations (by design)
  • The supported-pairs catalog is a snapshot taken at each SDK release, so it may not include pairs Mesh added after your installed version. Keep your SDK reasonably current.
  • To keep the SDK small, Level 2 includes icons for the most common tokens and networks only. Other pairs show a name or initials placeholder. Level 1 has full logos.
  • The bundled catalog covers Mesh-supported pairs only, not pairs specific to your account.

What you need to build

  1. Outage detection: decide when a failed Link token call means you should switch to backup mode.
  2. Backup configuration: build a MeshBackupConfig on your server and pass it to the SDK’s backup entry point.
  3. JIT callbacks (optional): implement onAddressInit and onStatusPoll so the widget can fetch addresses from your backend on demand. Skip this if every destination in your backup configuration already includes an address.
Mesh provides the backup widget, the supported-pairs and logos catalog, and the SDK backup entry point.

1. Detect a Mesh outage

Treat your POST /api/v1/linktoken call as a Mesh outage only when it fails with:
  • A network, DNS, or connection error (no HTTP response)
  • A timeout: set a 3–5 second ceiling on this call
  • An HTTP 5xx response
  • An HTTP 429 response
Retry once after 250–500ms before switching to backup mode, so a brief blip doesn’t trigger it.
Don’t enter backup mode on any 4xx other than 429. A 400, 401, 403, or 404 means there’s a problem with your request or credentials. Surface it as a normal error; switching to backup mode would hide a real integration bug.
Notes:
  • In backup mode there’s no Link token and no other Mesh API call. Don’t retry the request against another domain; build the backup configuration from data you already have.
  • Your app then opens the SDK with either the Link token or the backup configuration (see step 3).

2. Build the backup configuration

Build MeshBackupConfig on your server, not in client code, so destinations can’t be tampered with. Include every token/network pair you accept for this user.
clientId required
Your Mesh Client ID.
userId required
Your end-user identifier. Used for analytics only, not authentication.
destinations required
The token/network destinations you support for this user. Each must be a pair in the Mesh supported-pairs catalog.
destinations.networkId required
Mesh’s identifier for the network. Use the Get networks endpoint (/api/v1/transfers/managed/networks) to look these up ahead of time; the values don’t change, so you can cache them.
destinations.symbol required
The token symbol (eg. USDC).
destinations.address optional required unless resolved by JIT callbacks
The deposit address. Omit it only for destinations you resolve through onAddressInit and onStatusPoll.
destinations.addressTag optional required for memo-chain networks
The destination tag or memo for memo-chain networks: XRP, XLM, TON, and Injective.
preselectedSymbol optional
Skips the token selection screen. Must match one of your destination symbols; otherwise the widget shows token selection as usual.
Notes:
  • The networks above are Bitcoin, Ethereum, Solana, XRP Ledger, and Base. Replace every xxx with your user’s real deposit address and tag.
  • The Base entry has no address, so the widget resolves it through your JIT callbacks (step 4).

3. Open the SDK in backup mode

When you detect an outage, pass MeshBackupConfig to the SDK’s backup entry point instead of a Link token. Your existing callback functions (onEvent, onExit, and others) don’t change. Optional settings: on Web, openLinkBackup(backupConfig, { customIframeId }) renders into your own iframe, the same as openLink. On React Native, hideCloseButton hides the built-in close button, and settings accepts theme and language.
The object returned by createLink() exposes openLinkBackup() alongside the normal openLink().
The Web SDK renders the backup widget in an iframe on your page, so your page’s Content Security Policy (CSP) decides whether it can load. If you restrict frame-src, child-src, or default-src, check the following. A permissive default CSP needs no changes.
A misconfigured CSP blocks backup mode exactly when you need it. The widget fails closed and shows a blank frame and an error.
  • Serve the page over HTTPS. The backup widget is sent with Content-Security-Policy: frame-ancestors https:, so it only loads inside an HTTPS page. This mostly affects local development over HTTP.
  • Allow backup.meshconnect.com in frame-src / child-src (Level 1). It’s a different domain from the primary Mesh widget. If you only allow web.meshconnect.com, Level 1 can’t load.
  • Allow blob: in frame-src / child-src (Level 2). The bundled fallback renders as a sandboxed blob: iframe. Without it, Level 2 is blocked silently.
Your JIT callbacks run in your own app under your existing connect-src rules, so they need no widget-specific changes.
React Native needs none of this. The React Native SDK loads the widget as the top-level document in a native WebView, so there’s no host-page CSP to configure.
Render <LinkConnect> with a backupConfig prop in place of linkToken.

4. Implement the JIT callbacks (optional)

If any destination in your backup configuration omits address, the widget resolves it by calling two callbacks you pass to the SDK. They run in your app and call your own backend with your existing auth session, so your credentials never enter the widget. How the widget uses them:
  1. When the user confirms a token and network, the widget calls onAddressInit(symbol, networkId) once to start address generation.
  2. It then calls onStatusPoll(symbol, networkId) every 2–3 seconds, for up to about 3 minutes, until the address is ready or failed.
  3. When the address is ready, the widget validates it and shows the QR / copy-address screen. If it is failed or the deadline passes, the user sees an error.

onAddressInit(symbol, networkId)

Starts address generation. The widget moves straight to polling, so the return value is ignored. A thrown error or rejected promise counts as a generation failure.

onStatusPoll(symbol, networkId)

Returns a promise that resolves to the current status of the address.
status required
pending, ready, or failed. On pending, the widget polls again.
address optional required when ready
A valid deposit address for the requested network.
addressTag optional required for memo-chain networks when ready
The destination tag or memo for networks like XRP, XLM, TON, and Injective. Omit it otherwise.
Always return the same address for the same token and network. For a given symbol and networkId, store the first address (and tag) you resolve and return it every time after. A poll must never produce a new address; if it does, the user may send funds to an address that doesn’t match the one shown.
Include addressTag for memo-chain networks. A ready response without a tag on a network that requires one is rejected, and the user sees an error.
Other rules:
  • The widget fails closed. It shows a QR code only if the ready result matches the requested symbol and networkId and passes address format validation for that network. Otherwise it shows an error, never a wrong or blank QR code.
  • Errors end the attempt. A thrown error, a rejected promise, or status: 'failed' ends the attempt and shows an error.
  • Throw on non-OK responses. If your callbacks use fetch, check res.ok and throw when it’s false. fetch resolves on 4xx and 5xx, so without the check a backend error looks like pending until the 3-minute deadline.
Already built Just-in-Time address fetching? Your backend can likely serve both flows. In backup mode, your app calls your backend through these SDK callbacks instead of Mesh calling your JIT endpoints. See Just-in-time address fetching.

The deposit experience

Backup mode is strictly a deposit flow. There’s no account connection, verification, transfer execution, or reading of portfolio data.
  1. Select token: shown only if preselectedSymbol isn’t set. The list comes from your destinations.
  2. Select network: the networks available for the chosen token.
  3. Deposit: the address appears as a QR code and copyable text, with the tag or memo where applicable.

Supported pairs and logos

In Level 1, the widget loads supported token/network pairs and logos from a static catalog that Mesh publishes hourly on the independent domain. It includes all Mesh-supported pairs plus any pairs specific to your account. You don’t need to host anything. Every networkId and symbol in your destinations must be a pair in this catalog. In Level 2, the widget uses the snapshot bundled with your SDK version instead (see Level 2 limitations above).

Security considerations

Mesh’s independent check on the deposit address isn’t available during an outage. In backup mode, the address shown comes only from your backup configuration or your callbacks, so it’s only as trustworthy as your own systems. Build MeshBackupConfig on your server and resolve addresses through an authenticated path in your callbacks.
  • Your credentials never enter the widget. The callbacks run in your app with your existing session; the widget only exchanges symbol, networkId, and the resolved address with them.
  • There’s no Mesh-issued token to scope or expose in backup mode.

Test your implementation

Each SDK has an example app with a backup mode demo you can run locally: The example apps let you open backup mode without a Link token, force the Level 2 fallback, and force JIT resolution against a local mock backend. To force Level 2 in your own app, pass an unreachable origin as widgetOrigin (Web: openLinkBackup(backupConfig, { widgetOrigin }); React Native: the widgetOrigin prop). After about 5 seconds the SDK falls back to Level 2 and emits backupTierChanged. Use this for testing only; leave widgetOrigin unset in production.
Web SDK local testing: Level 1 only loads on an HTTPS page, so run your local app over HTTPS to test it. Level 2 works over plain HTTP.
What to test:
  • Outage trigger: Force your Link token call to time out or return a 5xx, and confirm your app opens the SDK in backup mode after one retry.
  • No false trigger: Return a 401 or 400, and confirm your app shows a normal error instead of backup mode.
  • Static addresses: Select a destination that includes an address, and confirm the QR code and copyable address match your configuration, including any tag.
  • JIT addresses: Select a destination without an address, and confirm onAddressInit is called once, onStatusPoll repeats until ready, and the same address comes back every time.
  • Memo chains: Select XRP or XLM and confirm the tag appears on the deposit screen.
  • Level 2 fallback: Force Level 2 with an unreachable widgetOrigin, and confirm the deposit flow still completes and backupTierChanged fires.
  • CSP (Web SDK): If you restrict frame-src or child-src, confirm both backup.meshconnect.com and blob: are allowed and the page is served over HTTPS.

What’s next

Next up: Just-in-time address fetching, offer every token and network you support without pre-generating every address, in both normal and backup mode.
AI coding reference: a compact summary of this page’s APIs, parameters, and patterns for use by AI coding assistants (following the llms.txt standard). Human readers can safely ignore this.llms.txt — SDK backup modeDeposit-only fallback for when meshconnect.com is unavailable. No Link token and no Mesh API calls: the client passes a MeshBackupConfig to the SDK’s backup entry point; the SDK loads a static deposit widget from separate Mesh infrastructure at backup.meshconnect.com (Level 1), or a deposit experience bundled in the SDK if that’s unreachable too (Level 2). User picks token and network, then sees a QR / copy-address screen. Supported SDKs: Web (@meshconnect/web-link-sdk 3.14.1+) and React Native (@meshconnect/react-native-link-sdk 2.5.6+). iOS, Android, and Flutter: on request via the Mesh representative.Levels: the SDK tries Level 1 first; if the backup widget doesn’t load within a few seconds (about 5s), it switches to Level 2 once for that session and emits backupTierChanged through onEvent (log it to monitor Level 2 usage). Level 1 (backup.meshconnect.com) runs on a different hosting provider from the core Mesh API but shares DNS with meshconnect.com, so a DNS-level outage falls through to Level 2. Level 2 makes no calls to any Mesh-owned domain.Trigger (your logic around POST /api/v1/linktoken, usually server-side): enter backup mode only on network/DNS/connection error, timeout (3–5s ceiling), HTTP 5xx, or HTTP 429, after one retry at 250–500ms. Never on other 4xx (400, 401, 403, 404): surface as a normal error.MeshBackupConfig (build server-side): clientId (required) | userId (required, analytics only) | destinations[] (required) with networkId (required), symbol (required), address (required unless resolved by JIT callbacks), addressTag (required for memo chains) | preselectedSymbol (optional; skips token select; must match a destination symbol).Web entry point: createLink({ onEvent, onExit, onIntegrationConnected, onTransferFinished, onAddressInit, onStatusPoll }) then link.openLinkBackup(backupConfig) instead of link.openLink(linkToken). Optional second argument { customIframeId } renders into your own iframe, as with openLink.React Native entry point: <LinkConnect backupConfig={backupConfig} onAddressInit onStatusPoll ... /> instead of linkToken. Optional: hideCloseButton, and settings with theme and language. Existing callbacks (onEvent, onExit, etc.) are unchanged on both SDKs.JIT callbacks (only if a destination omits address): onAddressInit(symbol, networkId) called once; return value ignored; throw/reject = failure. onStatusPoll(symbol, networkId) polled every 2–3s for up to about 3 min; must resolve to { status: 'pending' | 'ready' | 'failed', address?, addressTag? }. address required on ready; addressTag required on ready for memo chains (XRP, XLM, TON, Injective). Callbacks run in the client app and call the client’s own backend. If using fetch, check res.ok and throw when false; otherwise a backend 4xx/5xx looks like pending until the 3-minute deadline.Rules: idempotent per symbol + networkId (persist first address; polls never mint a new one) | widget fails closed on mismatched symbol/networkId or invalid address format | ready without required tag is rejected.Web CSP: serve page over HTTPS (widget sends frame-ancestors https:) | allow backup.meshconnect.com (Level 1) and blob: (Level 2) in frame-src/child-src if restricted. React Native: no CSP changes.Catalog: Level 1 uses an hourly-published supported-pairs and logos catalog on the backup domain; destinations must be pairs in it. Level 2 uses a snapshot bundled per SDK release, with icons for common pairs only, covering Mesh-supported pairs only (not account-specific pairs). Keep the SDK current.Security: Mesh’s address anti-tampering check isn’t in the path during an outage; addresses are only as trustworthy as the client’s systems. Client credentials never enter the widget.Testing: example apps with a backup mode demo: Web mesh-web-sdk/examples/react-example, React Native mesh-react-native-sdk/examples/react-native-example (open backup mode without a Link token, force Level 2, force JIT against a local mock backend). To force Level 2 in your own app, pass an unreachable widgetOrigin (Web: openLinkBackup(backupConfig, { widgetOrigin }); React Native: widgetOrigin prop); after about 5s the SDK falls back and emits backupTierChanged. Testing only; leave widgetOrigin unset in production. Web: Level 1 loads only on HTTPS pages, so run local apps over HTTPS; Level 2 works over HTTP.For the full consolidated reference across all guides, see docs.meshconnect.com/llms-full.txt