Privy enables creating self-custodial wallets for your users that can be used from your servers. Privy enforces self-custody of the wallet by requiring a valid access token from the user for any wallet actions, ensuring the user is authenticated in your app. This guarantees that the user must be in the loop for any transaction invoked by your server. At a high-level, you can create self-custodial wallets that can be used from your servers by:
1

Configure authentication settings

Configure the authentication settings from your existing authentication provider in the Privy Dashboard. Privy will use these settings to verify a user’s access token.
2

Create your user

Create a user user in Privy using the user ID from your authentication provider. This user will be assigned as the owner of their wallet.
3

Create a wallet owned by your user

Create a wallet owned by your user using their Privy user ID. When creating the wallet, you can optionally attach policies to the wallet to configure which kinds of transactions can be sent by your user.
4

Request a user key with a user's access token

While your user is authenticated in your app, use your user’s access token to request an ephemeral user key for your user. This key is required to sign requests to execute transactions, ensuring the user stays in the loop for all transactions.
5

Execute transactions from your server

Compute the user key’s signature over your API request and execute transactions from your server.
Follow the guide below for more concrete instructions.

1. Configure authentication settings

Privy ensures that users are in the loop for all wallet actions by requiring a valid access token for your user issued by your authentication provider. This ensures your user is authenticated for all transactions executed by your server. To verify a user’s access token, Privy requires that your app register details of your authentication setup in the Privy Dashboard. Namely:
  1. Get your JWKS.json endpoint from your authentication provider (e.g. Auth0, Firebase, Stytch). Privy will use this endpoint to verify access tokens for your users.
  2. In the Authentication page of the Configuration section of the Privy Dashboard, enable JWT-based authentication.
  3. Once JWT-based authentication has been enabled, register the JWKS.json endpoint from your authentication provider and the name of the JWT claim that specifies the user’s ID (typically sub).
Privy can now verify access tokens issued by your authentication provider to authenticate users, and issue user keys for users.

2. Create your user

Next, create a user in Privy that will own your wallet. Pass the user ID from your authentication provider in the request to associate the user in Privy with the user in your authentication provider.
Use the Privy client’s importUser method to create a user.
const user = await privy.importUser({
    linkedAccounts: [{
        type: 'custom_auth',
        customUserId: 'insert-user-id-from-authentication-provider'
    }]
});

// Save the Privy user ID
const id = user.id;
Make sure to save the id of the returned Privy user for the next step.

3. Create a wallet owned by your user

Next, given your Privy user ID from step 3, create a wallet owned by your user. This ensures that the user is the only party that is allowed to authorize transactions from the wallet.
When creating a wallet, you can also associate policies with the wallet to configure which kinds of transactions are allowed to be sent.
Use the createWallet method of the Privy client’s walletApi class to create a user:
const {id, address} = await privy.walletApi.createWallet({
    chainType: 'ethereum',
    owner: {userId: 'insert-privy-user-id'},
    policyIds: ['insert-any-policy-ids-to-associate-with-wallet']
});
Make sure to save the id of the returned wallet, to allow your server to transact with this wallet in the next step.

4. Request a user key

When your user is authenticated in your application and wants to take action with their wallet, first make a request from your frontend to your server with the user’s access token. You will use this access token to request an ephemeral user key. This key is required to sign requests to the Privy API to ensure that users authorize transactions that are being sent. Next, once your server has the user’s access token, make a request to Privy to get the user key.
To request a user key, use the generateUserSigner method of the Privy client’s walletApi class:
const {authorizationKey} = await privy.walletsApi.generateUserSigner({
    userJwt: 'insert-user-jwt-from-authentication-provider'
});
Next, update the Privy client to use the returned user key using the updateAuthorizationKey method:
await privy.walletApi.updateAuthorizationKey('insert-user-key-from-above');
Your Privy client will now automatically use this user key to sign requests to Privy’s API.

5. Execute transactions from your server

Lastly, execute transactions from your server with the user key. All requests to the Privy API to execute a transaction must be signed by the user key to ensure the user authorizes the transaction. Follow the steps below to sign a request and execute a transaction with the REST API.
You can also enable key export of a user’s wallet with a valid access token from the user.
The Privy client will automatically sign requests to the Privy API with the key you provided in the step above. You can simply use the privy.walletApi.ethereum.* and privy.walletApi.solana.* interfaces to take actions with wallets, and the SDK will automatically sign requests under the hood.