How to Use the Privy API: Embedded Wallets and Social Auth for Web3

Learn to use the Privy API for embedded wallets, social login, and server auth. React + Node code examples, webhooks, policy engine, and MFA setup.

Ashley Innocent

Ashley Innocent

23 April 2026

How to Use the Privy API: Embedded Wallets and Social Auth for Web3

Apidog for Enterprise

On-Premises Deploy

SSO & RBAC

SOC 2 Compliant

Explore Apidog Enterprise

Onboarding users to a Web3 app still pushes most people away at the first step. Seed phrases, browser extensions, and gas fees turn a two-tap signup into a ten-minute struggle. The Privy API fixes that gap by handing every new user an embedded wallet behind a familiar login: email, SMS, Google, Apple, or an existing wallet like MetaMask. You get a crypto-native user without asking anyone to install a browser extension.

Privy now backs wallets for Blackbird, Friend.tech, OpenSea, and thousands of other apps, and the product spans Ethereum, Solana, and any EVM chain. This guide walks through the full developer workflow: creating a Privy app, wiring the React SDK, verifying tokens on the server, signing transactions with embedded wallets, and shipping webhooks. If you also want to compare options like MetaMask’s developer toolkit, keep this page open and jump back and forth.

💡
Before you read the code, one tool note. Apidog is how you should inspect every HTTPS request Privy’s SDKs make under the hood. Point your app at a local proxy, capture the actual payload, and debug auth failures in seconds instead of tailing logs.
button

TL;DR

What is the Privy API?

Privy is an authentication and wallet infrastructure platform. It gives your app three things: a login UI, an embedded wallet provisioned per user, and a set of REST endpoints for server-side checks. The embedded wallet lives in a secure enclave, so Privy never sees the private key and neither does your backend. Users can export their key later if they want to move to a self-custody wallet; that optionality is a big part of the pitch.

The platform charges per monthly active wallet, which means you can ship a prototype for free and scale pricing as traction grows. The free tier covers 1,000 monthly active users, Pro starts at $149 per month, and Enterprise handles custom SLAs.

Authentication and setup

Start at privy.io and create a new app from the dashboard. You get two values you care about:

Set allowed login methods (email, SMS, Google, Apple, Farcaster, wallet), pick your default chain, and drop your domain into the allowed origins list. For React, install the SDK:

npm install @privy-io/react-auth

Wrap your app in PrivyProvider:

import { PrivyProvider } from '@privy-io/react-auth';

export default function App({ Component, pageProps }) {
  return (
    <PrivyProvider
      appId={process.env.NEXT_PUBLIC_PRIVY_APP_ID}
      config={{
        loginMethods: ['email', 'wallet', 'google'],
        embeddedWallets: { createOnLogin: 'users-without-wallets' },
        defaultChain: { id: 8453 }, // Base
        supportedChains: [{ id: 1 }, { id: 8453 }, { id: 137 }],
      }}
    >
      <Component {...pageProps} />
    </PrivyProvider>
  );
}

The createOnLogin flag provisions an embedded wallet the first time a user logs in without one. You control the supported chains; Solana lives under a separate solanaClusters config.

Core endpoints and SDK calls

Privy’s React SDK handles most flows so you rarely hit raw REST. Still, the server SDK and webhook payloads use the same token format, so knowing the underlying API helps when things go sideways.

Triggering login and reading the user

import { usePrivy, useWallets } from '@privy-io/react-auth';

function LoginButton() {
  const { ready, authenticated, login, logout, user } = usePrivy();
  const { wallets } = useWallets();

  if (!ready) return <p>Loading...</p>;
  if (!authenticated) return <button onClick={login}>Sign in</button>;

  const embedded = wallets.find((w) => w.walletClientType === 'privy');

  return (
    <div>
      <p>Hi {user.email?.address ?? user.id}</p>
      <p>Wallet: {embedded?.address}</p>
      <button onClick={logout}>Log out</button>
    </div>
  );
}

useWallets returns every wallet the user has linked, and the walletClientType field tells you which one Privy created. This is the pattern you follow for Privy embedded wallets.

Signing a transaction

const { wallets } = useWallets();
const wallet = wallets.find((w) => w.walletClientType === 'privy');

async function sendTx() {
  const provider = await wallet.getEthereumProvider();
  const hash = await provider.request({
    method: 'eth_sendTransaction',
    params: [{
      to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2',
      value: '0x38d7ea4c68000', // 0.001 ETH
    }],
  });
  console.log('tx hash', hash);
}

For Solana, swap getEthereumProvider for getSolanaProvider and pass a serialized transaction. If you want to mirror data access patterns from providers like Alchemy, Privy plays nicely alongside them; Privy handles the key, Alchemy handles the RPC.

Verifying tokens on the server

Install the server SDK:

npm install @privy-io/server-auth

Every authenticated request from your frontend carries a Privy access token (JWT). Verify it on the server before you trust any user ID:

import { PrivyClient } from '@privy-io/server-auth';

