Privy Skill
Product summary
Privy is a wallet infrastructure and authentication platform that enables developers to embed wallets and user authentication into applications. It provides client-side SDKs (React, React Native, Swift, Android, Flutter, Unity) for user-facing features and server-side SDKs (Node.js, Go, Java, Rust, Ruby) for backend wallet management. Key entry points: REST API at https://api.privy.io/v1/, PrivyProvider component for React apps, PrivyClient for backend operations. Configuration happens in the Privy Dashboard at https://dashboard.privy.io/. The primary documentation is at https://docs.privy.io.
When to use
Use Privy when:
- Building user authentication flows with email, SMS, social logins, passkeys, or wallet-based auth
- Creating embedded wallets for users (self-custodial, non-custodial, or custodial models)
- Sending transactions on Ethereum, Solana, Tempo, Bitcoin, Tron, Sui, or other blockchains
- Implementing wallet access controls with owners, signers, and policies
- Managing multi-party approval workflows or quorum-based signing
- Tracking wallet balances, transactions, and asset movements
- Setting up gas sponsorship, onramps/offramps, or yield earning
- Building trading apps, treasury management, agent wallets, or fintech applications
- Integrating with external wallets (MetaMask, Phantom, Rainbow, etc.)
Quick reference
Core concepts
| Concept | Purpose | Example |
|---|---|---|
| User | Unified identity across auth methods and wallets | Email + MetaMask linked to same user |
| Embedded wallet | Privy-managed wallet secured by key splitting | User wallet created on login |
| Owner | Entity with full control over a wallet | User, authorization key, or key quorum |
| Signer | Party with scoped permissions to sign transactions | Server automation, delegated access |
| Policy | Rules constraining wallet actions (amounts, recipients, contracts) | Max $1000 per transfer, approved recipients only |
| Intent | Proposed action awaiting approval (manual or quorum) | Transfer request pending team approval |
SDK setup
React/Next.js:
import {PrivyProvider} from '@privy-io/react-auth';
<PrivyProvider appId="your-app-id" clientId="your-client-id" config={{...}}>
{children}
</PrivyProvider>
Node.js:
import {PrivyClient} from '@privy-io/node';
const privy = new PrivyClient({appId: 'your-app-id', appSecret: 'your-app-secret'});
REST API:
curl -X POST https://api.privy.io/v1/wallets \
-H "Authorization: Basic <base64(appId:appSecret)>" \
-H "privy-app-id: your-app-id"
Key files and configuration
| Item | Location | Purpose |
|---|---|---|
| App ID & Secret | Privy Dashboard > Apps | API authentication credentials |
| Webhook signing secret | Dashboard > Configuration > Webhooks | Verify webhook payloads |
| App clients | Dashboard > Apps > App Clients | Environment-specific configuration |
| Login methods | Dashboard > Configuration > Login Methods | Enable email, SMS, OAuth, wallets, etc. |
| Policies | Dashboard or API | Define wallet action constraints |
Common API endpoints
| Endpoint | Method | Purpose |
|---|---|---|
/v1/wallets |
POST | Create wallet |
/v1/wallets/{id} |
GET | Fetch wallet details |
/v1/wallets/{id}/ethereum/eth_sendTransaction |
POST | Send EVM transaction |
/v1/wallets/{id}/solana/signAndSendTransaction |
POST | Send Solana transaction |
/v1/users |
POST | Create user |
/v1/users/{id} |
GET | Fetch user |
/v1/policies |
POST | Create policy |
/v1/intents |
GET/POST | Fetch or create intents |
Decision guidance
When to use embedded vs. external wallets
| Scenario | Embedded | External |
|---|---|---|
| New users without wallets | ✓ | ✗ |
| Users bringing existing wallets | ✗ | ✓ |
| Full control over UX | ✓ | ✗ |
| User controls keys directly | ✗ | ✓ |
| Seamless onboarding | ✓ | ✗ |
| Leverage existing balances | ✗ | ✓ |
When to use Privy auth vs. JWT-based auth
| Scenario | Privy Auth | JWT-based |
|---|---|---|
| No existing auth system | ✓ | ✗ |
| Multiple login methods needed | ✓ | ✓ |
| Existing auth provider (Auth0, Firebase) | ✗ | ✓ |
| Want Privy to manage sessions | ✓ | ✗ |
| Custom auth system | ✗ | ✓ |
When to use client-side vs. server-side wallets
| Scenario | Client-side | Server-side |
|---|---|---|
| User-controlled wallets | ✓ | ✗ |
| Application-owned wallets | ✗ | ✓ |
| Automated trading/agents | ✗ | ✓ |
| Consumer app | ✓ | ✗ |
| Treasury/business wallets | ✗ | ✓ |
| User signs transactions | ✓ | ✗ |
Workflow
1. Set up your Privy app
- Create account at https://dashboard.privy.io/
- Create a new app in the Dashboard
- Copy your App ID and App Secret
- Configure login methods (email, SMS, OAuth, wallets, etc.)
- Set up app clients for different environments if needed
2. Initialize Privy in your application
- For React: Wrap your app with
PrivyProviderat the root - For backend: Instantiate
PrivyClientwith appId and appSecret - For REST: Store credentials securely (environment variables)
- Wait for
readystate before consuming Privy hooks/state
3. Authenticate users
- Use
useLoginWithEmail(),useLoginWithWallet(), or other login hooks (React) - Or call
/v1/usersto create users server-side - Link multiple auth methods to same user if needed
- Retrieve user object with linked accounts and wallets
4. Create or fetch wallets
- Client-side: Configure
embeddedWallets.createOnLoginin PrivyProvider config - Server-side: Call
privy.wallets().create({chain_type: 'ethereum'})or POST to/v1/wallets - Specify owner (user ID, authorization key, or key quorum)
- Optionally set initial policies
5. Configure controls and policies
- Define owners and signers for the wallet
- Create policies with rules and conditions to constrain actions
- Use Dashboard or API to set up policies
- Test policy evaluation before production
6. Execute transactions
- Client-side: Use
useSendTransaction()hook or sign methods - Server-side: Call
privy.wallets().ethereum().sendTransaction()or equivalent - Provide transaction details (to, value, chain_id, etc.)
- Handle policy evaluation and approval flows
7. Monitor and react to events
- Set up webhooks in Dashboard > Configuration > Webhooks
- Verify webhook signatures using SDK or manual verification
- Subscribe to user, wallet, transaction, and intent events
- Update your backend state based on webhook payloads
Common gotchas
- Policy defaults to DENY: If a wallet has a policy, you must explicitly allow every RPC method or wallet action it will use. Missing rules are denied by default.
- Wallet ID vs. address: Use wallet
id(UUID) for API calls, not the wallet address. Address is for on-chain identification only. - Chain ID format: Use CAIP-2 format for chain IDs (e.g.,
eip155:1for Ethereum mainnet,solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpfor Solana). - Numeric values in wei/lamports: Policy conditions and transaction values are evaluated exactly as passed—no automatic conversion. ETH is in wei, SOL in lamports, USDC in microdollars.
- Webhook verification required: Always verify webhook signatures before trusting the payload. Use
privy.webhooks().verify()or manual verification. - Rate limits (HTTP 429): Implement exponential backoff retry logic. Privy rate limits REST endpoints for fair usage.
- Ready state not checked: Don't use Privy hooks before
ready === truein React. State may be stale or undefined. - Missing app client ID: If deploying across multiple domains, configure app clients in the Dashboard and pass
clientIdto PrivyProvider. - Policy evaluation in TEE: Policies are evaluated in secure enclaves—you cannot inspect or modify policy logic at runtime.
- Idempotency keys: Use idempotency keys for critical operations (wallet creation, transactions) to prevent duplicate processing on retries.
Verification checklist
Before submitting work with Privy:
- App ID and App Secret are stored securely (environment variables, not hardcoded)
- PrivyProvider wraps the entire app (React) or PrivyClient is instantiated once (backend)
-
readystate is checked before consuming Privy hooks (React) - All required login methods are enabled in Dashboard
- Wallets are created with correct owner (user ID, key, or quorum)
- Policies are defined and tested if wallet has restrictions
- Transaction payloads use correct chain ID format (CAIP-2)
- Numeric values (amounts, gas) are in correct units (wei, lamports, etc.)
- Webhook endpoint is registered and signature verification is implemented
- Error handling catches
APIErrorandPrivyAPIError(backend) - Idempotency keys are used for critical operations
- Rate limit retry logic is implemented
- All sensitive data (secrets, keys) is never logged or exposed to client
Resources
- Comprehensive page index: https://docs.privy.io/llms.txt
- Key concepts guide: https://docs.privy.io/basics/key-concepts
- REST API reference: https://docs.privy.io/api-reference/introduction
- Policies and controls: https://docs.privy.io/controls/policies/overview
- Webhooks setup: https://docs.privy.io/api-reference/webhooks/overview
For additional documentation and navigation, see: https://docs.privy.io/llms.txt