Skip to content

Importing a single user

Privy allows you to import a single user into your Privy app. To import a user, pass a ImportUserInput which includes the user's LinkedAccounts. You can also create a wallet with wallet pregeneration.

When an imported user logs in, all of their imported accounts (wallet, email, etc.) will be included in their user object. If the imported user has a pregenerated embedded wallet, that wallet will be available to the user upon sign in.

If you want to import multiple users at once, you can import users in bulk.

ImportUserInput

When importing a user, you will pass an ImportUserInput object. See the fields on the ImportUserInput object below:

FieldTypeDescription
linkedAccountsLinkedAccount[]An array including all of the user's linked accounts.

These objects are in the same shape as the linked accounts returned by getUser. For each linked account, you must specify the type and must not include a verifiedAt timestamp.
createEthereumWalletboolean(Optional) Whether to pregenerate an embedded Ethereum wallet for the imported user. Defaults to false.
createSolanaWalletboolean(Optional) Whether to pregenerate an embedded Solana wallet for the imported user. Defaults to false.

TIP

Looking for the types of LinkedAccounts?

See a list of the different account types and the data they include

Note:

  • Each account should be a JSON object including all the necessary fields for that account type.
    • Valid account types are apple_oauth, 'custom_auth', 'discord_oauth', 'farcaster', 'github_oauth', 'google_oauth', 'instagram_oauth', 'linkedin_oauth', 'spotify_oauth', 'telegram', 'tiktok_oauth', 'twitter_oauth', 'email', 'phone' and 'wallet'.
  • If importing a user with a custom_auth account, the custom_auth account must be the only element of the linked_accounts array. It is not permitted to import a user with a custom_auth account and other linked_accounts.
  • You must exclude the verifiedAt field.
  • The SDK and REST API have different naming conventions. The SDK uses camelCase and the API uses snake_case.
  CustomJwtAccount
FieldTypeDescription
type'custom_auth'N/A
API: custom_user_id
SDK: customUserId
stringID of user from custom auth provider.
  DiscordAccount
FieldTypeDescription
type'discord_oauth'N/A
subjectstringID of user from Discord user API response.
emailstringEmail of user from Discord user API response
usernamestringUsername of user from Discord user API response. Include the 4-digit discriminator prefixed by '#'.

(See Discord docs)

  EmailAccount
FieldTypeDescription
type'email'N/A
addressstringEmail address of user account.
  FarcasterAccount
FieldTypeDescription
type'farcaster'N/A
fidnumberFID of the user from Farcaster user API response.
API: owner_address
SDK: ownerAddress
stringWallet address of the user from Farcaster user API response. Note that this is the Farcaster wallet address, and not the Privy embedded wallet address.
usernamestring(Optional) Username of user from Farcaster user API response. Do not include the '@'.
API: display_name
SDK: displayName
string(Optional) Display name of user from Farcaster user API response.
biostring(Optional) Bio of user from Farcaster user API response.
API: profile_picture_url
SDK: profilePictureUrl
string(Optional) Profile picture URL of the user from Farcaster user API response. Must be a valid image URL.
API: homepage_url
SDK: homepageUrl
string(Optional) Profile URL of the user from Farcaster user API response.

(See Farcaster docs. Note that the Privy import interface differs slightly from the Farcaster public interface in order to maintain consistency with other Privy LinkedAccount types.)

  GithubAccount
FieldTypeDescription
type'github_oauth'N/A
subjectstringID of user from GitHub user API response.
emailstringEmail of user from GitHub user API response
namestringName of user from GitHub user API response
usernamestringUsername of user from GitHub user API response

(See GitHub docs)

  GoogleAccount
FieldTypeDescription
type'google_oauth'N/A
subjectstringsub pulled from Google-provided JWT with "openid" scope.
emailstringemail from Google-provided JWT with "email" scope.
namestringname from Google-provided JWT with "profile" scope.
  InstagramAccount
FieldTypeDescription
type'instagram_oauth'N/A
subjectstringID of user from Instagram user API response.
username stringThe name displayed on a user's profile from Instagram's /me API response.

(See Instagram docs)

  LinkedinAccount
FieldTypeDescription
type'linkedin_oauth'N/A
subjectstringID of user from LinkedIn user API response.
email stringEmail of user from LinkedIn user API response
namestringName of user from LinkedIn user API response. Do not include the '@'.

(See Linkedin docs)

  PhoneAccount
FieldTypeDescription
type'phone'N/A
numberstringPhone number of user account (non-international numbers default to US).