const privy = new PrivyClient(
  process.env.PRIVY_APP_ID,
  process.env.PRIVY_APP_SECRET
);

export async function GET(req) {
  const auth = req.headers.get('authorization')?.replace('Bearer ', '');
  try {
    const claims = await privy.verifyAuthToken(auth);
    // claims.userId is the Privy user DID
    return Response.json({ userId: claims.userId });
  } catch (err) {
    return new Response('Unauthorized', { status: 401 });
  }
}

You can also fetch the full user object (privy.getUser(userId)) to check linked accounts, wallet addresses, and custom metadata.

Exporting an embedded wallet

Privy lets users export their private key any time. The UX is a single hook:

import { useExportWallet } from '@privy-io/react-auth';

const { exportWallet } = useExportWallet();
<button onClick={() => exportWallet()}>Export private key</button>;

Privy shows a secure iframe modal; your app never touches the key material.

Authorization signatures and the policy engine

For sensitive operations (large transfers, new device logins), Privy supports authorization signatures. You define a policy in the dashboard, attach it to your app, and Privy enforces MFA, allowlists, or server-signed approvals before a transaction goes through. Details live in the Privy authorization key guide. Combined with MFA options (TOTP, SMS, passkey), this closes most of the account takeover surface that plain wallets leave open.

Webhooks

Privy posts JSON events to your endpoint on user and wallet lifecycle changes:

curl -X POST https://yourapp.com/webhooks/privy \
  -H "Content-Type: application/json" \
  -H "svix-id: msg_..." \
  -H "svix-signature: v1,..." \
  -d '{
    "type": "user.created",
    "user": { "id": "did:privy:...", "email": { "address": "a@b.com" } }
  }'

Verify the svix-signature header with the webhook secret from the dashboard before you write anything to your database.

Common errors and rate limits

A handful of errors show up over and over:

Use Apidog to replay a failing webhook locally. Paste the raw payload into a request, edit the signature header, and hit your dev server repeatedly until the handler passes.

Privy pricing

Check privy.io/pricing for current numbers; the tiers shift as the product grows.

Testing the Privy API with Apidog

Privy’s client SDK hides the HTTPS calls, but every token verification, user lookup, and webhook your backend handles is a regular REST request. That is where Apidog earns its keep. Create a Privy collection in Apidog, drop in your app ID and secret as environment variables, and hit endpoints like GET /api/v1/users/{userId} or POST /api/v1/users/{userId}/wallets without leaving the tool.

You can also record webhook payloads from the dashboard, save them as Apidog requests, and replay them against a local tunnel. Set up automated tests that verify a valid JWT returns a user object and an expired one returns 401; run them on every deploy. Download Apidog free and skip the cURL gymnastics. If you already moved off Postman, the side-by-side workflow guide covers the full migration.

button

FAQ

How is Privy different from Web3Auth or Magic?All three offer embedded wallets, but Privy leans harder on mixed auth (email + wallet + social) and a policy engine that larger apps need. Web3Auth focuses on MPC key splitting; Magic ships a broader magic-link product. Pick Privy when you want both a clean onboarding UI and fine-grained control over what wallets can do.

Does Privy support Solana?Yes. Embedded wallets work on Solana mainnet and devnet, and the React SDK exposes getSolanaProvider() for signing and sending transactions. You can configure both EVM and Solana in the same app.

Can users bring their own wallet?Yes. MetaMask, Coinbase Wallet, WalletConnect, Phantom, and dozens of others work out of the box. Privy treats external wallets as linked accounts, so the same user DID owns both the embedded and external keys.

What happens if Privy goes down?Users keep access to exported wallets, since the key lives in the user’s browser enclave. For production apps, turn on wallet exportability and document a fallback path. See the guide to comparing identity providers for more on vendor risk patterns.

Does Privy support MFA?Yes. TOTP, SMS, and passkeys are all built in, and you can require MFA for specific actions (sending tokens, exporting wallets) via the policy engine.

Is my app’s code running server-side or client-side?Both. Client SDK handles login UI and signing; server SDK verifies tokens and fetches user data. Never ship your app secret to the browser.

Explore more

How to Build Claude Workflows That Run Without You

How to Build Claude Workflows That Run Without You

Build Claude workflows that run without you. Learn headless execution, the verification gate, guardrails, scheduling, and handoffs that make unattended agents safe.

8 June 2026

Stop Prompting Your Coding Agent. Build the Loop That Prompts It Instead

Stop Prompting Your Coding Agent. Build the Loop That Prompts It Instead

Stop prompting your coding agent one shot at a time. Learn how to design self-correcting agent loops, why the verification gate matters most, and how API tests close the loop.

8 June 2026

How to Secure API Collaboration with Role-Based Access Control (RBAC)

How to Secure API Collaboration with Role-Based Access Control (RBAC)

A practical guide for protecting shared API workspaces, endpoints, credentials, docs, mocks, tests, and production environments during API collaboration.

5 June 2026

Practice API Design-first in Apidog

Discover an easier way to build and use APIs

How to Use the Privy API: Embedded Wallets and Social Auth for Web3