| name | Privy |
| description | Use when building authentication systems, creating embedded wallets, managing wallet controls and policies, signing transactions, or integrating wallet infrastructure into applications. Agents should reach for this skill when implementing user onboarding, wallet creation, transaction signing, policy enforcement, or wallet management across Ethereum, Solana, and other blockchains. |
| metadata | {"mintlify-proj":"privy","version":"1.0"} |
Privy Skill Reference
Product summary
Privy is a wallet and authentication infrastructure platform that enables developers to embed self-custodial wallets and user authentication directly into applications. It provides SDKs for React, React Native, Node.js, Swift, Android, Flutter, Unity, Java, Go, Rust, and Ruby, plus a REST API for server-side operations.
Key files and configuration:
- Dashboard: https://dashboard.privy.io (create apps, configure login methods, set up webhooks)
- App ID and App Secret: Retrieved from Dashboard > Configuration > App settings > Basics
- Environment variables:
PRIVY_APP_ID, PRIVY_APP_SECRET, PRIVY_WEBHOOK_SIGNING_SECRET
- Client-side:
PrivyProvider wraps React apps; usePrivy() and wallet hooks access functionality
- Server-side:
PrivyClient initialized with app ID and secret for Node.js, Go, Java, Rust, Ruby
Primary documentation: https://docs.privy.io
When to use
Reach for this skill when:
- Building user authentication flows (email, SMS, social, wallet, passkey, OAuth)
- Creating or managing embedded wallets for users or servers
- Implementing wallet controls, policies, and authorization keys
- Signing transactions on Ethereum, Solana, Tempo, Bitcoin, or other chains
- Setting up wallet actions (transfers, swaps, earn/yield)
- Configuring multi-factor authentication or security features
- Managing user accounts and linking multiple authentication methods
- Handling wallet lifecycle events via webhooks
- Building trading apps, treasury management, or agent wallets
- Integrating external wallets (MetaMask, Phantom, etc.)
Quick reference
SDK initialization
| Platform | Code |
|---|
| React | <PrivyProvider appId="..." clientId="..." config={{...}}> |
| React Native | <PrivyProvider appId="..." clientId="..." config={{...}}> |
| Node.js | new PrivyClient({appId: '...', appSecret: '...'}) |
| Go | privy.NewPrivyClient(privy.PrivyClientOptions{AppID: '...', AppSecret: '...'}) |
| Java | PrivyClient client = new PrivyClient(appId, appSecret) |
| REST API | Basic Auth: Authorization: Basic <base64(appId:appSecret)> + header privy-app-id: <appId> |
Common wallet operations
| Task | Method/Hook |
|---|
| Create wallet | useCreateWallet() (React) or privy.wallets().create() (Node.js) |
| Get wallet | useWallets() (React) or privy.wallets().get() (Node.js) |
| Sign transaction | wallet.sendTransaction() (Ethereum) or wallet.signTransaction() (Solana) |
| Send transaction | eth_sendTransaction (Ethereum) or signAndSendTransaction (Solana) |
| Get balance | privy.wallets().getBalance() (Node.js) |
| Export keys | wallet.exportPrivateKey() or wallet.exportSeedPhrase() |
Policy and control configuration
| Element | Purpose |
|---|
| Owner | Entity with full control (user ID, authorization key, or key quorum) |
| Signer | Additional party with scoped permissions; cannot modify policies |
| Policy | Rules constraining what actions are allowed (transfers, swaps, contract calls) |
| Rule | Specific action rule with conditions and ALLOW/DENY action |
| Condition | Boolean expression evaluated against request (e.g., recipient address, amount) |
Webhook event types
| Category | Events |
|---|
| User | user.created, user.authenticated, user.linked_account, user.wallet_created, mfa.enabled |
| Wallet | wallet.funds_deposited, wallet.funds_withdrawn, wallet.private_key_export, wallet.recovered |
| Transaction | transaction.confirmed, transaction.failed, transaction.broadcasted, transaction.execution_reverted |
| Wallet actions | wallet_action.swap.*, wallet_action.transfer.*, wallet_action.earn_deposit.* |
| Intent | intent.created, intent.authorized, intent.executed, intent.rejected |
Decision guidance
When to use embedded wallets vs. external wallets
| Scenario | Use embedded wallets | Use external wallets |
|---|
| New users without crypto experience | ✓ | |
| Users with existing wallets (MetaMask, Phantom) | | ✓ |
| Self-custodial requirement | ✓ | ✓ |
| Seamless onboarding UX | ✓ | |
| Power users bringing their own keys | | ✓ |
| Multi-chain support needed | ✓ | ✓ |
When to use wallet actions vs. RPC methods
| Scenario | Use wallet actions | Use RPC methods |
|---|
| Simple transfers or swaps | ✓ | |
| Complex contract interactions | | ✓ |
| Earn/yield operations | ✓ | |
| Custom transaction logic | | ✓ |
| Built-in quote/fee handling | ✓ | |
| Direct signing control | | ✓ |
When to use Privy authentication vs. JWT-based auth
| Scenario | Use Privy auth | Use JWT-based |
|---|
| No existing auth system | ✓ | |
| Already have Auth0, Firebase, Cognito | | ✓ |
| Want email + social + wallet logins | ✓ | |
| Integrating with existing provider | | ✓ |
| Need MFA and passkeys | ✓ | ✓ |
Wallet control models
| Model | Owner | Signers | Use case |
|---|
| User-owned | User | None | Self-custodial consumer wallets |
| User + server | User | Server (scoped) | Automated trading, limit orders |
| App-owned | Authorization key | None | Treasury, trading bots, agents |
| Custodial | Custodian | None | FBO banking-like models |
Workflow
1. Set up a Privy app
- Log into https://dashboard.privy.io
- Create a new app (separate apps for dev/staging/production)
- Navigate to Configuration > App settings > Basics
- Copy your App ID (public) and App Secret (keep secret)
- Store credentials in environment variables:
PRIVY_APP_ID, PRIVY_APP_SECRET
- Configure login methods in Configuration > Login methods if using Privy authentication
- Set up webhooks in Configuration > Webhooks if you need event notifications
2. Initialize Privy in your application
For React/React Native:
- Wrap your app with
<PrivyProvider appId="..." clientId="..." config={{...}}>
- Wait for
usePrivy().ready before consuming Privy state
- Use hooks like
usePrivy(), useWallets(), useCreateWallet() in components
For Node.js/server:
- Import
PrivyClient from @privy-io/node
- Initialize:
const privy = new PrivyClient({appId: '...', appSecret: '...'})
- Use
privy.wallets(), privy.users(), privy.webhooks() methods
3. Implement user authentication
- Choose authentication method (email, social, wallet, passkey, or your own JWT)
- If using Privy auth: configure login methods in dashboard
- If using JWT-based auth: register JWKS endpoint in Configuration > Authentication
- Call
usePrivy().login() (client) or create user via API (server)
- Verify user state with
usePrivy().user (client) or privy.users().get() (server)
4. Create and manage wallets
- Decide wallet ownership: user-owned, app-owned, or custodial
- Create wallet:
useCreateWallet() (React) or privy.wallets().create() (Node.js)
- Specify owner (user ID or authorization key) and chain type (ethereum, solana, etc.)
- Optionally attach policies and signers at creation time
- Retrieve wallet:
useWallets() (React) or privy.wallets().get() (Node.js)
- Store wallet ID for future operations
5. Set up policies and controls
- Define what actions wallets should allow (transfers, swaps, contract calls)
- Create policy in dashboard or via API with rules and conditions
- Specify field sources (transaction fields, calldata, message content)
- Set operators (eq, lt, gt, in, contains, etc.) and values
- Attach policy to wallet at creation or update wallet with policy ID
- Test policy evaluation with sample transactions
6. Implement transaction signing and sending
- For simple transfers: use wallet action API (
transfer())
- For swaps: use wallet action API (
swap()) with quote
- For custom logic: use RPC methods (
eth_sendTransaction, signTransaction, etc.)
- Call signing method with transaction/message data
- Handle user approval flow (embedded UI or custom)
- Monitor transaction status via webhooks or polling
7. Set up webhooks for events
- Create backend endpoint to receive POST requests
- Register endpoint in dashboard: Configuration > Webhooks
- Select event types to subscribe to (user, wallet, transaction, etc.)
- Verify webhook signature using
privy.webhooks().verify() (Node.js)
- Parse payload and handle event (e.g., update database on user creation)
- Return 2xx status code to acknowledge receipt
8. Verify and test
- Check that app ID and secret are correct
- Verify wallet creation with correct owner and chain type
- Test policy evaluation with sample transactions
- Confirm webhook delivery and signature verification
- Test authentication flow end-to-end
- Verify transaction signing and submission on testnet
Common gotchas
- App secret exposure: Never expose
PRIVY_APP_SECRET in client-side code or version control. Use environment variables and keep it server-side only.
- Missing
ready check: Always wait for usePrivy().ready === true before consuming Privy state in React to avoid stale data.
- Policy default deny: If a wallet has a policy, any RPC method not explicitly allowed in the policy will be denied. Include rules for all methods you intend to use.
- Webhook signature verification: Always verify webhook signatures using
privy.webhooks().verify() before trusting the payload. Unverified webhooks are a security risk.
- Rate limiting: API calls are rate-limited. Implement exponential backoff for retries (HTTP 429 responses). Batch operations where possible.
- Idempotency keys: Use idempotency keys for wallet creation and other mutations to prevent duplicate operations if requests are retried.
- Owner vs. signer confusion: Owners have full control and can modify policies; signers have scoped permissions only. Choose the right role for your use case.
- Chain type mismatch: Ensure wallet chain type matches the transaction you're signing (e.g., don't send Ethereum transactions to Solana wallets).
- Policy evaluation timing: Policies are evaluated at request time in secure enclaves. Conditions must match the exact request format (e.g., amounts in wei, not ETH).
- Webhook endpoint must be HTTPS: Webhook URLs must start with
https://. HTTP endpoints will be rejected.
- User key expiration: User keys for signing are time-bound. Request new keys if signing fails with auth errors.
- Missing JWKS endpoint: If using JWT-based auth, ensure your JWKS endpoint is publicly accessible and returns valid keys.
Verification checklist
Before submitting work with Privy:
Resources
Comprehensive navigation: https://docs.privy.io/llms.txt
Critical documentation pages:
For additional documentation and navigation, see: https://docs.privy.io/llms.txt