While number is accepted as input, phoneNumber is returned in the response.

  SpotifyAccount
FieldTypeDescription
type'spotify_oauth'N/A
subjectstringID of user from Spotify user API response.
emailstringEmail of user from Spotify user API.
name stringThe name displayed on a user's profile from Spotify display_name API response.

(See Spotify docs)

  TelegramAccount
FieldTypeDescription
type'telegram'N/A
telegram_user_idstringID of a user's telegram account.
first_name stringThe first name displayed on a user's telegram account.
last_name string(Optional) The last name displayed on a user's telegram account.
username string(Optional) The username displayed on a user's telegram account.
photo_url string(Optional) The url of a user's telegram account profile picture.

(See Telegram docs)

  TwitterAccount
FieldTypeDescription
type'twitter_oauth'N/A
subjectstringID of user from Twitter user API response.
name stringName of user from Twitter user API response
usernamestringUsername of user from Twitter user API response. Do not include the '@'.
API: profile_picture_url
SDK: profilePictureUrl
string(Optional) Profile picture URL of the user from Twitter user API response. Must be a valid image URL.

(See Twitter docs)

  WalletAccount
FieldTypeDescription
type'wallet'N/A
API: chain_type
SDK: chainType
'ethereum'Type of chain for the wallet. EVM chains ('ethereum') and Solana ('solana') are currently supported.
addressstringChecksummed wallet address.

Using @privy-io/server-auth

Use the PrivyClient's importUser method to import a single user into your Privy app.

tsx
const user = await privy.importUser({
  linkedAccounts: [
    {
      type: 'email',
      address: '[email protected]',
    },
  ],
  createEthereumWallet: true,
  createSolanaWallet: true,
});

Using the REST API

Make a POST request to:

sh
https://auth.privy.io/api/v1/users

Below is a sample cURL command for importing a new user into Privy:

bash
$ curl --request POST https://auth.privy.io/api/v1/users \
-u "<your-privy-app-id>:<your-privy-app-secret>" \
-H "privy-app-id: <your-privy-app-id>" \
-H 'Content-Type: application/json' \
-d '{
  "linked_accounts": [
    {
      "subject": "1234567890",
      "username": "batman#1234",
      "email": "[email protected]",
      "type": "discord_oauth"
    },
    {
      "number": "+1 123 456 7890",
      "type": "phone"
    },
    {
      "subject": "1234567890",
      "email": "[email protected]",
      "name": "Bruce Wayne",
      "type": "google_oauth"
    },
    {
      "address": "[email protected]",
      "type": "email"
    },
    {
      "address": "0x3DAF84b3f09A0E2092302F7560888dBc0952b7B7",
      "type": "wallet",
      "chain_type": "ethereum"  # "ethereum" is the only valid value for chain_type
    },
    {
      "subject": "1234567890",
      "username": "batman",
      "name": "Batman",
      "type": "twitter_oauth"
    },
    {
      "subject": "1234567890",
      "username": "joker",
      "name": "Joker",
      "type": "github_oauth",
    }
  ]
}'

A successful response will include the new user object along with their DID. See a sample successful response below:

json
{
	"id": "did:privy:clddy332f002tyqpq3b3lv327",
	"created_at": 1674788927,
	"linked_accounts": [
    {
      "subject": "1234567890",
      "username": "batman#1234",
      "email": "[email protected]",
      "type": "discord_oauth",
      "verified_at": 1674788927
    },
   ...
    {
      "subject": "1234567890",
      "username": "joker",
      "name": "Joker",
      "type": "github_oauth",
      "verified_at": 1674788927
    }
  ]
}

INFO

User import endpoints have heavier rate limit of 240 users in total per minute. If you are being rate limited, responses will have status code 429. We suggest you set up exponential back-offs starting at 1 second to seamlessly recover.

INFO

When a user logs in to your app with Google or Apple OAuth, if there is an existing email account associated with the email address used for Google/Apple OAuth, Privy will automatically authenticate the user into the existing email account. This helps prevent account duplication issues where a single user may have multiple accounts unnecessarily.


When importing users to Privy, Privy will not automatically merge Apple, Google, and email users with the same email address if imported separately. This is to support migrations from authentication systems that do not automatically merge Apple, Google, and email accounts on the basis of email address.


If you'd like to import a Google account and email account to have the same Privy User ID, you must import both accounts in the same linked_accounts array. If you import each account separately, they will have different Privy User IDs.