PollarPollar
Guides

Deferred Flow Guide

Deferred mode gives each user an address at sign-in but creates no account on-chain. The XLM reserve is only sponsored when your backend calls POST /v3/wallets/fund, typically after a business event like KYC approval or a first deposit.

Turnkey wallets. For a co-signed or self-custody wallet (every new wallet on mainnet) the call answers 202 SERVER_WALLET_ACCOUNT_REQUESTED with a requestId: the account creation waits for the user, who approves it in their next session. Treat it as pending, not as an error. See the Server API.

This guide walks through the full implementation end-to-end.


Prerequisites

  • Funding mode set to Deferred in Dashboard -> Wallets -> Account Funding (Stellar tab)
  • A secret key from Dashboard -> Build -> API Keys
  • That's it: no additional dashboard configuration required

How it works


Step 1: Gate unfunded wallets in the frontend

After login, decide whether to show your KYC/onboarding flow or the wallet UI. In Deferred mode the wallet exists but has no XLM reserve until activated. Pass the user's wallet.address (their G… public key) to your KYC flow so your backend can activate it later.

'use client';
import { usePollar } from '@pollar/react';

export function WalletGate() {
  const { isAuthenticated, wallet } = usePollar();

  if (!isAuthenticated) return <LoginButton />;

  // Track "has this user completed your business trigger?" in your own backend.
  // Until then, show the KYC/onboarding flow.
  return <KycFlow publicKey={wallet?.address} />;
}

Step 2: Trigger activation from your backend

When the business event occurs (KYC approved, first deposit confirmed, etc.), your backend calls POST /v3/wallets/fund using the secret key and the wallet's publicKey.

// Your backend: e.g. Next.js API route, Express handler, webhook receiver
async function fundWallet(publicKey: string) {
  const response = await fetch('https://server.api.pollar.xyz/v3/wallets/fund', {
    method: 'POST',
    headers: {
      'x-pollar-api-key': process.env.POLLAR_SECRET_KEY!,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ publicKey }),
  });

  if (!response.ok) {
    const { code } = await response.json(); // { code, success: false }
    throw new Error(`Funding failed: ${code}`);
  }

  return response.json();
  // { content: { publicKey, startingBalance }, code: 'SERVER_WALLET_FUNDED', success: true }
}

Never call this endpoint from the client. It requires your secret key; exposing it client-side compromises your entire app.


Step 3: Handle the response

CodeMeaningAction
200 OKWallet funded successfullyProceed: wallet is live on-chain
400 Bad RequestMissing or malformed publicKeyCheck the request payload
402 Payment RequiredFunding wallet has insufficient XLMTop up via Dashboard -> Wallets -> Account Funding
404 Not FoundpublicKey is not a wallet owned by your appVerify the public key
409 ConflictWallet already fundedSafe to ignore; treat as success
503 Service UnavailableStellar network issuePollar retries automatically

Step 4: Notify the frontend

After activation, notify your frontend so the UI updates. Your backend owns the "is this user activated?" signal, so the simplest approach is to poll your own endpoint; you can confirm on-chain by refreshing the wallet balance (a funded wallet is live on-chain, with its reserve sponsored by the app's funding wallet plus the app's configured starting balance).

'use client';
import { usePollar } from '@pollar/react';
import { useEffect, useState } from 'react';

export function KycFlow({ publicKey }: { publicKey: string }) {
  const { refreshWalletBalance, walletBalance } = usePollar();
  const [activated, setActivated] = useState(false);

  // Poll your own backend for the activation result, then refresh on-chain state.
  useEffect(() => {
    if (activated) return;
    const interval = setInterval(async () => {
      const done = await fetch('/api/activation-status').then(r => r.json());
      if (done.activated) {
        setActivated(true);
        await refreshWalletBalance();
      }
    }, 2000);
    return () => clearInterval(interval);
  }, [activated, refreshWalletBalance]);

  if (activated && walletBalance.step === 'loaded') {
    return <p>✓ Wallet activated</p>;
  }

  return <p>Complete KYC to activate your wallet...</p>;
}

Testing on testnet

  1. Set funding mode to Deferred in the Dashboard
  2. Log in: the wallet is created unfunded (no XLM reserve)
  3. Call your fund endpoint manually (e.g. with curl or Postman)
  4. Verify the wallet is now funded (its reserve is sponsored on-chain)
  5. Verify the G-address on Stellar Expert testnet
curl -X POST https://server.api.pollar.xyz/v3/wallets/fund \
  -H "x-pollar-api-key: sec_testnet_xxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{ "publicKey": "GXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" }'

On this page

Was this helpful?